19

It's well known that GET requests with ?xx=yy arguments embedded can be altered in transit, and therefore are insecure.

If I change the request to POST, and use HTTPS, then the parameters are in the body of the message, which is encrypted, and therefore difficult to hack, correct?

Two more cases concern me. Suppose GET style parameters were added to a POST request - would those parameters be reliably ignored?

What about some sort of security downgrade attack? If the URL manipulator forces HTTPS transactions to fail, and then the client/server "helpfully" downgrade to HTTP, which would allow the unencrypted POST body to be manipulated.

9
  • 17
    POST requests are not more secure than GET requests in transit. Why would you want query parameters to be ignored? You may consult the HTTP specs. Commented Jun 26, 2020 at 1:14
  • 53
    "It is well-known" - Citation needed!
    – user163495
    Commented Jun 26, 2020 at 5:45
  • 11
    The question comes off as if it's documented somewhere. I would heavily recommend on understanding better how HTTP methods work and what TLS does to the HTTP request. Maybe see it in action using wireshark. I am saying this after seeing that @ThoriumBR 's answer covers the question properly (more of how to get a better understanding of what's happening).
    – Elie Saad
    Commented Jun 26, 2020 at 5:51
  • @multithr3at3d I'm concerned about parameters being altered in transit. If I use POST and SSL, that becomes much harder to do, but if MITM can add ?xx=yy parameters to a POST url, and they are not ignored, then the encryption could be moot.
    – ddyer
    Commented Jun 26, 2020 at 19:38
  • 16
    @ddyer As far as MitM is concerned, there is no difference between POST body and GET parameters. Both are protected with HTTPS, and unprotected without. There are now 5 answers explaining as much, but you seem hell-bent on arguing. I'm honestly wondering why you even asked this question if you're not going to accept our answer?
    – marcelm
    Commented Jun 27, 2020 at 10:42

7 Answers 7

64

TL;DR: HTTPS provides encryption, and it's the only thing protecting the parameters.

It's well known that GET requests with ?xx=yy arguments embedded can be altered in transit, and therefore are insecure.

If you are not using encryption, everything is insecure: HTTP, Telnet, FTP, TFTP, IRC, SNMP, SMTP, IMAP, POP3, DNS, Gopher...

If I change the request to POST...

...it does not change anything at all.

and use HTTPS...

HTTPS changes everything.

Any HTTP request not protected by TLS is not protected. No matter if you use GET, POST, PUT, if it's a custom header, none changes a thing.

For example, this is a GET request:

GET /test?field1=value1&field2=value2 HTTP/1.1
Host: foo.exam
Accept: text/html

And this is a POST request:

POST /test HTTP/1.1
Host: foo.example
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

field1=value1&field2=value2

What is the difference? On the GET request, the parameters are on the first line, and on the POST, the parameters are on the last line. Just that. The technical reasons behind GET or POST are not the point here.

Suppose GET style parameters were added to a POST request - would those parameters be reliably ignored?

It depends entirely on the application. On PHP, for example, if the application expects $username = $_POST['username'], sending it as GET parameter changes nothing at all, as the application will get the POST parameter.

What about some sort of security downgrade attack? If the URL manipulator forces HTTPS transactions to fail, and then the client/server "helpfully" downgrade to HTTP, which would allow the unencrypted POST body to be manipulated.

Not easy for properly configured servers. If they use the HTTP Strict Transport Security header, it forces the client to only access the site using HTTPS, even if the user forces HTTP and port 80. The browser will helpfully upgrade to HTTPS, not the other way.

Even on servers that not use HSTS headers, if the first access is done via HTTPS, it's not trivial to downgrade to HTTP. The attacker must send a faked certificate, and the client must accept the faked certificate in order to an HTTPS connection be redirected to HTTP. But if the attacker succeeded on this, he will usually keep using HTTPS as the client already accepted his fake certificate anyway.

1
  • Comments are not for extended discussion; this conversation has been moved to chat.
    – Rory Alsop
    Commented Jul 6, 2020 at 10:56
35

No, no, no.

HTTPS protects the whole HTTP request. The url path, the parameters, cookies, http headers, the body... The only thing it doesn't protect (other than tcp parameters like ip addresses and ports) is the hostname you are connecting to, which is leaked through the SNI extension (this should be fixed by tls-esni, just a draft for now)

As such, when using HTTPS, sending "sensitive" parameters (such as user and password, or bank account to bill) in GET is not insecure because an attacker could change it.

(and if not using HTTPS, it is a bad idea even with POST)

However, it is nonetheless problematic.

  • GET parameters are part of the url, and appear in the server logs, your browser history, website analytics, the page printing, an antivirus analysis of the page...
  • GET requests are defined to be idempotent. Retrying a GET request (even automatically) shall not have side-effects. You can imagine what could happen if the request meant "please transfer this amount to account ###"
  • On the other hand, POST doesn't have this behavior. You will surely have noticed your browser warning you before resending a POST request, warning of the actions triggered by that potentially happening again.
  • Having certain parameters through GET could help with session fixation attacks (like having you load a url logging you with the user and password of the attacker, prior to charging "your" online credit)
  • In general, it's much easier to have someone load a page with some parameters than through POST (still possible using javascript, though, use anti-XSS tokens).

Suppose GET style parameters were added to a POST request - would those parameters be reliably ignored?

It's up to the website. They may accept some parameters only as GET and others only as POST, but also accept some as either GET or POST. If the a parameter with the same name is provided both ways, they would probably choose the POST one, but it could be configured to use GET, or error out as well.

What about some sort of security downgrade attack? If the URL manipulator forces HTTPS transactions to fail, and then the client/server "helpfully" downgrade to HTTP, which would allow the unencrypted POST body to be manipulated.

A client that automatically downgraded a HTTPS request to HTTP (which as you note, can easily be done by an attacker on the network) is complete and utterly broken. Please file a CVE for that.

1
  • 2
    "GET parameters are part of the url, and appear in the server logs, your browser history, website analytics, the page printing, an antivirus analysis of the page..." This is extremely important to consider if you are bound by HIPAA laws. Exposing an SSN or other PHI to an outside entity can result in millions of dollars of fines. It's a real pain, but use POST if your requests need to use SSNs or other PHI.
    – Kriil
    Commented Oct 26, 2021 at 17:06
20

It's well known that GET requests with ?xx=yy arguments embedded can be altered in transit, and therefore are insecure.

This is generally a reference to situations where GET requests get recorded in history logs, including local browser and possibly content inspection software or proxies. Otherwise there's no functional difference in security towards using HTTP GET vs POST requests over TLS.

Two more cases concern me. Suppose GET style parameters were added to a POST request - would those parameters be reliably ignored?

Entirely depends on your application's code.

What about some sort of security downgrade attack? If the URL manipulator forces HTTPS transactions to fail, and then the client/server "helpfully" downgrade to HTTP, which would allow the unencrypted POST body to be manipulated.

You can tackle those under HTTP by using Strict Transport Security (HSTS) optionally with preload. This instructs browsers to refuse to access a given site in HTTP... within a certain timeout. And there's an initial request that, unless you're using preload the browser needs to learn that HSTS is enabled.

7
  • it is undesirable for the whole site to go dark if SSL fails. Maintaining valid SSL certs is a treadmill in itself. I suppose you can't have it both ways!
    – ddyer
    Commented Jun 26, 2020 at 19:33
  • 18
    SSL is not that hard these days.
    – fraxinus
    Commented Jun 26, 2020 at 21:11
  • 2
    @ddyer, just install letsencrypt certbot (physical or virtualized servers) or cert-manager (orchestrated clouds) and let it take care of things.
    – Jan Hudec
    Commented Jun 27, 2020 at 9:52
  • 3
    There is no reason today to not use TLS. Neither performance nor availability are valid reasons. Apologies for disagreeing directly but these are old school arguments that do not hold water. TLS services fail just as well as plaintext ones do.
    – Pedro
    Commented Jun 27, 2020 at 11:04
  • Also apologies @thoriumbr since I've just realised a lot of what I wrote was on your answer.
    – Pedro
    Commented Jun 27, 2020 at 11:05
7

If you see the URL in browser, it doesn't mean that the URL is sent over the network in such form. In case of HTTPS an attacker can only see the target host and port of your request. The attacker cannot see anything more like method, URL, headers, body.

If you use HTTPS, your data cannot be changed on the way to the destination host and port. This holds also for the URL: It is not visible to anyone and cannot be manipulated.

The URL is visible only on the server side, after the server decrypted your request.

11
  • 3
    but they can be seen and manipulated by inserting a man in the middle between the intended server and the client - no. If the client is implemented properly, it requests the certificate of the server, verifies that it is valid. Then encrypts the traffic. MiM is not possible. Of course you can manipulate your network, DNS. Or you can directly install the certificate of the MiM, if you want to help them to read your traffic :) But for applications that implement TLS/SSL properly and that are configured properly (e.g. no certificates of malicious CAs in the trust store) MiM is not possible.
    – mentallurg
    Commented Jun 26, 2020 at 16:18
  • 11
    @ddyer A valid certificate can only be created by a CA that the client already trusts. So unless you can somehow manipulate the client device into trusting your MITM CA, you cannot generate a valid certificate.
    – kicken
    Commented Jun 26, 2020 at 21:18
  • 1
    @ddyer: Any operating system (Windows, LInux, MacOS, Android) have pre-installed CA certificates. If you create a certificate and try to say you are Google and certificated is issued by Verisign or other trusted CA, it will not be trusted, because the device (and all software on this device) know the real certificate from Verisign. Such top level CA certificates are pre-installed on any OS (WIndows, Linux, Mac, Android). It will take much efforts for an attacker to force user to accept untrusted certificate. But this is another story. Post a question about it, and we can discuss :)
    – mentallurg
    Commented Jun 26, 2020 at 22:26
  • 1
    @ddyer: 1) Who issued your certificate? A user has preinstalled CA certificates of such CAs like Comodo, DigiCert, GeoTrust, GlobalSign, Thawte etc. No matter what happens with DNS. If the issuer of the certficate is not trusted by the user (is not installed in the trust store), the certificate will not be trusted and thus TLS/SSL connection will not be established. 2) If you want to present some certificate issued by a trusted CA but not belonging to some other site, you cannot prove that you are the owner because you don't have the private key for it. Again, no TLS/SSL will be established.
    – mentallurg
    Commented Jun 28, 2020 at 1:11
  • 1
    @ddyer An SSL cert says which domain name it is for. When you provide the wrong cert, the browser shows an error page. You can test this by adding a line to your system hosts file to set the IP of some site equal to the IP of some other site.
    – Boann
    Commented Jun 28, 2020 at 4:18
