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!
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.
I have following code:
<?php
$param = $_GET['param'];
echo $param;
?>
when I use it like:
mysite.com/test.php?param=2+2
or
mysite.com/test.php?param="2+2"
it prints
2 2
not
4
I tried also eval - neither worked
+ is encoded as a space in query strings. To have an actual addition sign in your string, you should use %2B.
However, it should be noted this will not perform the actual addition. I do not believe it is possible to perform actual addition inside the query string.
Now. I would like to stress to avoid using eval as if it's your answer, you're asking the wrong question. It's a very dangerous piece of work. It can create more problems than it's worth, as per the manual specifications on this function:
The eval() language construct is very dangerous because it allows
execution of arbitrary PHP code. Its use thus is discouraged. If you
have carefully verified that there is no other option than to use this
construct, pay special attention not to pass any user provided data
into it without properly validating it beforehand.
So, everything that you wish to pass into eval should be screened against a very.. Very strict criteria, stripping out other function calls and other possible malicious calls & ensure that 100% that what you are passing into eval is exactly as you need it. No more, no less.
A very basic scenario for your problem would be:
if (!isset($_GET['Param'])){
$Append = urlencode("2+2");
header("Location: index.php?Param=".$Append);
}
$Code_To_Eval = '$Result = '.$_GET['Param'].';';
eval($Code_To_Eval);
echo $Result;
The first lines 1 through to 4 are only showing how to correctly pass a character such a plus symbol, the other lines of code are working with the data string. & as #andreiP stated:
Unless I'm not mistaking the "+" is used for URL encoding, so it would
be translated to a %, which further translates to a white space.
That's why you're getting 2 2
This is correct. It explains why you are getting your current output & please note using:
echo urldecode($_GET['Param']);
after encoding it will bring you back to your original output to which you want to avoid.
I would highly suggest looking into an alternative before using what i've posted
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
I am always thinking about validation in any kind on the webpage (PHP or ASP, it doesn't matter), but never find a good and accurate answer.
For example, a I have some GET-Parameter, which defines a SQL query like DESC oder ASC. (SQL-Injection?)
Or I have a comment-function for user, where the data is also saved in a database.
Is it enought to check for HTML-tags inside the data? Should the validation done before adding it to the database or showing it on the page?
I am searching for the ToDo's which should be always performed with any data given from "outside".
Thanks.
Have a good idea of what you want from the user.
You want them to specify ascending/descending order? That's an enumeration (or a boolean), not part of an SQL query:
$query = "SELECT [...] ORDER BY field " . escape($_GET['sortOrder']); //wrong
This is wrong no matter how much you escape and sanitize their string, because this is not the way to validate an enumeration. Compare:
if ($_GET['sortOrder'] == 'desc') {
$ascending = false;
} else {
$ascending = true;
}
if ($ascending) {
...
} else {
...
}
...which does not warrant a discussion of string escaping or SQL injection because all you want from the user is a yes/no (or ascending/descending) answer.
You want them to enter a comment? Why disallow HTML tags? What if the user wants to enter HTML code?
Again, what you want from them is, say, "a text... any text with a maximum length of 1024 characters*." What does this have to do with SQL or injection? Nothing:
$text = $_POST['commentText'];
if (mb_strlen($text, ENCODING) <= 1024) {
//valid!
}
The value in the database should reflect what the user entered verbatim; not translated, not escaped. Say you're stripping all HTML <tags> from the comment. What happens when you decide to send comments somewhere in JSON format? Do you strip JSON control characters as well? What about some other format? What happens if HTML introduces a tag called ":)"? Do you go around in your database stripping off smileys from all comments?
The answer is no, as you don't want HTML-safe, JSON-safe, some-weird-format-with-smileys-safe input from the user. You want text that is at maximum 1024 characters. Check for that. Store that.
Now, the displaying part is trickier. In order to display:
<b>I like HTML "tags"
in HTML, you need to write something like:
<b>I like HTML "tags"
In JSON, you would do:
{ "I like HTML \"tags\" }
That is why you should use your language facilities to escape the data when you're using it.
The same of course goes for SQL, which is why you should escape the data when using simple query functions like mysql_query() in PHP. (Parametrized queries, which you should really be using, on the other hand, need no escaping.)
Summary
Have a really good idea of what you want as the input, keeping in mind that you almost never need, say, "HTML-safe text." Validate against that. Escape when required, meaning escape HTML as you send to the browser, SQL as you send to the database, and so on.
*: You should also define what a "character" means here. UTF-8, for example, may use multiple bytes to encode a code point. Does "character" mean "byte" or "Unicode code point"?
If you're using PDO, be sure to use prepared statements - these clean the incoming data automatically.
If using the mysql_* functions, run each variable through mysql_real_escape_string first.
You can also do validation such as making sure the variable is one of an acceptable range:
$allowed_values = array('name', 'date', 'last_login')
if(in_array($v, $allowed_values)) {
// now we can use the variable
}
You are talking about two kinds of data sanitation. One is about putting user-generated data in your database and the other is about putting user-generated data on your webpage. For the former you should follow adam's suggestions. For the later you should look into htmlspecialchars.
Do not mix these two as they do two completely different things. For that purpose sanitation should only take place at the last moment. Use adam's suggestion just before updating the database. Use htmlspecialchars just before echoing data. Do not use htmlspecialchars on data before adding it to the database.
You might also want to look around Stackoverflow, because this sort of question has been asked and answered countless times in the past.
Is this enough?
$listing = mysql_real_escape_string(htmlspecialchars($_POST['listing']));
Depends - if you are expecting text, it's just fine, although you shouldn't put the htmlspecialchars in input. Do it in output.
You might want to read this: What's the best method for sanitizing user input with PHP?
you can use php function : filter_var()
a good tutorial in the link :
http://www.phpro.org/tutorials/Filtering-Data-with-PHP.html
example to sanitize integer :
To sanitize an Integer is simple with the FILTER_SANITIZE_INT filter. This filter strips out all characters except for digits and . + -
It is simple to use and we no longer need to boggle our minds with regular expressions.
<?php
/*** an integer ***/
$int = "abc40def+;2";
/*** sanitize the integer ***/
echo filter_var($int, FILTER_SANITIZE_NUMBER_INT);
?>
The above code produces an output of 40+2 as the none INT values, as specified by the filter, have been removed
See:
Best way to stop SQL Injection in PHP
What are the best practices for avoid xss attacks in a PHP site
And sanitise data immediately before it is used in the context it needs to be made safe for. (e.g. don't run htmlspecialchars until you are about to output HTML, you might need the unedited data before then (such as if you ever decide to send content from the database by email)).
Yes. However, you shouldn't use htmlspecialchars on input. Only on output, when you print it.
This is because, it's not certain that the output will always be through html. It could be through a terminal, so it could confuse users if weird codes suddenly show up.
It depends on what you want to achieve. Your version prevents (probably) all SQL injections and strips out HTML (more exactly: Prevents it from being interpreted when sent to the browser). You could (and probably should) apply the htmlspecialchars() on output, not input. Maybe some time in the future you want to allow simple things like <b>.
But there's more to sanitizing, e.g. if you expect an Email Address you could verify that it's indeed an email address.
As has been said don't use htmlspecialchars on input only output. Another thing to take into consideration is ensuring the input is as expected. For instance if you're expecting a number use is_numeric() or if you're expecting a string to only be of a certain size or at least a certain size check for this. This way you can then alert users to any errors they have made in their input.
What if your listing variable is an array ?
You should sanitize this variable recursively.
Edit:
Actually, with this technique you can avoid SQL injections but you can't avoid XSS.
In order to sanitize "unreliable" string, i usually combine strip_tags and html_entity_decode.
This way, i avoid all code injection, even if characters are encoded in a Ł way.
$cleaned_string = strip_tags( html_entity_decode( $var, ENT_QUOTES, 'UTF-8' ) );
Then, you have to build a recursive function which call the previous functions and walks through multi-dimensional arrays.
In the end, when you want to use a variable into an SQL statement, you can use the DBMS-specific (or PDO's) escaping function.
$var_used_with_mysql = mysql_real_escape_string( $cleaned_string );
In addition to sanitizing the data you should also validate it. Like checking for numbers after you ask for an age. Or making sure that a email address is valid. Besides for the security benefit you can also notify your users about problems with their input.
I would assume it is almost impossible to make an SQL injection if the input is definitely a number or definitely an email address so there is an added level of safety.