Securing HTML forms

In this short tutorial I will show you some ways to protect a (login) web form against the most common types of attacks, making it much safer.

I will use PHP as the server-side programming language, but any other language will provide similar features.

Use encryption
Something very important which new programmers usually forget is the use of encryption. It is very important that you encrypt the passwords that are stored in the database. And no, I don’t mean base64, which isn’t a real encryption. When a user logs in, their entered password needs to be encrypted, and then the encrypted strings should be compared.

Which encryption should you use?

This depends on the capabilities of the programming language, the performance of your server and the use of your web application. Large encryption algorithms are the safest, but can have performance impact on the server. But on the other hand, small algorithms are cracked much faster.

In PHP version 5.1 using the HASH plugin, you can use encryption algorithms like SHA-256 and SHA-512. 512 has the best security, but might seriously affect performance on a very busy website. In that case fall back to 256 or even SHA-1. Do make up your mind, because the algorithm is not reversible. So for each change, your users need to create a new password. Changing this weekly will seriously irritate your users, so be careful.

In this example I’ll encrypt the password field with SHA-512 encryption:

$password = hash("sha512",$_POST['password']);

Alternatively you can also create an MD5 hash without the HASH function:

$password = md5($_POST['password']);

Using SHA-512, you can turn a password like ‘l23’ into ‘3c9909afec25354d551dae21590bb26e38d53f2173b8d3dc3eee4c047e7ab1c1eb8b85103e3be7ba613b31bb5c9c36214dc9f14a42fd7a2fdb84856bca5c44c2’.

Protecting against SQL Injection

If your login information is stored in a SQL database, you need to communicate with it using special SQL commands. A common way to retrieve a login from a database is done something like this:

mysql_query("SELECT * FROM users WHERE username = '$username' AND password = '$password'");

If an attacker can visualize how this is being done on your webpage, it can send SQL commands to your database server using the text fields in your form. For instance, by adding a quotation mark it would end the text-part and then give the attacker the ability to send a SQL command that for example would always give back a result, thus getting logged in. It can also have an even more devastating effect: destroying the tabled of your database or collecting user information. Believe it or not, if a large portion of user information gets leaked, it can be blamed on YOU. Luckily there’s an easy way to do it. it takes more code, but it’s worth it.

In PHP you can use a function called ‘mysql_real_escape_string’. This function will escape characters which a SQL database might interpret as instructions. So for example a quotation character ” will be changed to \”.

New Situation:

$password = mysql_real_escape_string($password);

Cross-Site Scripting

A very common method of attacking is called Cross-Site Scripting (XSS), which comes in many forms. It basically comes down to sending maliciously crafted instructions to the web page. Suppose you have a form which allows a user to reset his password. When the user is logged in, he can click on a button that opens up the page containing the form.

On the user page:

 
<form action="edituser.php" method="post"><input type="hidden" name="edit" value="<?php echo $userid; ?>" />
<input type="submit" name="submit" value="Change Password" />

This will send a POST request to the page edituser.php. Now that page looks like this:

if(isset($_POST['edit'])) {echo "Please enter a new password:
 
<input type="password" name="pass" />";} else {
echo "You are not logged in, so you cannot change your password";
}

Only when you go to the edit page using the form, it gives you the ability to change the password. If an attacker would try to open this file directly, he would see an error message. Fortunately for the attacker this is an easy one to crack. All you have to do is create an HTML form (on your computer or on a webserver) which submits a field with a user ID to the edit page, with the same name (edit).

 
</form><form action="www.mydomain.com/edituser.php" method="post"><input type="text" name="edit" value="1" /> <input type="submit" name="inject" value="inject" /></form><form action="edituser.php" method="post">

If you put a ‘1’ inside the field ‘edit’, it will then create a new password for the user with ID # 1.There are two ways to fix this.1. Have the user enter his old password, and then check if the userid and the password match.
2. Create a token to prove to the edit-page that the request really comes from the server. We do this by creating a token and storing it in a session. Send that value along with the form using a hidden field, and then have the edit-page verify the token.

On the user environment page, check if a session variable for the token is stored and otherwise create it. I create one using the uniqid function together with a SHA-512 hash of the current timestamp.

 
session_start();
 
if(! isset($_SESSION['token']) ) {
$_SESSION['token'] = uniqid( hash("sha512",time() ) );
}
 
</form><form action="edituser.php" method="post"><input type="hidden" name="token" value="<?php echo $_SESSION[" /> <input type="hidden" name="edit" value="<?php echo $userid; ?>;" />
<input type="submit" name="submit" value="Change Password" />

Now change the edit-page to verify if the token from the form matches the one in the session-variable.

 
// Start the session (IMPORTANT)
session_start();
 
if(isset($_POST['edit'])) {
 
// Check if the hidden field 'token' matches our token.
if($_POST['token'] == $_SESSION['token']) {
echo "Please enter a new password:
 
<input type="password" name="pass" />";
} else {
echo "Incorrect token! Go away!";
}
} else {
echo "access denied!";
}

Please note that for method 2 to be secure, you must make sure that an attacker can’t get write access to your file system. Otherwise they can create a page which generates them a session token and then circumvent this. If you’re not sure, choose option 1.

Another way how XSS is used is by the creation of scripts on the pages of your website. Even though an attacker wouldn’t be able to modify your code because it’s secured, it can always be done dynamically. For example, you have a community website like a forum or blog and give people the ability to register. If I wanted to get the passwords if your fellow users, I’d simply create a login page that looks similar to yours. And then the magic happens as I create a user account with this username:

<script type="text/javascript">
window.location='http://www.myowndomain/fakeloginpage.php'></script>

Whenever a user displays any page that has this name on it, they will be redirected to the fake login page.

To prevent this from happening, you need to escape HTML code using the function htmlspecialchars. Example:

$username = htmlspecialchars($username)

The piece of JavaScript will still be displayed as the user name, but as far as the web browser is concerned, it’s only text.

Leave a Reply

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