Chapter 11 ■ the World Wide Web
199
When Forms Use Wrong Methods
Web applications that misuse HTTP methods cause problems with automated tools, user expectations, and
the browser.
I remember a friend whose small-business web page was stored within a local hosting company’s home-grown
PHP content management system. An admin screen presented him with links to the images that were used on his site.
We highlighted the page and asked a browser to download all of the links so that he would have his own backup of the
images. Minutes later he received a text from a friend: why were all of the images disappearing from his web site?
It turns out that the Delete button next to each image was not, alas, a real button that launched a POST operation.
Instead, each Delete was merely a link to a plain old URL, which had the nasty side effect of deleting an image if
you visited it! His browser was willing to GET the hundred links on the page because a GET should always, under all
circumstances, be a safe operation. His hosting company had betrayed that trust, and the result was that his web site
had to be restored from their backups.
The opposite error—performing “read” operations with POST—has less dire effects. It merely destroys usability
rather than deleting all of your files.
I once had the displeasure of using a homegrown search engine internal to a large institution. After several
searches, I had a page of results in front of me that my supervisor needed to see, so I highlighted the URL and
prepared to paste it into an e-mail.
Then I read the URL and was dismayed. Even without knowing how the server worked, I was sure that /search.pl
was not by itself going to bring this page of results back up when my supervisor visited it!
The query was invisible to my browser’s location bar because the search form was incorrectly designed to use
POST. This made the URL of every single search look exactly the same, meaning that searches could neither be shared
nor bookmarked. And when I tried to navigate through a series of searches with my browser’s Forward and Back
buttons, I got a sequence of pop-up windows asking if I really wanted to resubmit each search! As far as the browser
knew, any of those POSTs could have had side effects.
Using GET for places and POST for actions is crucial not merely for the sake of the protocol but for a productive
user experience.
Safe and Unsafe Cookies
The web application in Listing 11-2 attempts to provide privacy to its users. It requires a successful login before it
divulges the user’s list of payments in response to a GET of the / page. It also requires the user to have logged in before
it will accept a POST to the /pay form that lets the user transfer money.
Unfortunately, it is quite easy to exploit the application and make payments on behalf of another user!
Consider the steps that a malicious user who gains access to the site might take, perhaps by opening their own
account on the site to investigate how it works. They will open the debugging tools in Firefox or Google Chrome and
then log on to the site, watching the outgoing and incoming headers in the Network pane to see how the site works.
And what will they see coming back in response to their username and password?
HTTP/1.0 302 FOUND
...
Set-Cookie: username=badguy; Path=/
...
How interesting! Their successful login has delivered a cookie named username to their browser, with their own
username badguy as the value. Apparently, the site is blithely trusting that subsequent requests with this cookie must
necessarily indicate that they have typed their username and password correctly.
But surely the caller can give this cookie any value they want?