Uli's Web Site
[ Zathras.de - Uli's Web Site ]
Other Sites: Stories
Abi 2000
Stargate: Resurgence
Lost? Site Map!
     home | blog | moose | programming | articles >> blog

 Blog Topics

15 Most Recent [RSS]

 Less work through Xcode and shell scripts
2011-12-16 @600
 iTunesCantComplain released
2011-10-28 @954
 Dennis Ritchie deceased
2011-10-13 @359
 Thank you, Steve.
2011-10-06 @374
 Cocoa Text System everywhere...
2011-03-27 @788
 Blog migration
2011-01-29 @520
 All you need to know about the Mac keyboard
2010-08-09 @488
 Review: Sherlock
2010-07-31 @978
 Playing with Objective C on Debian
2010-05-08 @456
 Fruit vs. Obst
2010-05-08 @439
 Mixed-language ambiguity
2010-04-15 @994
 Uli's 12:07 AM Law
2010-04-12 @881
 Uli's 1:24 AM Law
2010-04-12 @874
 Uli's 6:28 AM Law
2010-04-12 @869
 Uli's 3:57 PM Law
2010-04-12 @867


On the difficulty of writing safe web sites

A while ago, this server was down because another user hosted on the same physical computer at my hoster's had an open mail relay script, which got the whole thing blocked, including my site.

That reminded me that, maybe, I should write a little piece on why one needs to be very careful when writing one's own web site, and in particular CGIs of some sort, whether they're in C, PHP or Perl.

The main thing to remember is the golden rule of web programming:

Any data coming from the user is insecure.

Many people know this, but few understand that this includes form fields.

It's easy to copy and edit forms. A hacker just does a "view source", copies that into an HTML file, and then changes it to her heart's content. As long as she keeps the form action pointing to our server, she can hand any garbage to the CGI script, including multiple lines in single-line fields, text in number fields... if this is a CGI written in C, this garbage data could do buffer overflow attacks, or even cause zero divisions, if we do not religiously truncate, filter and sanitize the input data in our CGI script.

And there are even Firefox plugins to edit forms on-the-fly, WYSIWYG.

This is the main venue of attack to a web server: Feeding it bad form data, and trying to make it do something it wasn't intended to do. While underflowing lengthrequirements or providing unexpected data generally only shoots down a process on the server, and on most servers at best terminates the hacker's session, overflows have much greater dangers: In theory, hackers could make our CGI write into memory that contains executable code, and then overwrite it with malicious code.

Always filter paths

But that's too complicated. There are easier ways that hackers try to make our scripts fall down. For example, I once came across a site with URLs like this:
Nice. A hacker changes that URL a little, and she can view any file on that server, even ones protected by .htaccess passwords. After all, the script reads the file on the server, and thus doesn't go through Apache. Talking of which, she could even view the .htaccess file's contents by specifying http://www.example.com/show.php?file=subsection/.htaccess, and if the web developer was stupid enough to use clear-text username/password pairs in there, the hacker would have access to those files even more easily.

But that's not enough. Our hacker is very clever, so she tries http://www.example.com/show.php?file=show.php and suddenly gets to read the raw source code of that server's file that she wouldn't get to see because it gets interpreted. And once she can read the actual PHP script, she might be able to find other venues of attack.

Or maybe she just enters http://www.example.com/show.php?file=/etc/httpd/httpd.conf and then gets to view the Apache configuration file, and now she knows where your passwords file is, what (possibly exploitable) modules you have installed, etc.

Okay, so you go there and prevent any paths that start with a slash. Great, so she just goes and tries ../etc/httpd.conf. "../" means "go one level up". If she does that a couple times, she ends up at the root, which might be at "../../../../", and voila, she has your httpd.conf file. Okay, so you also prevent paths that start with a period? She does: subsections/../../../../../etc/httpd.conf which goes in the subfolder and right back up again, and is equivalent to the ../../../../etc/httpd.conf we just blocked. Defeated again!

Ideally, you'd not allow paths at all. Just reject all paths that contain slashes or "../" sequences. If you need sub-folders, there's one more thing to watch out for: PHP's default installation also accepts URLs as file paths. http://leethaxorserver.com/exploit.php doesn't contain a "../", doesn't start with a slash, but can still compromise your server if you're stupid enough to use include() or require() to embed the file in your site, instead of using fread() and passing it through. Even then, the other user could present arbitrary HTML on your server.

Always strip out delimiters and other significant characters

Another thing hackers love to do is to abuse delimiters. Imagine we have a contact form that sends an e-mail. We've already realized that we can't pass our e-mail address as a hidden CGI parameter, because Firefox and a plugin are all it takes for a hacker to send that mail message to someone else than us. The same goes for sending a CC to the sender. They could just enter any e-mail address as the sender.

But then someone types the following in the subject field:

CC: victim1@example.com
Since e-mail messages contain of a bunch of headers of the form label:value, followed by an empty line, followed by the message text, our original message, which at worst should have been:
To: me@example.com
Subject: interesting

advertisement goes here
Will suddenly be:
To: me@example.com
Subject: interesting
CC: victim1@example.com

advertisement goes here
And thus send a copy to that victim. Voila, our server is an open mail relay and gets others on it blocked.

So, since we know that the fields in an e-mail header are delimited by line breaks, we make sure what should only be one line really is one line (no matter whether delimited by \n, \r or \r\n).

The same works for other delimiters. If we write something to a list in a file, we make sure any delimiters we use internally are stripped from input data. We make sure that when we take data that we write to an SQL database, it doesn't contain any SQL delimiters. So, if it contains an apostrophe, we turn that into \' to make sure no hacker can end the current string, put a semicolon after it (another dangerous delimiter!) and then start a new SQL command that erases your database, prints out your passwords or whatever. Same goes for PHP, with single quotes, double quotes and other characters. Once hackers' writings get executed as PHP code, they can do anything on our server, e.g. by using the system() function to run grep or whatever.

In HTML, delimiters are < and >. If the hacker can write those, in a comment field, she can embed any HTML code in the page, and thus give others a URL showing libellous content that looks like it's on our server. That's how many "cross-site-scripting" exploits basically work. A hacker just puts an <iframe ... >-tag in a comment field or CGI parameter, that gets displayed on our page, and inside the I-Frame their phishing site gets shown that asks them to enter their bank information to buy from us. We get the blame, they withdraw the money :-( They can even inject JavaScript this way and use DOM scripting to delete the rest of your page and show something completely different (that's very popular for making your ranking look better on eBay, just delete the real ranking box and provide your own with positive reviews).

Watch out for escape sequences

Hackers also like to encode stuff. I.e. you might filter the CGI parameter for newlines, but if they use a percent-escape-sequence to encode the newline, your filter might not catch it because \n and %0A just aren't the same. So, be sure you filter after you've expanded the escapes.

Typing in random URLs

Another approach is to just type in a random URL: http://www.example.com/login.php, or http://www.example.com/.htaccess -- if the server operator didn't block this URL and isn't using a server distribution that blocks such URLs automatically, then the hacker already got our password, or at least the names of the files we don't want her to see. If the server is on a case-insensitive file system, she might try http://www.example.com/.HTACCESS, because that's the same file, but since Apache was written for case-sensitive filenames originally, it didn't consider that the same file as the prohibited .htaccess, and she was able to access it after all.

Still want to write your own web site?

I'm sure I've forgotten some more things in the descriptions above for which I watch out when I write code. The sum total is: It pays off to be paranoid when writing your own CGIs, as easy as it may seem with today's scripting languages. For a web site that just contains contact forms and dynamic directory lists I might risk it.

For a shop system involving confidential customer data, maybe even payment information? Personally, I'd recommend that unless you're a seasoned web developer, you should let a professional do that, or use an existing package that is well-known and maybe even certified. Secure web development and secure desktop programming require a different skill set and having experience in one doesn't make one experienced in the other.

Anything you folks want to add?

Reader Comments: (RSS Feed)
No comments yet
Or E-Mail Uli privately.

Created: 2007-04-19 @946 Last change: 2007-04-28 @028 | Home | Admin | Edit
© Copyright 2003-2023 by M. Uli Kusterer, all rights reserved.