I'm trying to figure out the best way to sanatize and validate a reCAPTCHA key. The problem is I don't have a lot of information on how they keys are formed. I think the best way may be just to check to see if the string is 40 charicters long and contains letters,numbers,dashes, and underscores. Here's the infomation I have from the documntations.
invalid-site-public-key: Did you make sure to copy the entire key, with all hyphens and underscores, but without any spaces? The key should be exactly 40 letters long. Source
My public key looks like this 6Ler570SAAAAAOfjh3CNFPtuBSH_QdavHc5x_JUv I'm just worried about writing validation that is too strict and won't let some people use the plugin that I'm writing.
This is what I'm using now but not sure if there is a better way.
if( $recaptcha_public_key ) {
//validate the key
$recaptcha_public_key = filter_var($recaptcha_public_key, FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>"/[0-9a-zA-Z_-]{40}/")));
// Update value in database
update_option( 'recaptcha_public_key', $recaptcha_public_key );
}
Thanks!
What you have ("/[0-9a-zA-Z_-]{40}/") is as strict as you're going to get. The point of the key is that it is random - if it conformed to a strict set of formatting rules it would be easy to crack.
Without analyzing a set of public keys, it's fair to assume that each character is completely random within the set [0-9a-zA-Z_-]. Even if this is assumption is incorrect and there is some more specific pattern, this would be likely to change at some point in the future so it's not a good idea to commit your application to the current pattern.
Why are you verifying it yourself? You aren't hitting your database with the information or displaying it on the page are you? If you are putting it on the page html encode it and that should prevent scripts form being run.
You should just send it off to the third party using http://www.google.com/recaptcha/api/verify and it will validate it (as it states in http://code.google.com/apis/recaptcha/docs/verify.html).
This seems to be perfect
if(preg_match('#^6[0-9a-zA-Z_-]{39}$#', $key)){
// Valid key
}
These are the current conditions of the keys:
40 characters
Start with a "6"
Only alphanumeric, underscore and dash
characters
Related
For my application, written in PHP 5+, I have a common.php which is included from all other pages. Within that I have an include sanitize.php which aims to sanitise any input vars used in the URL. So, targetting $_GET[] values.
This is just to have one place where I can tidy any vars, if used, and use them in the code later.
There seems to be no tidy way, I've seen, to sanitise based on expected/desired inputs. The method I initially looked at was this sanitize.php having a foreach to loop through any vars, lookup the type of sanitization required, and then add the cleaned vars to a separate array for use within my code.
Instead of using PHP sanitization filters, to keep it standard, I thought I'd use regex. Types I want are alphaonly, alphanumeric, email, password. Although "password" would allow some special chars, I want to remove or even escape potentially "hazardous" ones like ' " to then be included into a mysql DB. We have a european userbase so different locales are possible, but I'm hoping that won't be too much of an issue.
Would this be a "good" solution to start from, or am I trying to reinvent the wheel?
Random Page
/mypage.php?c=userid&p=lkasjdlakjsdlakj&z=....
(use SANITIZED_SAFE_INPUT_VARS variable only)
sanitize.php
var aryAllowedGetParamNames = array(
"c" => "alphaonly", //login
"p" => "alphaemail", //password
"e" => "email" //email
//...
);
var sanitizeTypes = array (
"alphaonly" => "[a-zA-Z]",
"alphanumeric" => "[a-zA-Z0-9]",
"email" => "[a-zA-Z0-9]...etc"
);
var SANITIZED_SAFE_INPUT_VARS = array();
foreach ($_GET as $key => $value) {
//apply regex and add value to SANITIZED_SAFE_INPUT_VARS
}
EDIT
There seems to be some opinion about the use of passwords in the URL. I'll explain in a little more detail. Instead of using a POST login prompt with username and password, I am using an ajax async call to _db_tryLogin.php with parameters for userid and password. The username is ALWAYS a 6-ALPHA-only text string, and the password is an md5 of what was typed. I'm aware of the opinions on MD5 not being "safe enough".
The JS currently MD5s the password and sends that to the _db_tryLogin.php.
-> async : _db_login.php?c=ABCDEF&p=SLKDauwfLKASFUWPOjkjafkKoAWOIFHF2733287
This will return an async response of "1" or "0". Both will cause the page to refresh, but if the _db_tryLogin.php page detects the password and userid matches one DB record, then session variables are set and the site knows the user is logged in.
I used MD5 for the async request just to quickly hash the password so it's not transmitted in plaintext.
The _db_tryLogin.php takes the password, which is md5(plainpass) adds a SALT and MD5s again, and then this is what is compared against the usertable in the DB.
DB password stored = md5(SALT.md5(plainpass))
I would to start just regex each variable , apply null if it doesn't match the requirements. Either test what it SHOULD have only, or what it shouldn't have, whichever is smaller:
$safeValue = (preg_match('/^[a-zA-Z0-9]{0,5}$/',$value) ? $value : "");
ALONG with prepared statements with parameter input aka
$query = "SELECT x FROM table WHERE id=?";
bind_param("si",$var,$var)
PHP also comes in with built filters, such as email and others). Example: filter_var($data, FILTER_SANITIZE_EMAIL)
http://php.net/manual/en/filter.filters.sanitize.php
What are you sanitising against? If you're [only] trying to protect your SQL database you're doing it wrong, and should be looking into Prepared Statements.
USER SUBMITTED DATA SHOULD NEVER BE TRUSTED. Accepted, yes, trusted - No.
Rather than going through a long tedious process of allowing certain chararacters, simply disallow (ie remove) characters you don't want to accept, such as non-alphanumeric or backtick characters etc. It may also save you a lot of efforts to use the PHP strip_tags() function.
1) Create your function in your include file. I would recommend creating it in an abstract Static Class, but that's a little beyond the scope of this answer.
2) Within this function/class method add your definitions for what bad characters you're looking for, and the data that these checks would apply to. You seem to have a good idea of your logic process, but be aware that there is no definitively correct code answer, as each programmers' needs from a string are different.
3) using the criteria defined in (2) you can then use the Regex to remove non-valid characters to return a "safe" set of variables.
example:
// Remove backtick, single and double quotes from a variable.
// using PCRE Regex.
$data = preg_relace("/[`"']/","",$data);
4) Use the PHP function strip_tags() to do just that and remove HTML and PHP code from a string.
5) For email validation use the PHP $email = filter_var($data, FILTER_SANITIZE_EMAIL); function, it will be far better than your own simple regex. Use PHP Filter Validations they are intended exactly for your sort of situation.
6) NEVER trust the output data, even if it passes all the checks and regexes you can give it, something may still get through. ALWAYS be VERY wary of user submitted data. NEVER trust it.
7) Use Prepared Statements for your SQL interactions.
8) As a shortcut for number types (int / float) you can use PHP type-casting to force a given varibles to being a certain type and destroying any chance of it being anything else:
$number = $_GET['number']; //can be anything.
$number = (int)$_GET['number']; //must be an integer or zero.
Notes:
Passwords should not be a-z only, but should be as many characters as you are able to choose from, the more the better.
If the efforts you are actioning here are for the case of protecting database security and integrity, you're doing it wrong, and should be using Prepared Statements for your MySQL interactions.
Stop using var to declare variables as this is from PHP4 and is VERY old, it is far better to use the Variable preconditional $ (such as $variable = true;) .
You state:
We have a european userbase so different locales are possible
To which I would highly recommend exploring PHP mb_string functions because natively PHP is not mutlibyte safe.
So I'm busy building a site and trying to test out a sort of filter for certain words but trying to determine which is the best function to use and through what language. I've done a bit of research and in PHP I can use the strpos() function so for example:-
if (strpos($checkstring, 'geordie') !== false) {
$checkstring = 'invalid name';
}
I'm unsure as to whether there is a decent JQuery function that could be used to achieve the same thing. Basically I want to be able to block my friends from using my name or nickname so it would include any and all variations of 'geordie' including lowercase and uppercase as well as getting past it using 'GeoRdie' or something to that affect but also want to stop variations which would be my full nickname 'geordie dave' or 'geordie ****' or even 'geordie dave is a ****'.
I realise that this is probably a bit of a complicated one but there must be a way using perhaps an array of names?
Any help on a function to use would be great and if anyone could possibly give me an example of code that could be used would also be beneficial.
You should probably do it in javascript and in php (client side and server side). The javascript eqivalent of strpos is indexOf. If you only check with javscript, someone could forge a post packet and it would still be accepted by the server. If you are only going to check in one place, make it server side, but for user-friendly-ness, both is preferred.
I think that you should also use PHP strtolower function on $checkstring variable.
In JavaScript, you can use String#indexOf(String) to match exact strings, or RegExp#test(String) for more complicated matching.
if (str.indexOf("geordie") !== -1) {
// `str` contains "geordie" *exactly* (doesn't catch "Geordie" or similar)
}
if (/geordie/i.test(str)) {
// `str` contains "geordie", case-insensitive
}
And I'll second what Alfie said: You can't just do this on the client, because client requests can be spoofed. Client-side validation is purely for making a nice user experience; server-side validation is always required.
I'm used to the habit of checking the type of my parameters when writing functions. Is there a reason for or against this? As an example, would it be good practice to keep the string verification in this code or remove it, and why?
function rmstr($string, $remove) {
if (is_string($string) && is_string($remove)) {
return str_replace($remove, '', $string);
}
return '';
}
rmstr('some text', 'text');
There are times when you may expect different parameter types and run different code for them, in which case the verification is essential, but my question is if we should explicitly check for a type and avoid an error.
Yes, it's fine. However, php is not strongly typed to begin with, so I think this is not very useful in practice.
Additionally, if one uses an object other than string, an exception is a more informative; therefore, I'd try to avoid just returning an empty string at the end, because it's not semantically explaining that calling rmstr(array, object) returns an empty string.
My opinion is that you should perform such verification if you are accepting input from the user. If those strings were not accepted from the user or are sanitized input from the user, then doing verification there is excessive.
As for me, type checking actual to data, getted from user on top level of abstraction, but after that, when You call most of your functions you already should now their type, and don't check it out in every method. It affects performance and readability.
Note: you can add info, which types is allowed to arguments for your functions by phpDoc
It seems local folks understood this question as "Should you verify parameters" where it was "Should you verify parameter types", and made nonsense answers and comments out of it.
Personally I am never checking operand types and never experienced any trouble of it.
It depends which code you produce. If it's actually production code, you should ensure that your function is working properly under any circumstances. This includes checking that parameters contain the data you expect. Otherwise throw an exception or have another form of error handling (which your example is totally missing).
If it's not for production use and you don't need to code defensively, you can ignore anything and follow the garbage-in-garbage-out principle (or the three shit principle: code shit, process shit, get shit).
In the end it is all about matching expectations: If you don't need your function to work properly, you don't need to code it properly. If you are actually relying on your code to work precisely, you even need to validate input data per each unit (function, class).
I'm trying to work with decimal data in my PHP and MySql practice and I'm not sure about how can I do for an acceptable level af accuracy.
I've wrote a simple function which recives my input text value and converts it to a decimal number ready to be stored in the database.
<?php
function unit ($value, $decimal_point = 2) {
return number_format (str_replace (",", ".", strip_tags (trim ($value))), $decimal_point);
}
?>
I've resolved something like AbdlBsF5%?nl with some jQuery code for replace and some regex to keep only numbers, dots and commas.
In some country, people uses the comma , to send decimal numbers, so a number like 72.08 is wrote like 72,08. I'd like avoid to forcing people to change their usual chars and I've decided to use a jQuery to keep this too.
Now every web developer knows the last validation must be handled by the dynamic page for security reasons.
So my answer is should I use something like unit (); function to store data or should I also check if users inserts invalid chars like letters or something else? If I try this and send letters, the query works without save the invalid data, I think this isn't bad, but I could easily be wrong because I'm a rookie.
What kind of method should I use for my query if I want a number like 99999.99?
don't forget to consider formatting also DATABASE values with something like FLOAT(10,2)
IMHO this is also very important!
then, of course use server side language for make real validation is the best practice!
you can read this:
http://php.net/manual/en/function.number-format.php
javascript can be fancy and handy but not secure although!
I'm doing something like the following:
SELECT * FROM table WHERE user='$user';
$myrow = fetchRow() // previously I inserted a pass to the db using base64_encode ex: WRM2gt3R=
$somepass = base64_encode($_POST['password']);
if($myrow[1] != $somepass) echo 'error';
else echo 'welcome';
Im always getting error, I even echo $somepass and $myrow[1] they are the same, but still error. What Am I doing wrong? Thanks
Try using var_dump instead of echo - maybe one of them has a space or newline at the start/end.
Edit:
You must be storing it as CHAR(40): A fixed-length string that is always right-padded with spaces to the specified length when stored
Use VARCHAR or trim()
If $myrow[1] is actually the correct password in base64-encoding, I don't see any errors.
Try this ind the end:
echo "<br />$myrow[1] != $somepass";
What does it say?
And by the way: I don't see any reason to base64-encode the passwords. What are you trying to accomplish?
I think somehow if I do a var_dump() I get:
string(40) "YWRraM2= "
string(8) "YWRraM2="
seems like somehow if I insert the data into the db using the console its adding an extra space to the pass field.
myplacedk: is there any reason why I should not be doing it? I thought it will add an extra leyer of security?
This encoding does two things:
It adds code, making it more complex and easier to make errors
If you view your database on your screen, and someone looks over your shoulder, the passwords may be a bit harder to remember.
So no, it doesn't really add any security. It's just an encoding, it's easy to decode.
Maybe you are mistaking it for md5-hashing or something like that.
Playing around is great, but when it comes to security, I really recommend not using something you don't understand. In the long run, it will do more damage than good.
Some issues:
From your comments elsewhere, I guess that the problem with the current code is that your database field is CHAR(40). A CHAR field always has a fixed size. Try changing the database field type to VARCHAR instead of CHAR.
Using base64_encode before storing in a database is nowhere near secure. Good practice is storing only a one-way hash of the password in the database -- typically md5 or (better) sha1. Then, when the user wants to log in, use the same hash-function on the provided password, and then compare the two hashes.
This has the added benefit of working with passwords longer than 40 characters too.
A sha1 or md5-hash always takes a fixed amount of space, so if you go this route, you don't have to switch your database column to VARCHAR :)