Is either GET or POST more secure than the other?

Viewed 177589

When comparing an HTTP GET to an HTTP POST, what are the differences from a security perspective? Is one of the choices inherently more secure than the other? If so, why?

I realize that POST doesn't expose information on the URL, but is there any real value in that or is it just security through obscurity? Is there ever a reason that I should prefer POST when security is a concern?

Edit:
Over HTTPS, POST data is encoded, but could URLs be sniffed by a 3rd party? Additionally, I am dealing with JSP; when using JSP or a similar framework, would it be fair to say the best practice is to avoid placing sensitive data in the POST or GET altogether and using server side code to handle sensitive information instead?

28 Answers

As far as security, they are inherently the same. While it is true that POST doesn't expose information via the URL, it exposes just as much information as a GET in the actual network communication between the client and server. If you need to pass information that is sensitive, your first line of defense would be to pass it using Secure HTTP.

GET or query string posts are really good for information required for either bookmarking a particular item, or for assisting in search engine optimization and indexing items.

POST is good for standard forms used to submit one time data. I wouldn't use GET for posting actual forms, unless maybe in a search form where you want to allow the user to save the query in a bookmark, or something along those lines.

You have no greater security provided because the variables are sent over HTTP POST than you have with variables sent over HTTP GET.

HTTP/1.1 provides us with a bunch of methods to send a request:

  • OPTIONS
  • GET
  • HEAD
  • POST
  • PUT
  • DELETE
  • TRACE
  • CONNECT

Lets suppose you have the following HTML document using GET:

<html>
<body>
<form action="http://example.com" method="get">
    User: <input type="text" name="username" /><br/>
    Password: <input type="password" name="password" /><br/>
    <input type="hidden" name="extra" value="lolcatz" />
    <input type="submit"/>
</form>
</body>
</html>

What does your browser ask? It asks this:

 GET /?username=swordfish&password=hunter2&extra=lolcatz HTTP/1.1
 Host: example.com
 Connection: keep-alive
 Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/ [...truncated]
 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) [...truncated]
 Accept-Encoding: gzip,deflate,sdch
 Accept-Language: en-US,en;q=0.8
 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

Now lets pretend we changed that request method to a POST:

 POST / HTTP/1.1
 Host: example.com
 Connection: keep-alive
 Content-Length: 49
 Cache-Control: max-age=0
 Origin: null
 Content-Type: application/x-www-form-urlencoded
 Accept: application/xml,application/xhtml+xml,text/ [...truncated]
 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; [...truncated]
 Accept-Encoding: gzip,deflate,sdch
 Accept-Language: en-US,en;q=0.8
 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

 username=swordfish&password=hunter2&extra=lolcatz

BOTH of these HTTP requests are:

  • Not encrypted
  • Included in both examples
  • Can be evesdroped on, and subject to MITM attacks.
  • Easily reproduced by third party, and script bots.

Many browsers do not support HTTP methods other than POST/GET.

Many browsers behaviors store the page address, but this doesn't mean you can ignore any of these other issues.

So to be specific:

Is one inherently more secure then another? I realize that POST doesn't expose information on the URL but is there any real value in that or is it just security through obscurity? What is the best practice here?

This is correct, because the software you're using to speak HTTP tends to store the request variables with one method but not another only prevents someone from looking at your browser history or some other naive attack from a 10 year old who thinks they understand h4x0r1ng, or scripts that check your history store. If you have a script that can check your history store, you could just as easily have one that checks your network traffic, so this entire security through obscurity is only providing obscurity to script kiddies and jealous girlfriends.

Over https, POST data is encoded, but could urls be sniffed by a 3rd party?

Here's how SSL works. Remember those two requests I sent above? Here's what they look like in SSL: (I changed the page to https://encrypted.google.com/ as example.com doesn't respond on SSL).

POST over SSL

q5XQP%RWCd2u#o/T9oiOyR2_YO?yo/3#tR_G7 2_RO8w?FoaObi)
oXpB_y?oO4q?`2o?O4G5D12Aovo?C@?/P/oOEQC5v?vai /%0Odo
QVw#6eoGXBF_o?/u0_F!_1a0A?Q b%TFyS@Or1SR/O/o/_@5o&_o
9q1/?q$7yOAXOD5sc$H`BECo1w/`4?)f!%geOOF/!/#Of_f&AEI#
yvv/wu_b5?/o d9O?VOVOFHwRO/pO/OSv_/8/9o6b0FGOH61O?ti
/i7b?!_o8u%RS/Doai%/Be/d4$0sv_%YD2_/EOAO/C?vv/%X!T?R
_o_2yoBP)orw7H_yQsXOhoVUo49itare#cA?/c)I7R?YCsg ??c'
(_!(0u)o4eIis/S8Oo8_BDueC?1uUO%ooOI_o8WaoO/ x?B?oO@&
Pw?os9Od!c?/$3bWWeIrd_?( `P_C?7_g5O(ob(go?&/ooRxR'u/
T/yO3dS&??hIOB/?/OI?$oH2_?c_?OsD//0/_s%r

GET over SSL

rV/O8ow1pc`?058/8OS_Qy/$7oSsU'qoo#vCbOO`vt?yFo_?EYif)
43`I/WOP_8oH0%3OqP_h/cBO&24?'?o_4`scooPSOVWYSV?H?pV!i
?78cU!_b5h'/b2coWD?/43Tu?153pI/9?R8!_Od"(//O_a#t8x?__
bb3D?05Dh/PrS6_/&5p@V f $)/xvxfgO'q@y&e&S0rB3D/Y_/fO?
_'woRbOV?_!yxSOdwo1G1?8d_p?4fo81VS3sAOvO/Db/br)f4fOxt
_Qs3EO/?2O/TOo_8p82FOt/hO?X_P3o"OVQO_?Ww_dr"'DxHwo//P
oEfGtt/_o)5RgoGqui&AXEq/oXv&//?%/6_?/x_OTgOEE%v (u(?/
t7DX1O8oD?fVObiooi'8)so?o??`o"FyVOByY_ Supo? /'i?Oi"4
tr'9/o_7too7q?c2Pv

(note: I converted the HEX to ASCII, some of it should obviously not be displayable)

The entire HTTP conversation is encrypted, the only visible portion of communication is on the TCP/IP layer (meaning the IP address and connection port information).

So let me make a big bold statement here. Your website is not provided greater security over one HTTP method than it is another, hackers and newbs all over the world know exactly how to do what I've just demonstrated here. If you want security, use SSL. Browsers tend to store history, it's recommended by RFC2616 9.1.1 to NOT use GET to perform an action, but to think that POST provides security is flatly wrong.

The only thing that POST is a security measure towards? Protection against your jealous ex flipping through your browser history. That's it. The rest of the world is logged into your account laughing at you.

To further demonstrate why POST isn't secure, Facebook uses POST requests all over the place, so how can software such as FireSheep exist?

Note that you may be attacked with CSRF even if you use HTTPS and your site does not contain XSS vulnerabilities. In short, this attack scenario assumes that the victim (the user of your site or service) is already logged in and has a proper cookie and then the victim's browser is requested to do something with your (supposedly secure) site. If you do not have protection against CSRF the attacker can still execute actions with the victims credentials. The attacker cannot see the server response because it will be transferred to the victim's browser but the damage is usually already done at that point.

There is no added security.

Post data does not show up in the history and/or log files but if the data should be kept secure, you need SSL.
Otherwise, anybody sniffing the wire can read your data anyway.

Even if POST gives no real security benefit versus GET, for login forms or any other form with relatively sensitive information, make sure you are using POST as:

  1. The information POSTed will not be saved in the user's history.
  2. The sensitive information (password, etc.) sent in the form will not be visible later on in the URL bar (by using GET, it will be visible in the history and the URL bar).

Also, GET has a theorical limit of data. POST doesn't.

For real sensitive info, make sure to use SSL (HTTPS)

Neither one of GET and POST is inherently "more secure" than the other, just like neither one of fax and phone is "more secure" than the other. The various HTTP methods are provided so that you can choose the one which is most appropiate for the problem you're trying to solve. GET is more appropiate for idempotent queries while POST is more appropiate for "action" queries, but you can shoot yourself in the foot just as easily with any of them if you don't understand the security architecture for the application you're maintaining.

It's probably best if you read Chapter 9: Method Definitions of the HTTP/1.1 RFC to get an overall idea of what GET and POST were originally envisioned ot mean.

The difference between GET and POST should not be viewed in terms of security, but rather in their intentions towards the server. GET should never change data on the server - at least other than in logs - but POST can create new resources.

Nice proxies won't cache POST data, but they may cache GET data from the URL, so you could say that POST is supposed to be more secure. But POST data would still be available to proxies that don't play nicely.

As mentioned in many of the answers, the only sure bet is via SSL.

But DO make sure that GET methods do not commit any changes, such as deleting database rows, etc.

This isn't security related but... browsers doesn't cache POST requests.

My usual methodology for choosing is something like:

  • GET for items that will be retrieved later by URL
    • E.g. Search should be GET so you can do search.php?s=XXX later on
  • POST for items that will be sent
    • This is relatively invisible comapred to GET and harder to send, but data can still be sent via cURL.

Neither one magically confers security on a request, however GET implies some side effects that generally prevent it from being secure.

GET URLs show up in browser history and webserver logs. For this reason, they should never be used for things like login forms and credit card numbers.

However, just POSTing that data doesn't make it secure, either. For that you want SSL. Both GET and POST send data in plaintext over the wire when used over HTTP.

There are other good reasons to POST data, too - like the ability to submit unlimited amounts of data, or hide parameters from casual users.

The downside is that users can't bookmark the results of a query sent via POST. For that, you need GET.

It is harder to alter a POST request (it requires more effort than editing the query string). Edit: In other words, it's only security by obscurity, and barely that.

Disclaimer: Following points are only applicable for API calls and not the website URLs.

Security over the network: You must use HTTPS. GET and POST are equally safe in this case.

Browser History: For front-end applications like, Angular JS, React JS etc API calls are AJAX calls made by front-end. These does not become part of browser history. Hence, POST and GET are equally secure.

Server side logs: With using write set of data-masking and access logs format it is possible to hide all or only sensitive data from request-URL.

Data visibility in browser console: For someone with mallicious intent, it's almost the same efforts to view POST data as much as GET.

Hence, with right logging practices, GET API is as secure as POST API. Following POST everywhere, forces poor API definitions and should be avoided.

Many people adopt a convention (alluded to by Ross) that GET requests only retrieve data, and do not modify any data on the server, and POST requests are used for all data modification. While one is not more inherently secure than the other, if you do follow this convention, you can apply cross-cutting security logic (e.g. only people with accounts can modify data, so unauthenticated POSTs are rejected).

I'm not about to repeat all the other answers, but there's one aspect that I haven't yet seen mentioned - it's the story of disappearing data. I don't know where to find it, but...

Basically it's about a web application that mysteriously every few night did loose all its data and nobody knew why. Inspecting the Logs later revealed that the site was found by google or another arbitrary spider, that happily GET (read: GOT) all the links it found on the site - including the "delete this entry" and "are you sure?" links.

Actually - part of this has been mentioned. This is the story behind "don't change data on GET but only on POST". Crawlers will happily follow GET, never POST. Even robots.txt doesn't help against misbehaving crawlers.

You should also be aware that if your sites contains link to other external sites you dont control using GET will put that data in the refeerer header on the external sites when they press the links on your site. So transfering login data through GET methods is ALWAYS a big issue. Since that might expose login credentials for easy access by just checking the logs or looking in Google analytics (or similar).

GET is visible to anyone (even the one on your shoulder now) and is saved on cache, so is less secure of using post, btw post without some cryptographics routine is not sure, for a bit of security you've to use SSL (https)

There are no security unless https is used - and with https, the transfer security is the same between GET and POST.

But one important aspect is the difference for client and server when it comes to remembering requests. This is very important to remember when considering GET or POST for a login.

With POST, the password is processed by the server application and then throw away, since a good design would not store passwords - only cryptographically secure hashes - in the database.

But with GET, the server log would end up containing the requests complete with the query parameters. So however good the password hashes in the database are, the server log would still contain passwords in clear text. And unless the file system is encrypted, the server disk would contain these passwords even after the log files have been erased.

The same problem happens when using access tokens as query parameters. And this is also a reason why it is meaningful to consider supplying any access token in the HTTP header data - such as by using a bearer token in the Authorization header.

The server logs are often the weakest part of a web service, allowing an attacker to elevate their access rights from leaked information.

Post is the most secured along with SSL installed because its transmitted in the message body.

But all of these methods are insecure because the 7 bit protocol it uses underneath it is hack-able with escapement. Even through a level 4 web application firewall.

Sockets are no guarantee either... Even though its more secure in certain ways.

Related