4

With HTTPS, the entire HTTP request passes thru the encrypted SSL pipe, so both GET and POST parameters, and the URL path, and cookies, and all other parts of the request are protected against MitM tampering in transit.

This can't guarantee that the server and client are uncompromised, but it means you don't have to trust every random computer between the two.

The host name and port number are observable by a MitM, but they cannot be tampered with, except by killing the connection.

Traffic timings and (padded) sizes are observable, and this information could be used by a motivated observer to infer what is being transferred. E.g., a big file might be video, or a specific file size corresponds to a specific file.

Systems do not automatically drop back to HTTP if HTTPS fails; that would be catastrophic. Without SSL, nothing whatsoever is protected against total recording and/or modification.

3
  • The case that interests me is where the client has hacked his own computer to insert a MITM for the purpose of attacking the server.
    – ddyer
    Commented Jun 27, 2020 at 22:26
  • 1
    @ddyer SSL only protects data in transit. It does not attempt to assert dominion over the computers at either end. You cannot completely secure a computer in someone else's house. It is impossible to stop a sufficiently motivated user sending any modified request they want, by creating a custom client or modifying yours. SSL will make that more frustrating, but not impossible.
    – Boann
    Commented Jun 28, 2020 at 0:18
  • that's what I thought too. Ya can't trust those clients!
    – ddyer
    Commented Jun 28, 2020 at 1:07
