Website Security: An Interesting Report On Web Security
Website Security: An Interesting Report On Web Security
high on the radar of anyone who has a Web presence under their
control. Ineffective Web security leads to all of the things that
make us hate the Web: spam, viruses, identity theft, to name a few.
The problem with Web security is that, as important as it is, it is also very
complex. I am quite sure that some of you reading this are already part of an
network of attack computers and that your servers are sending out spam
messages without you even knowing it. Your emails and passwords have been
harvested and resold to people who think you need either a new watch, a
male enhancement product or a cheap mortgage. Fact is, you are part of the
problem and don’t know what you did to cause it.
The reason is that security experts don’t like to talk too much in public about
what they do and where the issues lie; and sadly enough, they can also come
across as arrogant in their views. This could be the result of people not taking
security seriously and not following the most basic advice, such as using
passwords that are clever, not “password” or “letmein.”
Another reason is those tutorials that show you how to “do something in five
minutes” and conveniently neglect to mention the security implications of
their advice. If it sounds too easy to be true, it probably is. A perfect example
of this is PHP solutions that use a file for data storage and ask you to make it
writable to the world. This is easy to implement, but it means that any
spammer can write to this file.
An Interesting Report On Web Security
Web security company Cenzic released a report detailing trends and numbers
related to Web security for the first and second quarters of 2009.
Among the most serious vulnerabilities were path traversal, cross-site
scripting, cross-site request forgery and SQL injection. Unmentioned are a
newer threat, clickjacking, and a user interface issue called phishing. You may
have to deal with all of these as a Web developer if you touch PHP and HTML,
CSS and JavaScript. Even if you don’t use PHP, you could still cause a lot of
problems. Even if you don’t touch code and simply design, you could be a
great asset in this area. You could help make the Web safer by making security
issues understandable to your users.
Let’s go through all of these things and explain what they are and do. The first
thing you need to know, though, is how URIs work.
URIs: The Main Way To Attack A Web Service
The address of any document (i.e. file on the Internet) is its Uniform
Resource Identifier (URI). This is what you enter in the browser bar to
access the document and what you embed into code to point to the
document. For example, my website address is http://icant.co.uk, and the
document you see when you open it in a browser
is http://icant.co.uk/index.php (the server automatically redirects to that
document). The logo image resides at the
URI http://icant.co.uk/iconslogo.png, and the image of me pointing at you is
on a totally different server and has the
URIhttp://farm4.static.flickr.com/3172/3041842192_5b51468648.jpg.
All of these URIs are okay for you to access. Some URIs, though, contain
information that should not be accessible to the outside world. For example,
the /etc/password folder on a server contains password and user information
that should not leak to the Internet.
Every URI can also contain parameters. These are instructions you can send to
the script located at that URI and that are appended to the URI starting with
a? and separated by ampersands. If you want to search for puppies on Google,
for example, you can use the URI http://www.google.com/search?q=puppies,
and if you want to begin your search after the first 50 results, you can
use http://www.google.com/search?q=puppies&start=50.
Normally, these parameters are not entered by end users but rather come
from the HTML interface. If you look at the source code of the Google home
page and get rid of the painful bits, you end up with the following form:
<form name="f" action="/search">
<input type="hidden" value="en" name="hl"/>
<input type="hidden" value="hp" name="source"/ >
<input name="q"/>
<input type="submit" name="btnG"/>
<input type="submit" name="btnI"/>
<input type="hidden" name="aq"/>
<input type="hidden" name="oq"/>
<input type="hidden" name="aqi"/>
</form>
So in essence, this form sends the content of all of these fields to the
URIsearch and appends them to that URI. This is how you end up with this,
http://www.google.com/search?hl=en &source=hp&q=puppies&aq=f&oq=&aqi=
when you submit the form. Notice, for instance, that I have no btnG parameter
because I used the Enter key to submit the form.
On the search results page, you can see the pagination links at the bottom
(the 1 2 3 and so on under the Gooooooogle logo), and you can see
that these links send the same data to the URI and add a start parameter:
<a href="/search?hl=en&q=puppies&start=40&sa=N">5</a>
You can send parameters to a script with the URI via form fields, links or any
other thing in HTML that contains a URI: images, link elements, frames,
anything that can take an href or src attribute. If an attacker can override any
of these or add a new image to your HTML without you knowing it, they could
point to their own URIs and send their own parameters.
You have to be careful with what your parameters contain and where they
point to, which could be someone else’s server (to get more code) or sections
of your own server that you don’t want to show or send to another server.
Different Types Of Attacks. What Do These
Words Mean?
Let’s quickly go through the different items mentioned in the graph above,
explaining what they are and what they mean.
SQL INJECTION
With an SQL injection, an attacker accesses your database by sending an
SQL command to your server via the URI or form fields. This is easily worked
around by sanitizing, but neglecting to do so can be fatal for your website,
as the following XKCD comic shows:
Once you have successfully injected JavaScript, you will be able to read out
cookies; open forms that ask the user to enter their passwords or credit card
details; execute viruses, worms and “drive-by downloads”; the lot. The reason
is that JavaScript is not bound by any security model; any script on the page
has the same rights, no matter which server it has come from. This is a big
security problem with JavaScript and is something clever people are working
on.
XSS is a very common problem. Websites such as XSSED.org have a field
day showing the world just how many websites are vulnerable:
The remedy for XSS is to be very paranoid about anything that comes via
forms or the URI. You also need to be sure that your PHP is set up properly
(we’ll come back to some ways to test for that and to write good code later
on).
PATH TRAVERSAL
Allowing for path or directory traversal on your server is an amazingly bad
idea. You would be allowing people to list the folders on your server and to
navigate from folder to folder. This allows attackers to go to folders with
sensitive information or website functionality and have some fun. The
following screenshot is of me accessing the database of a sandwich company,
sending emails from their server and reading the order logs:
I was able to get all of this information simply by accessing the cgi-
bin folder, which was unprotected from being listed. So, instead of going
tohttp://example.com, I went to http://example.com/cgi-bin/ in my browser. I
knew something was wrong on their big Flash website when I clicked on the
menu. It popped up in a new window and had a URI like
http://www.example.com/cgi/food_db/db.cgi?db=default &uid=default&Category=Sa
ndwiches&Subcategory=Sandwiches&Product=Chicken%20and%20Bacon&Soup_size=&Dr
inks_milk_type=&ww=on&view_records=yes
which gave me all the information I needed to play around.
The other problem of allowing folders to be listed is that search engines will
index your information, allowing anyone to use Google as a hacking tool. As
servers create a page with a title and a headline of the folder name, these are
indexed by Google.
This method of searching worked much better in the past, by the way: not
because people protect their servers better now, but because spammers who
offer fake pirated products realize that people do these searches and fake it
now to optimize their own websites’ search engine rankings.
CROSS-SITE REQUEST FORGERY
Cross-site request forgery (CSRF) exploits browsers and websites
that allow for functionality to be called without really knowing that an actual
user initiated it. Say you have a form on your website http://example.com that
works with GET and sends things to your database:
<form method="get" action="add_to_db.php">
<div>
<label for="name">Name</label>
<input type="text" id="name" name="name">
</div>
<div>
<label for="email">email</label>
<input type="text" id="email" name="email">
</div>
<div>
<label for="comment">Comment</label>
<textarea id="comment" name="comment"></textarea>
</div>
<div><input type="submit" value="tell me more" ></div>
</form>
Forms can be sent by two methods: GET adds all of the parameters to the URI
visibly in the address bar, whereas POST sends them “under the hood.” POST
also allows you to send much more data. This is a simplification but all you
need to know for now.
If the script that adds to the database doesn’t check that the form was really
sent from your server, I could add an image to any website by doing this:
<img src="http://example.com/add_to_db.php?
name=cheap%20rolex&[email protected]&comment=mortgage%20help"
width="1" height="1">
Anybody coming to my website would now be putting another comment into
your database. I could use an image or CSS link or script or anything that
allows for a URI to be defined and loaded by a browser when the HTML
renders. In CSS, this could be a background image.
CSRF becomes even more dangerous when you are logged into and
authenticated by a particular system. An image in any other tab in your
browser could execute a money transfer, read your emails and send them on
and many other evil things.
A really interesting case of CSRF (albeit an innocent one) occurred in 2006,
when Google released its now discontinued Web accelerator tool (GWA). The
idea was to pre-fetch websites that were linked to from the current document,
thus making surfing faster. All well and good… until you ended up with delete
links in websites that worked like this:
<a href="/app/delete_entry.php?id=12" >delete</a>
Because some applications did not check if this was an initiated deletion or an
attempt of GWA to pre-load the page, the tool deleted whole blogs and
product databases. Google did nothing wrong, but the community learned a
lot about CSRF that day.
Now, you might suppose that moving your forms from GET to POST would
make them safe, right? Partially, yes, but an attacker could still use a form and
trick people into clicking a button to make the request:
<form method="post" action="add_to_db.php">
<div>
<input type="hidden" name="name" value="bob" >
<input type="hidden" name="email" value="[email protected]" >
<input type="hidden" name="comment"
value="awesome article, buy cialis now!" >
<input type="submit" value="see beautiful kittens now!" >
</div>
</form>
You could even use JavaScript to automatically send the form or a script on
another server to do the POST request from the back-end. There are many
ways to exploit CSRF, and protecting against it is not that
hard.
REMOTE FILE INCLUSION (RFI)
With Remote file inclusion or code injection, an attacker uses a
flaw in your website to inject code from another server to run on yours. It is in
the same family as XSS but much more problematic because you have full
access to your server (with JavaScript, you can steal cookies and call other
code, but you can’t access the file system without resorting to tricks with Flash
or Java Applets).
Any code injected to your server with an untested variable
and include()command, for example, could run server commands: upload and
download and transfer data to other servers, check your server passwords and
user names, anything you can do on the command line via PHP or ASP if your
server allows for it.
This is probably the worst that can happen to your server, because with
command line access, I could turn it into an attack machine for a server
network attack, silently listen to everything you and your users do on the
server and send it to another Web resource, store information and viruses for
distribution, inject spam links, you name it.
The workaround is to turn off globals and to never ever assemble a URI from
parameter or form data. (More on that later in the PHP section of the tips.)
PHISHING
Phishing is the technique of fooling people into entering information into
a bad website. You show end users an interface that looks legit (for a bank or
what have you) but that in reality sends their information to your database.
Because phishing is a felony, I cannot show you a demo.
The trick with phishing is to make the form really look like it comes from a
website you trust. You have probably gotten emails saying that your “XYZ
bank account” has been compromised, and you know for certain that this isn’t
the case because you have no account with that bank and may not have even
heard of it. This is a wild-guess phishing attempt, which is not usually effective.
On the Web, though, an attacker can perform a JavaScript trick to find out
where you’ve been. As Jeremiah Grossman showed some
years ago, you can use JavaScript to determine the state of a link on the
page. Because the colors of visited and unvisited links are different, we can use
this technique to figure which websites a user has been to and then display
the appropriate logo above the form. This demo shows this quite
effectively. Funny enough, you can also use this trick for good; for
example, by showing
people only the buttons of social
media websites they use.
CLICKJACKING
Clickjacking is a terribly clever way to use CSS and inline frames to trick
users into clicking something without knowing it. Probably the most famous
example of this was the “Don’t click me” exploit of Twitter a few months ago.
All of a sudden, Twitter was full of messages pointing to a website with a
button that read “Don’t click me”. Here is an examples for Jason Kottke’s
stream: