Home > Web Security > HTTP Methods: GET vs POST

HTTP Methods: GET vs POST

November 21st, 2008

HyperText Transfer Protocol, or HTTP, is the protocol of the web. It is what transports data from client to server and back. The HTTP specification defines several HTTP methods for transferring different types of data. Most of the methods defined are used for proxys and specialty applications. HTTP GET and POST are the two major methods in use on the web today.

Introducing the GET method

Whenever you type in a URL in the address bar of your browser or click on a link from your Email, your browser creates a request that it sends to the server. These requests are in plain-text English. A typical request for http://www.google.com looks like this:

GET / HTTP/1.1
Host: www.google.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;
Keep-Alive: 300

The request specifies the method (GET), the document (/), the protocol version (HTTP/1.1), and the Host from which you are requesting this data. The remaining key-value pairs are there to describe your browser and computer, and what they support. If the requested document is simply a slash as it is in this case, the server knows to serve up its default home page.

GET is also the default method that is used for retrieving any images, style sheets, JavaScript, flash embeds, and typically any other asset that is loaded inside of a given web page.

If you perform a search on Google, the headers will look like this:
(I have excluded the rest of the headers, as they are the same above and irrelevant to this discussion)

GET /search?hl=en&q=Hockey&btnG=Google+Search&aq=f&oq= HTTP/1.1
Host: www.google.com

As you can see here, the requested document now is a long string of data. The HTTP specification tells us that anything that comes after the ? is to be interpreted as key-value pairs. These key-value pairs can then be read by the server application so that it may generate the page dynamically. These keys and values may be modified easily by someone simply by clicking on their address bar and typing new values. The HTTP GET method is limited in how much data it can send at once. This limitation is not defined in the specification, and has been implemented by server and browser vendors differently so we can not consistently rely on using a GET request to pass large amounts of data. Check this site for more information: http://www.boutell.com/newfaq/misc/urllength.html

One of the nice things about GET requests, is that you can easily copy and paste that link to a friend and then your friend can see the exact same web page that you are seeing. We’ll find out that this is also what makes the GET methods so dangerous.

Introducing the POST method

The POST method, like the GET method, can also send data to a server. POST is typically the method used for sending larger amounts of data, and is always the method used when uploading binary data. POST is also the method used when you want to send data, but do not want to clutter the URL with senseless parameters and long strings. All login forms are (or should be!) POST requests because you wouldn’t want your users’ login details to be visible in the URL.

On Wordpress.com there is a login form. A typical login will create a POST request like this:
(I have excluded the rest of the headers, as they are the same above and irrelevant to this discussion)

POST /wp-login.php HTTP/1.1
Host: wordpress.com

log=myusername&pwd=mypassword&testcookie=1&redirect_to=http%3A%2F%2Fwordpress.com%2F&submit=Login

As you can see here, the request format is still the same as the GET method but with two key differences. First, and most obvious, is that this request uses the POST verb rather than GET. The second, and most important, difference is that while the browser still sent a chunk of data, even in the same format as the GET method, it sent it in a separate payload, rather than a part of the URL.

This means that the data could not be modified by a typical visitor without the use of advanced tools, because it does not exist in the URL at all. POST does not suffer from the typical data size limitations as GET does.

When to use GET and when to use POST

There is a very simple rule to follow here. GET should only be used to retrieve information. It should never be used to manipulate your database. POST can be used for both retrieving data from the database and changing the database.

Suppose you have a web application that allows a user to change their password. You might create a web page with a form on it using the GET method. It would take one parameter – newPassword.

A member could enter a new password and press submit and their browser would change its URL to:

http://www.mySocialNetwork.com/settings/changePassword?newPassword=puppies

While this may not seem like a big deal, imagine if a malicious user decided to take the above URL and send it to all the other members of the site. There is a good chance that at least a few people might click on the link, accidentally changing their passwords to “puppies”.

If the changePassword function only supported POST, then an attacker would not be able to craft a URL like the one above. The catch here is that changing all of your HTML forms to use POST does not mean you are safe. Your backend code which processes the request must we aware of which requests are POST and which are GET.

In C# there exists an object called Request which provides all of the details of a given request, including posted form values, URL parameters, cookies, etc. If a programmer chooses to use Request["paramaterName'] then the Request object will look for parameterName in both posted form values as well as URL parameters. Use of this is insecure. Instead, Request.Form["parameterName"] to ensure that the value only comes from a POST parameter.

PHP also has a $_REQUEST global variable which does the same as the Request object in C#. Instead of using $_REQUEST, a developer should use $_POST to retrieve only POSTed parameters.

What can happen if we do it wrong?

By using the wrong method or by accidentally supporting both GET and POST for the same action, you open your website up to a class of attacks known as Cross Site Request Forgeries. CSRF attacks are complicated and beyond the scope of this article, so I will be writing another post soon detailing how CSRF attacks work.

Bryan Migliorisi Web Security

  1. Bala Sakthis
    July 12th, 2009 at 17:24 | #2

    Hi Bryan,
    I went through your article. A crisp explanation with the header data.

    “In C# there exists an object called Request which provides all of the details of a given request…..”

    After reading the above para, I wanted to share one of the whitepapers, I went through. Please visit http://lavakumar.com/ and read the article on “Split and Join”. Also, please google and learn about HTTP Parameter pollution. This vulnerability has its base on what you had warned.

    Thanks!
    Bala

  1. No trackbacks yet.