1

Other answers being good regarding SSL (it is called TLS these days, but who cares), they almost bypassed

Suppose GET style parameters were added to a POST request - would those parameters be reliably ignored?

No. There are even application frameworks that allow for free intermix between URL and request body parameters in a POST request.

In JavaEE, for example, one have to do some extra work in order to determine if a specified parameter came from the URL or from the request body. And generally no one cares.

It doesn't matter from the security standpoint either - whoever can pass URL parameter to the server can pass a request body parameter as well. If the connection is unencrypted, a man in the middle can mangle it however he sees fit.

If the connection is encrypted with SSL/TLS, it is encrypted as a whole, before any HTTP interaction can happen and it stays encrypted until it is closed.

The only thing a man in the middle can do to a properly encrypted connection is to break it. (Well, one can also exploit some protocol or implementation vulnerability, but they are rare these days)

1

In addition to the other answers, there is another dimension of security to consider, and that is to do with what happens to the URL. None of the following allow the values to be intercepted or changed, just indicate where they could be read. All of these also apply equally to HTTP and HTTPS; the presence of HTTPS does not mitigate any of them.

  1. Even using HTTPS, the full URL is transmitted to any third party servers that load components on the page through the referer header. This means that any GET parameters could potentially be exposed to third parties. This can be mitigated by setting a Referr-Policy on your request.

  2. Web servers typically log HTTP requests in the file system. By default, these are configured to log the URL that was sent to the server, which means that any GET parameters could be visible in your logs and available to whoever has access to them. Some proxy servers also log URLs that have been visited (but the fact that a proxy server can see your encrypted traffic is another level of trust altogether).

  3. Your browser may cache a list of URLs that you have visited, which would also include the GET parameters.

1
  • Plus some MitM-Proxies which are common in corporate settings (and break the TLS end to end protection with fake trusted CAs) might log the requests (like servers) and are less likely to log the whole body. it's a common compliance requirement to not send sensitive data in the URL even when the https protection does work in principle. Especially since they also can end up in bookmark files or might be sent to shortened services or things like reputation checkers. Not to mention the useability aspect of URLs which are not easily readable.
    – eckes
    Commented Jun 29, 2020 at 8:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .