I am gonna give you some ideas for writing secure codes for general coding flaws in PHP. Most of the time, the programmers forget to sanitize the user input in their PHP code & hence, the code becomes vulnerable to some of the common exploits like file inclusion vulnerabilities, SQL injection, XSS & others… So I am here to give you ideas on preventing these simple vulnerabilities from your PHP code…
FILE INCLUSION : File inclusion vulns like RFI(remote) & LFI(local) are exploited by including another file(other than intended by programmer) & this is damn devastating as we can completely rm the box if we escalate privilege with PoC exploits… Anyway let me show the vulnerable code for it…
$page = $_GET[‘page’];
if (isset($page)) #checks if the $page variable page is set or not
{
include($page); #includes the page without checking if it is legitimate or not…
}
?>
I’ve seen many programmers writing the same code esp. Nepali PHP coders & it leads to unexpected result… So any malicious user can include some evil files to r00t the box & you are own3d…
Also many programmers think that they can patch this vuln with the following snippet(based on real example from one of the ISPs)
$venpage = $_GET[‘page’];
$venpage = $venpage . “.php”;
if (IsSet($venpage))
{
include($venpage);
}
?>
This seems to work… aha but still it has got a hole… NULLBYTES – – ? Oh hacked but I secured it lol… Did you??? No, you didn’t…
So let me talk about securing it… The switch is the perfect and simplest method to secure this whole code…
$page = $_GET[‘page’];
if(isset($page)) #check if there’s page variable set or not
{
switch($page)
{
case “info”:
include(“info.php”);
break;
case “about”:
include(“about.php”);
break;
default:
include(“index.php”);
break;
}
}
?>
The above written code is simple yet secured… So why not use it… Damn perfect…
Another method though I don’t use it much is:
//ERROR_REPORTING(E_ALL);
if (IsSet($_GET[‘page’]))
{
$page=$_GET[‘page’];
$page=preg_replace(‘/[^a-z]+/i’,”,$page);
include $page.”.php”;
}
else
{
echo “No page set”;
}
?>
this also should work fine though as already stated I don’t use this one… Its a regular expression method…
SQL INJECTION: SQL injections are one of the most prevalent web vulns in the websites and they can be very harmful esp. for the commercial sites… But still many sites still remain vulnerable to the SQL injection. & again the problem is again the lack of sanitization of GET/POST variables or any other inputs from users… To avoid SQL injection, you need to be as hard as you can. Don’t allow any other data types where you assume to be integer types. Don’t allow something that is not what you wanted to be accepted by your code. Be as strict as you can for the datatypes.
Now let me show you the simplest form of the vulnerability.
//configurations for mysql connection
$host = “localhost”;
$user = “root”;
$pass = “w000000t”;
$db = “db_shop”;
//connecting to mysql
mysql_connect($host, $user, $pass);
mysql_select_db($db);
$uid = $_GET[‘uid’];
if (isset($uid))
{
$query = mysql_query(“SELECT * FROM `profile` WHERE `uid` = $uid”);
if ($query)
{
while($profile = mysql_fetch_array($query))
{
//display or do something here
}
}
}
?>
You can see that this takes uid from GET i.e. from user and works accordingly. Seems fine and most of the site visitors won’t know about it. But what if someone elite visits the site. He/She will test the GET variable and change the uid value.
The query runs and runs without any filtering mechanism. And if the malicious runs the SQL query, he can do anything to the database. So what’s the solution for this? Simply, type checking. You won’t expect uid to be anything other than integer type. So why not tell PHP that the uid must be integer…
//configurations for mysql connection
$host = “localhost”;
$user = “root”;
$pass = “w000000t”;
$db = “db_shop”;
//connecting to mysql
mysql_connect($host, $user, $pass);
mysql_select_db($db);
$uid = (Int) $_GET[‘uid’]; //you say that uid must be integer…
if (isset($uid))
{
$query = mysql_query(“SELECT * FROM `profile` WHERE `uid` = $uid”);
if ($query)
{
while($profile = mysql_fetch_array($query))
{
//display or do something here
}
}
}
?>
So this should be secure…
Moreover, there are several functions in PHP for various kinds of validation and escaping like mysql_real_escape_string, htmlentities(), strip_tags(),etc. and there are different other ones to validate the datatypes like is_numeric() and settype(). Explore them and be secured.
With this, the tutorial for secure coding in PHP has ended… I might extend this to validate uploads also when I have time but till then, bye and be safe.