What is most efficient method to making sure that get/post parameters won't provide any security vulnerability.
I am familior of htmlentities for javascript code injection prevention
and addslashes to prevent sql injection.
so.. for now i'm using them both on each get/post parameter.
are there any other functions i can use to prevent these vulnerabilities better or are there any other security issues that i should worry about related to my php code ?
htmlentities (or htmlspecialchars) and addslashes (or mysql_real_escape_string or other database-appropriate escaping function; addslashes is invariably the wrong thing) are nothing to do with GET/POST parameters. They are outgoing-escaping functions whose input might come from parameters, but might equally come from somewhere else, such as a static string or a string fetched from the database.
for now i'm using them both on each get/post parameter.
No, that doesn't work. It's a common mistake, and one perpetuated by a lot of the totally dreadful PHP tutorial material out there. Trying to split off the problem of string escaping into one little loop instead of being spread all over the code sounds nice, but string escaping doesn't work like that in reality. You need to apply the right form of escaping, and only the right form of escaping, at each time you put a string inside another string. You cannot do that in advance.
Don't try to ‘sanitise’ or ‘filter’ all the incoming parameters to encode or remove characters like \ or <. This will result in your application filling up with rubbish like \\\\\\\\\\\\\\\\\\\\\\\\\\ and &amp;amp;amp;amp;amp;. Instead, you should only encode them — along with any other varaibles that don't come from GET/POST — at the last minute when spitting them into a different context of text, like htmlspecialchars for HTML or mysql_real_escape_string for MySQL string literals. You are usually better off with parameterised queries though, which avoids the SQL escaping issues.
That's not to say you shouldn't check your incoming data for conformance to your application's requirements. If you've got a field you expect to get an integer for, be sure to intval it before using it. If you've got a plain single-line text string which you don't expect to contain newlines, be sure to filter the \n character from the string, along with all other control characters [\x00-\x1F\x7F]. But these are application requirements, not something you can necessarily run across all your input.
GET and POST variables are no more dangerous than any other variables. You should handle injection vulnerabilities at the usage point, not at the input point. See my answer here:
What’s the best method for sanitizing user input with PHP?
You can use Data Filtering as a data firewall.
http://www.php.net/filter
GET/POST are public so the main security concern is to not pass sensitive information (i.e. keys and values that give away your directory structure or db schema). Also remember that anyone can manipulate or create their own HTTP requests so be sure to validate data before inserting it into a database. Other than that they don't pose any threats on their own since they have no effects until you do something with them.
If you are looking for a simple and fast solution, that prevents general security vulnerabilities, I could name the following functions.
htmlentities() , strip_tags() and addSlashes() if get_magic_quotes_gpc() returns FALSE
On the other hand, if you'd like to tighten up your security , check the Data Filtering, mentioned by Kristoffer BOhmann
There are already many good answers, as a rule of thumb you should:
turn off magic_quotes_gpc
validate get/post parameters
html encode parameters before display
use the escape function of the database in queries
This is just the minimum that will prevent the most common vulnerabilities.
This is an example of how to use Addslashes Or Mysql_real_escape_string(): http://zacklive.com/addslashes-or-mysql-real-escape-string-stop-sql-injection/906/
Related
i reading about php security these days and i'm dizzy, please explain clear!
i know i should use strip_tags() or htmlentities() for XSS attacks. but if i need some where html tags, same as blog post, what should i do!?
but where should i use mysql_real_escape_string() and add_magic_quotes()?
are these same?
an other question is, should i use mysql_real_escape_string() for every SQL query? (INSERT, UPDATE,SELECT, DELETE, etc.)? can this function has bad effect on my data (for example, on a blog post that has html tags or ', "")?
i know i should use strip_tags() or htmlentities() for XSS attacks. but if i need some where html tags, same as blog post, what should i do!?
If you don't trust the users, then parse the HTML, run all the elements and attributes through a whitelister, then serialise the document back to HTML.
but where should i use mysql_real_escape_string() and add_magic_quotes()? are these same?
They aren't the same, and you should, generally speaking, avoid them. Use bound parameters instead.
an other question is, should i use mysql_real_escape_string() for every SQL query?
You should escape all user input before passing it to a dabtas.
Forget about magic_quotes. It was a lazy way to automatically escape certain control characters found within user input. Continue learning about newer and more efficient methods to filter/sanitize user input and you'll discover why magic_quotes has been deprecated.
can this function has bad effect on my data (for example, on a blog
post that has html tags or ', "")?
You shouldn't have any problems because the data isn't stored in the database with the extra slashes. If it is, there's a good chance magic_quotes is enabled and needs to be turned off.
should i use mysql_real_escape_string() for every SQL query?
User input needs to be filtered/sanitized before using it to make a query. Use that function, or prepared statements.
If you need to allow HTML within a blog post, you should whitelist tags and attributes, but you should not attempt this yourself. Instead, use HTMLPurifier. Use if before storing in the database as it is heavy and slow, but very safe.
http://htmlpurifier.org/
Magic quotes should not be used at all. Ever. mysql_real_escape_string() should be used on every single argument provided in the query. It is all that is needed to prevent SQL injections. Of course, making sure the connection expects the character encoding you are actually sending is a prerequisite.
The idea of a generic sanitation function is a broken concept.
There is one right sanitation method for every purpose. Running a generic sanitation method on a string will often break it - escaping a piece of HTML code for a SQL query will break it for use in a web page, and vice versa. Sanitation should be applied right before using the data:
mysql_real_escape_string() for functional mysql_* calls (or parametrized queries)
htmlspecialchars() for safe HTML output
preg_quote() for use in a regular expression
escapeshellarg() / escapeshellcmd() for use in an external command
etc. etc.
Using a "one size fits all" sanitation function is like using five kinds of highly toxic insecticide on a plant that can by definition only contain one kind of bug - only to find out that your plants are infested by a sixth kind, on which none of the insecticides work.
Always use that one right method, ideally straight before passing the data to the function. Never mix methods unless you need to.
I am using mysql_real_escape_string to save content in my mySQL database. The content I save is HTML through a form. I delete and re-upload the PHP file that writes in DB when I need it.
To display correctly my HTML input I use stripslashes()
In other case, when I insert it without mysql_real_escape_string, I do not use stripslashes() on the output.
What is your opinion? Does stripslashes affect performance badly ?
Do not use stripslashes(). It is utterly useless in terms of security, and there's no added benefit. This practice came from the dark ages of "magic quotes", a thing of the past that has been eliminated in the next PHP version.
Instead, only filter input:
string: mysql_real_escape_string($data)
integers: (int)$data
floats: (float)$data
boolean: isset($data) && $data
The output is a different matter. If you are storing HTML, you need to filter HTML against javascript.
Edit: If you have to do stripslashes() for the output to look correctly, than most probably you have magic quotes turned on. Some CMS even made the grave mistake to do their own magic quotes (eg: Wordpress). Always filter as I advised above, turn off magic quotes, and you should be fine.
Do not think about performance, think about security. Use mysql_real_escape_string everytime you're inserting data into DB
No, don't escape it. Use prepared statements instead. Store your data in its raw format, and process it as necessary for display - for example, use a suitable method to prevent Javascript from executing when displaying user supplied HTML.
See Bill Karwin's Sql Injection Myths and Fallacies talk and slides for more information on this subject.
See HTML Purifier and htmlspecialchars for a couple of approaches to filter your HTML for output.
Check out a database abstraction library that does all this and more for you automatically, such as ADOdb at http://adodb.sourceforge.net/
It addresses a lot of the concerns others have brought up such as security / parameterization. I doubt any performance saved is worth the developer hassle to do all this manually every query, or the security practices sacrificed.
It is always best to scrub your data for potential malicious or overlooked special characters which might throw errors or corrupt your database.
Per PHP docs, it even says "If this function is not used to escape data, the query is vulnerable to SQL Injection Attacks."
I'm using PHP 5 with SQLite 3 class and I'm wondering if using PHP built-in data filtering function with the flag FILTER_SANITIZE_STRING is enough to stop SQL injection and XSS attacks.
I know I can go grab a large ugly PHP class to filter everything but I like to keep my code as clean and as short as possible.
Please advise.
The SQLite3 class allows you to prepare statements and bind values to them. That would be the correct tool for your database queries.
As for XSS, well that is entirely unrelated to your use of SQLite.
It's never wise to use the same sanitization function for both XSS and SQLI. For XSS you can use htmlentities to filter user input before output to HTML. For SQLI on SQLite you can either use prepared statements (which is better) or use escapeString to filter user input before constructing SQL queries with them.
If you don't trust your own understanding of the security issues enough to need to ask this question, how can you trust someone here to give you a good answer?
If you go down the path of stripping out unwanted characters sooner or later you're going to be stripping out characters that users want to type. It's better to encode for the specific context that the data is used.
Check out OWASP ESAPI, it contains plenty of encoding functions. If you don't want to pull in that big of a library, check out what the functions do and copy the relevant parts to your codebase.
If you are just trying to build a simple form and dont want to introduce any heavy or even light frameworks, then go with php filters + and use PDO for the database. This should protect you from everything but cross site request forgeries.
FILTER_SANITIZE_STRING will remove HTML tags not special characters like &. If you want to convert a special character to entity code prevent malicious users to do anything.
filter_input(INPUT_GET, 'input_name', FILTER_SANITIZE_SPECIAL_CHARS);
OR
filter_input($var_name, FILTER_SANITIZE_SPECIAL_CHARS);
If you want to encode everything it's worth using for
FILTER_SANITIZE_ENCODED
For more info:
https://www.php.net/manual/en/function.filter-var.php
I think its good enough to secure your string data inputs, but there are many other options available which you can choose. e.g. other libraries would increase your application process time but will help you to process/parse other types of data.
On my website I have a variable called $user_data that contains input from a form. I then show this variable on the user page (via echo).
What is the best method to avoid any security risks with this variable? I use strip_tags(), but it is not enough.
This variable also gets saved to a MySQL database.
There are two very important things you must do to avoid serious security problems.
You need to escape the user input before putting it in your SQL query. Escaping means escape all the special characters such as '; luckily, there is a function that already does it automatically: mysql_real_escape_string.
If you don't escape user input nasty things could happen. Imagine that your query is INSERT INTO userdata VALUES ('$user_data'). Now imagine that the user wrote '; DROP DATABASE userdata;.
If you don't escape it, your query will become: INSERT INTO userdata VALUES (''; DROP DATABASE userdata;'). As you can imagine this is not good: if you have multi statements enabled you can kiss goodbye to your database. This is called an SQL Injection attack.
When you are outputting your variable to the user you also need to properly replace HTML special characters with HTML entities. Luckily, there is a function to do that too: htmlspecialchars(). It will transform the special HTML characters such as < to <.
This seems to be a problem that is often underestimated, but in reality it's very serious. Imagine if $user_data contains <script>SomeNastyScript()</script>. It could exploit existing vulnerabilities in the browser of your users, or it could send a non-HTTPOnly cookie (that may contain saved passwords) to the attacker, or it could trick the user into writing their password on a form generated through the manipulation of the DOM (possible in javascript), or a lot of other bad things.
This is called XSS (Cross-site scripting).
Short version
Call mysql_real_escape_string on the string before inserting it into your SQL query (but not when you echo it).
Call htmlspecialchars on the string before displaying it to the user (but not when you put it in the database).
When you're going to output something, strip_tags or htmlspecialchars is fine. I prefer the latter, since you then don't totally destroy <3 and the like that were never meant as HTML tags anyway.
When putting a value directly into a query, mysql_real_escape_string is the appropriate way to escape, or just using PDO and prepared statements.
Of course, it's best to do these escape methods only when you're about to need them, rather than applying both to all variables ever. It's always a pain to have to strip the slashes back out of a MySQL-escaped variable if you want to actually work with it before putting it into the database, and that's no better than PHP4's magic quotes. Similarly, you don't want to turn someone's password of "one<two" into "one<two" before inserting it into the database. (Obviously, you shouldn't be storing plaintext passwords, but the generic example stands.)
There is not a thing called "secureness".
No way to just secure an abstract variable. Everything depends on the scenario.
A condoms commonly used for safety. Would you secure your money with a condom? I suppose - no.
Same here.
You'd better distinguish these 2 matters - a database security and displaying security.
Database one is little more complicated than just "Call mysql_real_escape_string". I've described all the rules comprehensively in this answer
You can also do this:
$way = preg_replace('#[^a-z0-9]#i', '',
strip_tags(htmlentities(htmlspecialchars(mysqli_escape_string($db_conx, $_GET['way'])))));
I am building a new web-app, LAMP environment... I am wondering if preg_match can be trusted for user's input validation (+ prepared stmt, of course) for all the text-based fields (aka not HTML fields; phone, name, surname, etc..).
For example, for a classic 'email field', if I check the input like:
$email_pattern = "/^([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)" .
"|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}" .
"|[0-9]{1,3})(\]?)$/";
$email = $_POST['email'];
if(preg_match($email_pattern, $email)){
//go on, prepare stmt, execute, etc...
}else{
//email not valid! do nothing except warn the user
}
can I sleep easy against the SQL/XXS injection?
I write the regexp to be the more restrictive as they can.
EDIT: as already said, I do use prepared statements already, and this behavior is just for text-based fields (like phone, emails, name, surname, etc..), so nothing that is allowed to contain HTML (for HTML fields, I use HTMLpurifier).
Actually, my mission is to let pass the input value only if it match my regexp-white-list; else, return it back to the user.
p.s:: I am looking for something without mysql_real_escape_strings; probably the project will switch to Postgresql in the next future, so need a validation method that is cross-database ;)
Whether or not a regular expression suffices for filtering depends on the regular expression. If you're going to use the value in SQL statements, the regular expression must in some way disallow ' and ". If you want to use the value in HTML output and are afraid of XSS, you'll have to make sure your regex doesn't allow <, > and ".
Still, as has been repeatedly said, you do not want to rely on regular expressions, and please by the love of $deity, don't! Use mysql_real_escape_string() or prepared statements for your SQL statements, and htmlspecialchars() for your values when printed in HTML context.
Pick the sanitising function according to its context. As a general rule of thumb, it knows better than you what is and what isn't dangerous.
Edit, to accomodate for your edit:
Database
Prepared statements == mysql_real_escape_string() on every value to put in. Essentially exactly the same thing, short of having a performance boost in the prepared statements variant, and being unable to accidentally forget using the function on one of the values. Prepared statement are what's securing you against SQL injection, rather than the regex, though. Your regex could be anything and it would make no difference to the prepared statement.
You cannot and should not try to use regexes to accodomate for 'cross-database' architecture. Again, typically the system knows better what is and isn't dangerous for it than you do. Prepared statements are good and if those are compatible with the change, then you can sleep easy. Without regexes.
If they're not and you must, use an abstraction layer to your database, something like a custom $db->escape() which in your MySQL architecture maps to mysql_real_escape_string() and in your PostgreSQL architecture maps to a respective method for PostgreSQL (I don't know which that would be off-hand, sorry, I haven't worked with PostgreSQL).
HTML
HTML Purifier is a good way to sanitise your HTML output (providing you use it in whitelist mode, which is the setting it ships with), but you should only use that on things where you absolutely need to preserve HTML, since calling a purify() is quite costly, since it parses the whole thing and manipulates it in ways aiming for thoroughness and via a powerful set of rules. So, if you don't need HTML to be preserved, you'll want to use htmlspecialchars(). But then, again, at this point, your regular expressions would have nothing to do with your escaping, and could be anything.
Security sidenote
Actually, my mission is to let pass
the input value only if it match my
regexp-white-list; else, return it
back to the user.
This may not be true for your scenario, but just as general information: The philosophy of 'returning bad input back to the user' runs risk of opening you to reflected XSS attacks. The user is not always the attacker, so when returning things to the user, make sure you escape it all the same. Just something to keep in mind.
For SQL injection, you should always use proper escaping like mysql_real_escape_string. The best is to use prepared statements (or even an ORM) to prevent omissions.
You already did those.
The rest depends on your application's logic. You may filter HTML along with validation because you need correct information, but I don't do validation to protect from XSS, I only do business validation*.
General rule is "filter/validate input, escape output". So I escape what I display (or transmit to third-party) to prevent HTML tags, not what I record.
* Still, a person's name or email address shouldn't contain < >
Validation is to do with making input data conform to the expected values for your particular application.
Injections are to do with taking a raw text string and putting it into a different context without suitable Escaping.
They are two completely separate issues that need to be looked at separately, at different stages. Validation needs to be done when input is read (typically at the start of the script); escaping needs to be done at the instant you insert text into a context like an SQL string literal, HTML page, or any other context where some characters have out-of-band meanings.
You shouldn't conflate these two processes and you can't handle the two issues at the same time. The word ‘sanitization’ implies a mixture of both, and as such is immediately suspect in itself. Inputs should not be ‘sanitized’, they should be validated as appropriate for the application's specific needs. Later on, if they are dumped into an HTML page, they should be HTML-escaped on the way out.
It's a common mistake to run SQL- or HTML-escaping across all the user input at the start of the script. Even ‘security’-focused tutorials (written by fools) often advise doing this. The result is invariably a big mess — and sometimes still vulnerable too.
With the example of a phone number field, whilst ensuring that a string contains only numbers will certainly also guarantee that it could not be used for HTML-injection, that's a side-effect which you should not rely on. The input stage should only need to know about telephone numbers, and not which characters are special in HTML. The HTML template output stage should only know that it has a string (and thus should always call htmlspecialchars() on it), without having to have the knowledge that it contains only numbers.
Incidentally, that's a really bad e-mail validation regex. Regex isn't a great tool for e-mail validation anyway; to do it properly is absurdly difficult, but this one will reject a great many perfectly valid addresses, including any with + in the username, any in .museum or .travel or any of the IDNA domains. It's best to be liberal with e-mail addresses.
NO.
NOOOO.
NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.
DO. NOT. USE. REGEX. FOR. THIS. EVER.
RegEx to Detect SQL Injection
Java - escape string to prevent SQL injection
You still want to escape the data before inserting it into a database. Although validating the user input is a smart thing to do the best protection against SQL injections are prepared statements (which automatically escape data) or escaping it using the database's native escaping functionality.
There is the php function mysql_real_escape_string(), which I believe you should use before submitting into a mysql database to be safe. (Also, it is easier to read.)
If you are good with regular expression : yes.
But reading your email validation regexp, I'd have to answer no.
The best is to use filter functions to get the user inputs relatively safely and get your php up to date in case something broken is found in these functions.
When you have your raw input, you have to add some things depending on what you do with these data : remove \n and \r for email and http headers, remove html tags to display to users, use parameterized queries to use it with a database.