16

I'm designing api with method that should be an idempotent, and should not modify any data on the server. It should be method that process request and return response for given parameters.

One of the parameters is sensitive data. It's not an option to use additional encryption. Data is already encrypted, but security requirements are very demanding and even encrypted data should be treated very carefully.

According to REST spec, idempotent query method should be implemented as a GET HTTP method. Problem in this case is sensitive data that shouldn't be pass as a GET parameter in URL. Only option in HTTP standard is to pass sensitive data in a body part of HTTP request.

My question is what is better? Broke rest api design, and send query request as a POST, or pass encrypted data in URL? Maybe is there better solution I don't see?

Grandys
  • 163
  • 1
  • 1
  • 8
  • There’s lots out there when Googling `REST API GET with sensitive data` - I’d check that out first. See e.g. http://security.stackexchange.com/questions/29598/should-sensitive-data-ever-be-passed-in-the-query-string for arguments against putting it in the query string - a big one being that URLs and query strings are typically logged on the web server – Pekka Sep 19 '16 at 08:42

1 Answers1

15

According to REST spec, idempotent query method should be implemented as a GET HTTP method.

2016

As far as I can tell with my limited English SHOULD != MUST. You won't break REST API design by sending a POST in this case. You can send your sensitive data in a HTTP header if that is possible. And ofc. you should use HTTPS if you want to send sensitive data to anywhere.

2019

I checked the HTTP 1.1 standard meanwhile. They don't explicitly use the MUST or SHOULD words in the specs for idempotency, but I got the impression they mean SHOULD. Another HTTP related thing here, that we use GET mostly because we can cache response with it. You don't necessarily want to cache sensitive data, so it might not make sense to insist on using GET on retrieval when security is more important by the parameters. You can find some tips about how to set cache-control headers here, but you can read the HTTP standard for that too.

From security perspective my non-expert opinion is the following:

Normally query parameters are not that sensitive, usually they are just random ids or keywords. So maybe the problem is with your design and you should hide these sensitive parameters (e.g. social security number) behind random ids instead of querying them explicitly. Another thought here, that user credentials must be in the Authorization header for example, not in the query string, so if the sensitive data is that kind, then you are doing it wrong.

As far as I understand the issue about sending sensitive data in URLs is that it can show up in browser history, cache, address bar and in server logs unencrypted. Even though many people call REST webservices directly from browser via AJAX (or the fetch API), that is not the intended way they should be used. Webservices are mostly for server side usage to scale out your application to multiple threads, cores or servers. So if you use a server side HTTP client which does not have history or cache to call the REST webservice programmatically, then all you need to do is encrypting your logs. If the client has cache, then you can encrypt that too if you feel it necessary. I think it is possible to filter these params from logs and store the cached content based on the salted hash of the URL, but I don't have much experience with that.

If you have a 3rd party client or a browser where you don't have that kind of control, then you can still assume that it follows the HTTP standard. So you can use the cache-control headers to disable cache for sensitive content. The address bar and history is not a problem by single page applications unless they move the sensitive data to there with the history API, but that can happen no matter what you do. It is possible to disable the Referrer header too. Only if you serve HTML with your webservice will you have a problem with browsers, because that assumes that javascript is disabled (so you cannot use location.replace to override browser history along with the sensitive querystring) and that the browser is your REST client. I think that is a very unlikely scenario, though it is possible to do it relative well with XML+XSL reusing most of the code or nowadays maybe with nodejs or some sort of transpiler on different languages.

So I think this can be solved even without POST if you do everything right. But this is just an opinion, I wait for security expert to correct me...

Community
  • 1
  • 1
inf3rno
  • 24,976
  • 11
  • 115
  • 197
  • 4
    Please pay attention, HTTPS usage doesn't hide or encode url or any GET parameters. They still can be sniffed or logged in the middle. You can use regular POST or send data with custom header parameter like `X-Parameters`. As header as POST body will be encoded with SSL usage. – Aleksandr Ryabov Jan 08 '20 at 11:27
  • 3
    @AleksandrRyabov This is not true. HTTP hides the whole URL, but it can show up in many places after it is decrypted including server logs, browser history, etc... That's why it is better to avoid using sensitive data in URLs. http://blog.httpwatch.com/2009/02/20/how-secure-are-query-strings-over-https/ https://security.stackexchange.com/questions/29598/should-sensitive-data-ever-be-passed-in-the-query-string I don't think this is an issue if you call the REST API from server side, not from browser and the server logs are encrypted. Thanks for your input, I'll edit the answer! – inf3rno Jan 09 '20 at 01:32
  • unfortunately this is true. All the data in query string will be exposed regardless of using encryption. I can see lots of logs without encryption in my security practice (and not logs only). Developer can be responsible for storing data (like logs) at his own server but it can do nothing in the middle. It doesn't matter if request sent from browser or from a server. This is the explanation at OWASP: https://www.owasp.org/index.php/Information_exposure_through_query_strings_in_url – Aleksandr Ryabov Jan 10 '20 at 07:04
  • 1
    @AleksandrRyabov Still 80% of it is browser or HTTP client related, like shoulder surfing or browser history, web logs, referer header, browser cache, etc. If I don't use a browser but a HTTP client library those can be avoided. I could not identify what TBD and shared systems are on the list. I am still not convinced. Can you demonstrate it somehow that this is an issue with custom HTTP clients? For example using this: https://nodejs.org/api/https.html#https_https_get_url_options_callback – inf3rno Jan 10 '20 at 16:58
  • 2
    seems we are loosing the root key of discussion. I focus author on the fact - https scheme does not encrypt any data in query string. It can encrypt just request body. Many of people don't understand how SSL works and they think everything sent with SSL are encrypted, which is wrong. That is why I've specified link to OWASP with full explanation of the issue. Let me specify it again: https://owasp.org/www-community/vulnerabilities/Information_exposure_through_query_strings_in_url – Aleksandr Ryabov Jan 25 '20 at 22:39
  • 2
    @AleksandrRyabov Show me where it writes that HTTPS does not encrypt the querystring. :-) – inf3rno Jan 25 '20 at 22:52
  • I did it twice in the conversation. Please check my references to OWASP above. – Aleksandr Ryabov Jan 26 '20 at 00:13
  • 2
    @AleksandrRyabov Ok. I give up. I already sent you 2 links which contain evidence that the querystring is encrypted with HTTPS. Your link does not say that it is not. It just says that the URLs can be stored unencrypted in different storages and information can be leaked that way. If you don't store them or encrypt the storages or trust the storages, then the problem is solved. Idk. why you have a problem understanding what this vulnerability is about. – inf3rno Jan 26 '20 at 10:45
  • no you doesn't. I can see just a links to NodeJS documentation and outdated 2009 article. Sorry, but they are not relevant links to the issue. My sample describes Risk Factors, Proof-of-Concept and references for testing. I wish you would not follow the description and links at article references. Except that security issue requires explanation from security resources, like OWASP, NIST, MITRE, etc. Only those resources are considering as authoritative ones among security engineers. Please give us references to them. – Aleksandr Ryabov Jan 27 '20 at 19:59
  • 3
    And short answer for the author: data from url encrypted at transport layer but don't at client side which make them vulnerable. In addition to that the leakage could be from http referer: user opens site A on TLS and then clicks a link to site B. If both sites are on TLS, the request to site B will contain the full URL from site A in the referer parameter of the request. As result admin from site B can retrieve full path from the log files of server B). Summary: never store sensitive data in the GET parameters. – Aleksandr Ryabov Jan 27 '20 at 20:00