Ready to Start Your Career?

By: V
July 15, 2016
A Cautionary Tale about PHP Secure Coding Techniques

By: V
July 15, 2016

- a simple math equation
- controlling heavy machinery thousands of miles away
- serving a simple tax form that auto calculates your yearly dues
- creating custom encryption and encoding tools.
- GET
- POST
- COOKIE
- USERAGENT
file.php?website=a ; whoami
Notice that Linux commands can be strung together with semi-colons. The output will show the error from the incomplete whois query, but then show that you are running as most likely Apache or NGINX. Xander would then argue, "Well, but they can't upload a file with that, so I'm safe!"We would then have to show Xander how easy that is.file.php?website=a ; (echo attack code here) > somefile.sh
Xander would then freak, when he saw the sh file appear right in the same folder as his. We would advise Xander, this is nearly as simple to fix as it was to mess up with just a line of code. And show Xander how to limit input to only what is absolutely needed for the script to work. And show him the following re-written version of his PHP code:<?php$website = preg_replace("/[^A-Za-z0-9.-]/", '', $_GET['website']);$cmd = "whois $website";passthru($cmd);?>This simple change didn't even add a line, but it filters the input stripping anything that isn't a letter, number, dash or period - which are the only things domain names contain. Xander then informs us his homepage has code that saves the useragent of visitors to MySQL and that recently he has been getting lots of MySQL syntax errors in the logs from that file, but he's certain that his SQL syntax is perfect. He shows you his code:<?phpinclude("dbconfig.php");$useragent = $_SERVER['HTTP_USER_AGENT'];$ip = $_SERVER['REMOTE_ADDR'];$time = time();$counter = mysql_query("INSERT INTO useragents SET ip = '$ip', time = '$time', useragent = '$useragent' ");?> Xander then says, "There are no inputs from the user, so how can this be exploited?"We then show Xander, how SQLMAP will alter its own useragent to exploit any code that uses the useragent data, just as it does with GET and POST, and we dump a copy of Xanders entire database to his amazement and horror. We then explain that this to is so simple to fix, and NEVER, NEVER, NEVER trust any data coming in from users, no matter where it comes from. We show Xander to fix this, while preserving the format and content as well. we would use thefollowing code:<?phpinclude("dbconfig.php");$useragent = base64_encode($_SERVER['HTTP_USER_AGENT']);$ip = $_SERVER['REMOTE_ADDR'];$time = time();$counter = mysql_query("INSERT INTO useragents SET ip = '$ip', time = '$time', useragent = '$useragent' ");?> We then advise Xander that he must use the appropriate base64_decode function on any pages that display the useragent data.We add that, a good function to put into his main config file at the very top, would be:if(strripos($_SERVER['REQUEST_URI'], "UNION") !== false) {if(strripos($_SERVER['REQUEST_URI'], "SELECT") !== false) {die;}} We explain that some of the most common SQL Injections involve the combination of these two words in the URI, and that this function will terminate execution if they are detected. And furthermore, if he builds the rest of his pages to not use either word in the URIs, he can de-nest the second IF statement from the first and achieve better coverage of possible attempts. These two statements are unnecessary if all of the code is perfectly secured in thefirst place.Xander explains that he never thought about how his code could be used in such strange and unusual ways by an attacker, and that we have opened his eyes to how you must limit the ways the code is able to function, in order to protect it.We add to Xander that he should employ variations of these methods for filtering and protecting not only his GET and Useragent inputs, but his POST and COOKIE inputs as well. And, advise that, just because data is stored in a cookie for your site, doesn't mean the COOKIE isn't forged. Thanks and I hope this tale was helpful.