13

Should I use GET or POST for retrieving sensitive data, given that:

  • The response will contain sensitive data.
  • There are side-effects to the request (such as explicit accountability logging).

The RFC 2616, to me, doesn't clarify this for me:

9.1.1 Safe Methods

Naturally, it is not possible to ensure that the server does not generate side-effects as a result of performing a GET request; in fact, some dynamic resources consider that a feature. The important distinction here is that the user did not request the side-effects, so therefore cannot be held accountable for them. [...]

Community
  • 1
  • 1
JJ Zabkar
  • 3,792
  • 7
  • 45
  • 65

6 Answers6

14

A step back

First of all, the RFC 2616 is obsolete. Hence, it shouldn't be used as a reference anymore.

Below you'll find the current references for the HTTP/1.1 protocol:

The safe property

Have a look at what the RFC 7231 says about safe methods:

4.2.1. Safe Methods

Request methods are considered "safe" if their defined semantics are essentially read-only; i.e., the client does not request, and does not expect, any state change on the origin server as a result of applying a safe method to a target resource. [...]

This definition of safe methods does not prevent an implementation from including behavior that is potentially harmful, that is not entirely read-only, or that causes side effects while invoking a safe method. What is important, however, is that the client did not request that additional behavior and cannot be held accountable for it. For example, most servers append request information to access log files at the completion of every response, regardless of the method, and that is considered safe even though the log storage might become full and crash the server. [...]

Of the request methods defined by this specification, the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe. [...]

In the context of HTTP methods, safe is not related to security and, in a similar way, safe is not about how you deal with sensitive data. Safe means read-only.

As stated above, the use of safe methods do not prevent you from performing operations that are not read-only, such as logging the request to a file. However, this operations should be transparent for the client.

Which method should you use?

It depends on the operation you are performing. In REST APIs, the POST method is frequently used to create resources while the GET method is frequently used to request a representation of a resource.

And how about security and sensitive data?

If you want to ensure security when sending sensitive data over the wire, use HTTPS and don't expose sensitive data (such as passwords) in the URL.

Community
  • 1
  • 1
cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • 5
    The Point is `use HTTPS and don't expose sensitive data (such as passwords) in the URL.` – Yohanim Jun 24 '21 at 09:32
  • 2
    How exactly does this answer the question? Both creating resources and requesting representations of resources can return sensitive data, no? – avisk Jul 27 '21 at 19:37
  • 1
    For along time JSON responses with sensitive data should only be permitted from POST, because a malicious script can generate a valid GET from the user's browser and capture the JSON response. That is not possible with a POST. Is that no longer possible? Can we be sure all users are on browsers that now prevent this? I still wouldn't return sensitive JSON data from a GET. HTTPS doesn't protect from this type of attack. – AaronLS Dec 10 '21 at 21:19
8

In addition to Cássio Mazzochi Molin's excellent answer, you should use HTTPS but you should (generally) use:

  • GET for retrieving sensitive data.
  • POST for sending sensitive data.

The reason to use GET when retrieving is that the action does not have side-effects, therefore there is no reason to use POST. The only previously applicable reason to use POST was when retrieving JSON via AJAX, because old browsers had bugs meaning that another domain that the user had open in their browser could steal the data from the JSON using a <script> tag (JSON Hijacking). Disallowing GET prevented this attack because <script src="..."> always uses the GET method. See this answer. Note that using POST here means you should disable GET server-side for this method.

The reason to use POST for sending sensitive data is that it prevents data leakage via the query string (although another way would be to use GET with custom headers set, although POST makes much more sense). The reason is that query string data in the URL is logged by proxy servers, by server logs as default, and can also be stored in browser history, making it not a great place to transmit personal or otherwise sensitive details. Note that during transit over HTTPS they would be encrypted, it is just that they can leak from the encrypted state into other non-encrypted or non-controlled locations. Of course, going back to RFC 7231, if you're making changes based on this sent sensitive data, POST is the better idea as it'll prevent the browser accidentally sending it again in most cases.

One more reason to use POST is that modern browsers don't appear to cache the results of POST requests by default. However, this should not be relied upon. It is much better to set Cache-control: no-store header in your response either way, any time that sensitive data is output.

Community
  • 1
  • 1
SilverlightFox
  • 32,436
  • 11
  • 76
  • 145
  • What should you use if you're sending and retrieving sensitive data in the same request? – avisk Aug 18 '21 at 21:47
  • 1
    `POST` because then you're not putting sensitive information in the query string. The request method doesn't affect how data is returned. – SilverlightFox Aug 22 '21 at 13:32
  • may I know if I still can use GET with request body ? (the endpoint needs sensitive data) but operation is just normal read. – Andre Suchitra Jan 21 '22 at 03:59
  • @AndreSuchitra That's known as a "fat" GET. You will probably encounter problems doing this, as devices such as proxies, browsers, caching layers, etc, won't be expecting a request in this format. Problems could range from users being served cached pages rather than reading the data requested by the body parameters, to requests not working at all. If you're concerned about referrer leakage, data caching, or browser history logging, I'd recommend to use POST for this operation, although refer to my answer regarding taking proper precautions regarding caching. XHR is also safer. – SilverlightFox Jan 23 '22 at 10:32
1

I would suggest using POST, not for any real technical reason, like side-effects, but rather because servers are often configured to watch POST calls more, and many off the shelf security modules consider POST as the place where the action happens.

Thats not really a great technical reason, but I would be interested in seeing what others think.

Kyle Olds
  • 11
  • 1
1

If the data is highly sensitive, consider using a POST. It's easy to issue a GET request without much thought - for instance if someone is looking at log file while logged in to the application with appropriate permissions and they click a link, they would generate a get request.

You can instead ask the client to construct a document you could call a 'sensitive data access request'. Potentially you could require a field with the reason for looking at this data. The server could receive this request and send the sensitive data in response.

Depending on the type of client application the users have access to, it might be much easier to demonstrate intentionality if a user sends a POST request than if they send a GET request.

bdsl
  • 288
  • 2
  • 9
0

You should use GET for retrieving information from the server.

Auditing and logging would not be considered side-effects since they are transparent to the client.

Securing the response data can be done using SSL and "Cache-control: no-store". Once the sensitive data gets to the client, there's no way to stop them from doing whatever they want with it.

Brady Olsen
  • 682
  • 7
  • 6
0

Using POST would only make sense as part of an application designed to prevent a user from repudiating receipt of the response. I don't know of any such schemes, and I wouldn't hazard to devise one off the top of my head.

The intent of the user's request isn't to create an audit log entry; the intent is to get the response. The accountability log is a side effect, but it's hidden from the user, so POST is not required.

In other words, you can't hold users accountable for getting the data, because you can't prove they received it. But knowing who requested the data might help an investigation, so recording it as a side effect is still useful.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • Using POST doesn't necessarily mean that the user actively requested the data. Consider a cross-domain POST made either by AJAX of via a form submitted by JavaScript. Even in the first case, the Same Origin Policy does not prevent the POST from being made, it only prevents any data returned from being read. – SilverlightFox May 20 '16 at 09:39