
GET vs POST in terms of security - TimothyBurgess
http://stackoverflow.com/questions/198462/get-versus-post-in-terms-of-security/1744404#1744404
======
pak
The difference between GET and POST is interface-related, not security-
related. A better example for why you avoid GET for non-idempotent operations
is to prevent a webcrawler from coming along and innocently making massive
changes to your site just by following links. Security-wise, there's little
difference between the two, it's trival for the client to change the type of
request. (If I can't get some guy on a forum by embedding a picture, I'll send
him a link to some website I control where there's a hidden <form> that posts
to the site I want.) CSRF is only preventable by putting secret tokens in your
forms that get echoed in the submission request (or by double-submitting the
cookie as I do, but tptacek will be in here shortly to tell me why that is so
silly).

~~~
tzs
There is one security difference. POST doesn't leave the data in the URL bar
at the top of the browser. I sure would rather a site submit my credit card
via POST than via GET.

~~~
marcinw
In addition to tzs' comment above, POST parameters do not get logged by the
web server either (default Apache logging, etc), unless you're using a module
like mod_security to log POST data.

Besides, don't use GET for non-idempotent requests (those which change state).
That's just webapp development 101.

Edited for clarity.

~~~
axiak
Either I'm completely misunderstanding your grammar, or you don't understand
what idempotent means... idempotent and state-changing are almost opposites.

~~~
fhars
_You_ don't understand what idempotent means. An action is idempotent if
repeating it does not change the result. For example, multiplying by zero is
idempotent, 0 * x is the same as 0 * 0 * 0 * 0 * x. But of course it changes
something, as 0 * x is clearly not x in the general case.

In the http case, GET and HEAD should not change any state (be safe and
idempotent), PUT and DELETE should change state but be idempotent, and POST
can do whatever it wants.
<http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html>

~~~
axiak
Maybe you saw the text after @marcinw changed his text? I agree with you, of
course I will say that most http GET actions I see are trivially idempotent --
that is to say they are idempotent because they don't change the state at all.

~~~
fhars
No, I saw the original version that cautioned against state changing
idempotent GET requests. The changed version is actually worse, as it only
cautions against non-idempotent GETs, which is not enough. State changing
idempotent requests via GET are quite as bad.

In fact, idempotency is irrelevant for GET, as GET requests should be safe,
which trivially implies that they are idempotent. So requiring idempotency in
addition to safety does nothing except making the prose harder to read.

------
KevBurnsJr
This bit me in the ass once and I learned my lesson.

I was working at a social networking startup and I created a Groups feature
which allowed users to create their own groups with a forum and a photo
gallery and a member list, news feed and so on.

Then one day a user sent us an email claiming her group was displaying erratic
behavior (users randomly banned, posts randomly deleted, etc). It took us
weeks to figure it out, but our ops guy eventually helped us track it down to
Google Web Accelerator, which was pre-fetching URLs displayed on the page via
GET (links labeled "Ban" and "Delete").

This unintentionally effected a similar "Confused Agent" exploit since the app
was misusing HTTP in precisely the manor described in this post.

Google Web Accelerator has since been discontinued for precisely this reason.

<http://webaccelerator.google.com/webmasterhelp.html>

~~~
acdha
Upvote just for being confident enough to mention that - everyone has an
embarrassing learning experience like that in their history.

------
Xk
The example there is one of a cross-site request forgery (CSRF or XSRF). They
pose a solution for POST requests, namely, the "Anti-Forgery Token". This is
the right way to stop CSRF on post forms.

However, this is a defense which works just as well for GET requests. Just put
a nonce in the URL. /do.php?action=delete&id=3&nonce=88e3a6fe57854f2ed18c.
Solves it just as well. (Another common solution is to duplicate the session
cookie in the URL.) It is not bad form to have a get request which changes
state so long as there is a nonce in the URL.

Edit: URL was being truncated.

~~~
Stormbringer
... and you just broke bookmarks ...

Why do people insist on hammering in the screws, and screwing in the nails?

If you want to send data from the browser back to the server, use a post. It
isn't difficult!

Is the motivation behind this secretly that there is some retarded 3rd party
framework in play here that doesn't support post? Something like Ruby on Rails
or Django or some weird ass Java REST library???

~~~
Xk
There's no reason to bookmark the "Delete this email" link (a la SquirrelMail,
RoundCube). Sometimes links make sense to use, and it's possible to safely
make GET requests change state when you need to.

Edit:

Now that I think about it, why would you want to bookmark a link which
modified state? The only time to use a nonce is to make it secure against CSRF
attacks. You can't bookmark them when they're a post anyways, so you don't
lose anything. Am I wrong somewhere?

~~~
TeHCrAzY
Because links are links, and you are setting the wrong expectation by changing
state via one.

~~~
Xk
I would disagree. Go to google, search anything. Notice that clicking a link
is what sets safe search. It's a GET request. It's not all that unusual.

------
cmelbye
As one of the commenters pointed out, CSRF is just as possible with POST
requests as it is with GET requests...

~~~
kenjackson
Why is this so? It seems like I can do a CSRF attack via any BB as just a
normal forum user who can place an href in a message. How does one do that
with a POST? Sorry if this is obvious.

~~~
BarkMore
If the attacker can add a form and script to a page, then the attacker can
arrange for the form to automatically POST using script.

If the attacker cannot add a form and script directly to the forum, then the
attacker can try to trick the victim into following a link to a page where the
attacker can add these elements.

Switching from GET to POST makes the attack more difficult because social
engineering is required, but it does not eliminate the problem.

~~~
jbri
Yes, but the attacker can _not_ get the browser to silently fetch the page
(regardless of whether Javascript is disabled) just by sticking, say, an <img>
tag somewhere.

~~~
weixiyen
Therefore it is important to use tokens.

Another way (or in addition to using tokens) is to not expose hard delete
functionality to the front-end period.

One thing I've done is to create a 'recycle' table in the database with a
unique ID.

Also give every table in your database a deleted column.

If something gets deleted, create a new row in the 'recycle' table and use
that ID to populate the 'deleted' column of all the rows that were deleted.
This way each delete associates itself to multiple rows.

This offers you the ability to "undo" any delete + all associated rows with
the delete from an admin interface that is not exposed publicly to web users.

This way, you have 3 tiers of protection:

\- tokens

\- a soft delete that you can easily undo

\- backup copy of the db if all else fails

------
jwr
It doesn't matter if you use GET or POST. If you don't sign requests, you
don't know where they are coming from.

In the API we've implemented recently in our company (e-commerce search-as-a-
service) we use request signing exactly according to Amazon's AWS specs.

~~~
blantonl
I don't think it is a matter of _where_ it came from, it is a matter of _who_
it came from.

------
app
There are two additional security features POST has that GET does not:

1- POSTs cannot be forwarded

2- some browsers (webkit only I believe) require a client to interact with a
domain before they can POST to it-- this means iframes cannot POST.

When it comes to XSRF, they are equally (in)secure.

------
xd
Don't use GET (<a href="api?deleteId=213">delete</a>) requests for operations
that are intended to modify content. Some browser plugins follow/crawl links
which could inadvertently ruin the users day ;-)

------
3ch0
And dont forget the refeerer header that will contain any GET data. I've
spoted several sites with this flaw by just looking at the data in my visit
log.

------
TimothyBurgess
This is probably an atypical type of thread for HN but I figured I'd share
anyway. It's pretty obvious once you read it but I was a bit curious on the
topic regarding SSL/https and sending data via GET. I'd never thought of
posting an "image" (or whatever) for an admin to see that could contain
harmful data in its URL.

