45

I have 2 choices in sending data between 2 web applications.

  1. I encode the data in Base64 and append to the URL and retrieve these parameters at my destination application and decode the parameters.

    For eg., http:/myDomain/someCode/pages/somePage.jsf?pin=MzAwMDY3MDI2OQ

  2. Send the parameters as hidden values from application1 to application2.

    String res=(String)request.getAttribute("paramValue");
    document.myForm.action='myDestinationURL';
    document.myForm.method="POST";
    document.myForm.submit();
    
    <form name="myForm" method="post">
    <input type="hidden" name="paramValue" value="<%=res%>" />

In Choice 1, one can know the parameters that am sending and my Encoding technique. In choice 2, one can view the data that am sending by doing a view source easily.

Apart from above things, what possible ways exist for an intruder to know my system better? And which option is more suitable in general for a developer? Choice 1 or Choice 2?

Ali Ahmad
  • 4,784
  • 8
  • 35
  • 61
Vikas V
  • 693
  • 8
  • 12
  • The most complete answer I have seen until now to this question is [this answer](https://stackoverflow.com/a/1744404/6640924) from [@roman-starkov](https://stackoverflow.com/users/33080/roman-starkov). – rbelow Apr 06 '21 at 13:23

6 Answers6

46

Option 1 may introduce a number of non-security related issues anyway:

  • The resulting URL may be cached by the browser, or bookmarked, causing users to resubmit.
  • The resulting URL may be shared by users, causing third parties to submit.
  • The URL may be sent to your browser vendor, who may hit the site.

But this is about security, and it introduces a few risks not present in option 2:

  • The URL with its parameter may end up in the proxy logs of everything along the way, revealing your data.
  • Your decode function is now an additional attack vector. (Does it handle unicode correctly? Does it have length restrictions?)
  • You may be tempted to think of your encoded string as somehow secure, when it's just security through obscurity (and not very much obscurity), or perhaps more appropriately, security theatre.

That said though; they are otherwise largely equivalent in the security they offer. They both submit plain text data in the HTTP header, and base64 isn't exactly rocket science (and you can base64 encode your POST version).

Neither offers any meaningful protection for your data.

If it's information you don't want the user to see; why are you sending it to the user to begin with? Consider the architecture you're using and see if there's a way to simply remove the risk entirely by not handling that information on the client side.

So, to answer the question: with regards to sending data - both reveal the same information to an attacker; choose whichever option is more appropriate for the situation (this Treehouse blog post may help with that), but you should not rely on either method to actually protect anything.

Bob Watson
  • 2,856
  • 17
  • 29
17

It is easy to make cross-site GET requests by including a simple <img> tag in a Web page. For instance, in a page from www.evilhacker.com, some Javascript produces a long stream of <img> tag with attacker-chosen paths, all pointing to www.targetbank.com -- and your browser will include the bank cookie in all the requests.

This alone means that you'd better not support GET requests which implies any modification on the target site. As a general rule, GET requests should be reserved to operations for which replay attacks are not a problem -- i.e., in practice, read accesses to static data only.

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • 7
    +1 - It's still easy for someone from `evilhacker.com` to have you insert POST parameters (e.g., use javascript to submit a hidden form when you load a page), which is why CSRF (cross-site request forgery) protections are necessary; typically a secret CSRF token tied to the user/session being present in the POST variables before the action is done. The difference is that if you go to nearly any discussion forum that allows users to include images you are susceptible to GET attacks. (Granted here on SE, all included images are hosted by SE so should be safe). – dr jimbob Feb 12 '13 at 15:46
  • Cross site POST request are not much harder then cross site GET requests. Especially if JavaScript is enabled, the form can be submitted without any user interaction at all. – Hendrik Brummermann Feb 13 '13 at 09:07
  • 1
    @HendrikBrummermann I think they are considerably more difficult to execute in many cases. I can make you submit a GET request wherever I want with an `` tag on any page you load. Lots of sites let you embed images from external hosts, including this one, meaning I don't even have to convince you to go to my website. Not so many let you embed arbitrary JavaScript. – Tom Marthenal Feb 17 '13 at 06:45
11

Use POST to send requests that modify data at the server.

By the HTTP specification, GET requests (e.g., parameters in the URL) should only be used for requests to retrieve (hence the name GET) but not modify data. POST requests (non-visible parameters, but still unencrypted in the HTTP request) should be used whenever the request creates/updates/modifies data that's to be stored in the database (other than standard logs). This makes it slightly harder for attackers to do cross-site request forgeries, as well as less likely to accidentally double-submit or store secret information in your web page history/web server logs.

Is the pin variable a secret?

What you are doing at the moment seems like it could be unsafe depending on the meaning of the pin variable. Does this need to be kept secret from potential eavesdroppers or could people intercepting the pin do some sort of attack with it? If so, only use HTTPS (for end-to-end encryption over the transport layer) for every request with this secret data. The base-64 value you used seemed to be 3000670269 (granted I had to append two equal signs to make it a proper b64 encoding).

What would happen if an attacker tried using other pins?

Let's say my pin='300670269', but to test your system I sent MzAwMDY3MDI1OQ (for pin='3000670259'). Would that let them effectively break into another users account? If so, at the very least, you should do something like have an extra POST variable like checksum=SHA256(pin+secret_server_side_string) where secret_server_side_string is some long random string (e.g., something like de10RRORX50UAUhx0dDIxJnzXKBAs68yjdWVz8QQ - 40 random upper+lower+numbers characters has lg(62)*40 = 238 bits of entropy), and your applications only act on the pin if the checksum matches the pin. Your application should generate the checksum (without revealing the secret_server_side_string to the client). You also have to be careful that your application does constant-time string comparisons when checking the checksum with the pin, so your application isn't vulnerable to timing attacks.

dr jimbob
  • 38,768
  • 8
  • 92
  • 161
3

There is an recent interesting attack that has been exploited to evade Web Application Firewall Rules known as "HTTP Parameter Pollution attack". I will explain with an example like

POST /index.aspx?par=1&par=2 HTTP/1.1
User-Agent: Mozilla/5.0
Host: Host
Cookie: par=5; par=6
Content-Length: 19
par=3&par=4 

For this Post Request Application behavior will depend on the developer and like for java.

  1. javax.servlet.ServletRequestInterface(Query String direct parsing)
  2. java.lang.StringgetParameter(java.lang.Stringname) Returns the value of a request parameter as a String, or null if the parameter does not exist
  3. java.lang.String[] getParameterValues(java.lang.Stringname) Returns an array of String objects containing all of the values the given request parameter has, or null if the parameter does not exist.
Ali Ahmad
  • 4,784
  • 8
  • 35
  • 61
3

In addition to Bob's answer, there is another security disadvantage when making use of GET requests with sensitive parameters.

The URL, which includes the sensitive information, is sent to third-party web servers hosting resources referenced by the resulting HTML page.

Example:

First request:

GET /someCode/pages/somePage.jsf?pin=MzAwMDY3MDI2OQ HTTP/1.0
Host: domain

Response to that request:

HTTP/1.0 OK
Content-type: text/html

<img src="http://thirdparty/hello.jpg" />

The web browser renders the HTML and tries to get the image as follows:

GET /hello.jpg HTTP/1.0
Host: thirdparty
Referer: http://domain/someCode/pages/somePage.jsf?pin=MzAwMDY3MDI2OQ

This can be especially a problem when the HTML rendered on the page is attacker controlled (to a certain extent, having whitelisted html). For example, a web mail service that places the session in the URL would allow attackers to send an image in the HTML body of the email pointing to the attacker's web server / script. Then the attacker has to just follow the URL in the Referer header sent by the victim's web browser when rendering the image. This sort of vulnerability did in fact affect Excite mail (we're talking history here :) ) and some other webmail services in the past.

Sandro Gauci
  • 456
  • 4
  • 5
0

Another security factor to consider is that the webserver's access logs will typically capture the URLs that were requested, including query string parameters. If you don't want the query string to be logged, you may need to resort to a POST request.

There are, of course, non-security-related factors to consider when deciding between GET and POST requests, such as the browser's behaviour when reloading the page, or when the page is recalled via the browser's Back button.

200_success
  • 2,144
  • 2
  • 15
  • 20