3

Couple of days back, i came across news about how hackers Stole 200,000+ Citi Accounts Just By Changing Numbers In The URL. Seems like Developers compromised security for being RESTful and also didn't bothered to keep session id in place of userId. I'm also working on a product where security is the main concern so I'm wondering whether we should avoid REST and use post requests everywhere in such a case? or am I missing something important about REST ?

r15habh
  • 1,468
  • 3
  • 19
  • 31
  • 1
    maybe also read: [stackoverflow.com: GET versus POST in terms of security?](http://stackoverflow.com/questions/198462/get-versus-post-in-terms-of-security/198476) – Jacco Jun 16 '11 at 12:21
  • Your question seems to indicate that [REST](http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) requires the use of GET. From [my reading](http://www.xfront.com/REST-Web-Services.html) it seems that REST requires the use of GET for data that the client can not change, and the use of POST for data the client can change. It may be confusing that REST requires the communication to be [stateless](http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_3), while allowing the data to change. – this.josh Jun 16 '11 at 22:33
  • 1
    @this.josh [here's](http://blog.apigee.com/detail/restful_api_design/) a nice intro of RESTful API design – r15habh Jun 17 '11 at 17:46

7 Answers7

5

Don't blame the model for a poor implementation, instead learn from the mistakes of others.

That's my (brief) opinion, but I'm sure better answers will be added :)

(P.S. - using Post doesn't increase the security in any way)

Usza
  • 46
  • 1
  • 8
Nathan
  • 6,095
  • 2
  • 35
  • 61
4

The kind of security issues mentioned in the question have largely nothing to do with REST, SOAP or Web. It has got to do with how one designs the applications.

Here is another common example. Say, there is a screen in an e-commerce application to show the details of an order. For a logged in user, the URL may look like this:

http://example.com/site/orders?orderId=1234

Assuming that orders are globally unique (across all users of that system), one could easily replace that orderId with some other valid OrderId not belonging to the user and see the details. The simple way to protect this is to make sure that the underlying query (SQL etc) has user's Id also added as conjunction (AND in a WHERE clause for SQL).

In this specific case, a good application design would have ensured that the account id coming in the URL is verified with the associated authenticated session.

Ramesh N
  • 138
  • 6
2

The same data gets transmitted across the wire whether you use GET or POST. Here is a sample GET request that is the result of submitting a form [took out User-Agent value because it was long]:

GET /Testing/?foo=bar&submit=submit HTTP/1.1
Host: localhost
User-Agent: ...
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://localhost/Testing/demoform.html

Now here's the same request as a POST:

POST /Testing/ HTTP/1.1
Host: localhost
User-Agent: ...
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://localhost/Testing/demoform.html
Content-Type: application/x-www-form-urlencoded
Content-Length: 21
foo=bar&submit=submit

Note that this is what the server sees when you submit the request or what a man-in-the-middle attacker might see while intercepting the request.

In the GET we see that foo = bar and submit = submit on the first line of the request. In the POST we have to look at the last line to see that...hey! foo = bar and submit = submit. Same thing.

At the browser level, the difference manifests itself in the address bar. The first request shows the ?foo=bar&submit=submit string and the second one does not. A malicious person that wants to intercept this data doesn't care about what appears in the browser's address bar. The main danger comes about because anyone can copy a URL out of the address bar and pass it around thus leaking the parameters; in fact it is very common for people to do that.

The only way to keep our malicious person from seeing either of these types of requests is for it all to be encrypted before it is sent to the server. The server provides the public key which is used (via the https protocol and SSL/TLS). The browser uses the key to encrypt the request and the server decrypts it with its private key. There is still an issue on the client side as to whether the key it received from the server actually belongs to the people running the server. This has to be verified via some out of band trust system like a third party verification or fingerprint comparisons or something like that.

All this is completely orthogonal to REST. Regardless of how you do it, if you are communicating information across the wire with HTTP you are going to have this issue and you're going to need to encrypt the requests/responses to prevent malicious people from seeing them.

stand
  • 3,054
  • 1
  • 24
  • 27
0

I would consider REST and all web applications security concerns very similar.

The problem stated in the question is considered "school" error - something experienced web developer would not do. So if you understand web app security - you'll understand REST security as well.

So add experienced web developer to your team if you don't have any - he'll help you with REST.

Greg
  • 5,862
  • 1
  • 25
  • 52
0

POST requests are no safer than RESTful requests, which are no safer than GET requests.

There are a range of measures to increase the security of your application, that cannot all be listed here. Wikipedia has a good number of them and methods to prevent them.

Here's an example: GET requests shouldn't be used for critical actions such as withdrawing a bank account, because if you're logged into your bank account, someone can set a rouge image with the source as http://yourbank.com/actions/withdraw/300USD , and the URL will be loaded, withdrawing money from your bank account. This is easily countered by using a POST request.

And then, we have some further security considerations to take dealing with this post request, because again it can be spoofed.

foxy
  • 7,599
  • 2
  • 30
  • 34
  • Do you have an explanation or examples of why POST and GET have equivelent safety? – this.josh Jun 16 '11 at 07:23
  • @this.josh I guess this is a little subjective. POST, when used correctly, is safer than GET, but has more limitations. Both POST and GET requests are liable to the XSRF, especially on older browsers with less strict security rules. In POST requests, instead of an image being used as the vector of attack, some Javascript code is used. – foxy Jun 16 '11 at 07:31
  • And neither stand up to an attacker with a proxy - check @stand's answer :-) – Rory Alsop Jun 17 '11 at 09:50
  • @Rory, you need to be using the proxy in order for the attack vector to work. And who in their right mind would go about using some untrusted proxy for their confidential data? Properly using POST instead of GET can, however, prevent XSCF and XSS attacks. – foxy Jun 17 '11 at 10:18
  • I agree POST helps, but your comment about proxies is mostly irrelevant as an attacker can place proxies into the path relatively easily in many circumstances. And in the case of this attack, the attacker was a valid authenticated user who could have used their own proxy anyway! – Rory Alsop Jun 17 '11 at 11:30
0

Using POST instead of GET as a security measure is simply a use of "security through obscurity". In reality it is no safer as any one with a small amount of knowledge of HTTP can forge a POST request.

Using sessions ids instead of user ids is also just another way of obscuring the security hole, it's not really fixing the problem as session ids can be hijacked too.

The fact that in this particular case security hole was made extremely easy to exploit by changing the URL does not make the use of REST the cause of the security issue.

As others have mentioned, whenever you need to secure REST services, HTTPS is the place to start looking.

Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • HTTPS wouldn't have been much better, since you can still change the user ID in the URL... – tc. Jun 19 '11 at 02:59
  • @tc I wasn't trying to suggest that HTTPS removes the need for authorizing access to resources. It just enables to you securely authorize access. Whether the userID is in the URL or not is irrelevant. – Darrel Miller Jun 19 '11 at 12:34
  • 1
    It would not have helped Citibank in the slightest, and in the current "ecosystem" HTTPS mostly protects against things like FireSheep. Perhaps Citibank even used HTTPS; I haven't seen anyone give the actual URLs used. – tc. Jun 19 '11 at 14:07
-1

If security is the main concern, exclusively use https:// and POST, never http:// and GET.

This will avoid the attack you describe as well as many others such as session hijacking, and simple eavesdropping on the line.

(... and, abstain from making the mistake of authenticating with https:// and switching to http:// later, which was "de facto standard" until a few months ago when someone published a tool which did the obvious)

Damon
  • 67,688
  • 20
  • 135
  • 185
  • You've got this all wrong. Even with https and post, the hackers would accomplish the same thing. Remember that they were already authenticated as another user. – k_b Jun 16 '11 at 07:00
  • That's the point. If you use https:// and POST everywhere, exclusively, with no exceptions (and follow very basic security practice otherwise), then authenticating or impersonating another user is not possible other than by breaking the cryptographic algorithms. Which, frankly, is beyond the scope of most people. The system only becomes _trivially_ attackable if you do stupid things like authenticating via SSL and then redirecting to a plain normal http connection with a session-id in the URL (which a _lot_ of people used to do until recently). – Damon Jun 16 '11 at 07:14
  • 3
    No, their problem was that if authenticated as one user (which they obviously owned themselves), you'd have access to other users' data as well. That has nothing to do with either https or post. – k_b Jun 16 '11 at 07:22
  • 2
    _"So if the URL was something like citibank.com/user/12345, all you had to do was change it to citibank.com/user/123456 and you had access to all of their account information."_ -- That is _exactly_ the problem of HTTP/GET. A randomly generated session id of non-trivial length transmitted via HTTPS/POST which the server maps to a corresponding user cannot be exploited in such a manner. – Damon Jun 16 '11 at 07:27
  • No, that's not a get problem. It would be almost as easy doing the same exploit with a post. The problem is the lack of access restriction in the authenticated session. Remember that authentication and authorization are two different things. In this case, the latter is the problem. – k_b Jun 16 '11 at 07:37
  • In one case, _the user_ says "Hello, I am user 1234" via the URL, and the server trusts that claim. And, which is worst, the attack does not even need any particular computer skill or even a special tool, all it takes is someone wondering "what if I change my account number in the address bar?". In the other case, the user authenticates via a secure connection (via a password or whatever), and _the server_ is authorative of what precise account this particular encrypted connection maps to. How can those two entirely different things be the same? – Damon Jun 16 '11 at 07:51
  • 'citibank.com/user/12345' does not equal to 'I am user 12345', but 'I want to see the profile for user 12345'. Based on the authenticated user session, it's up to the server to check whether I am that user or whether I am a bank admin authorized to view customer profiles. If I am user 54321, I should simply be denied access, and the attempted exploit should be logged. Citibank obviously only checks whether a user has an authenticated session, which obviously isn't enough. In that case, specifying the user id through a post isn't helpful, since I can forge that quite easily. – k_b Jun 16 '11 at 08:09
  • 2
    Using POST or GET is really quite irrelevant from a security point of view. You should be using the HTTP verbs in manner that correctly follows RESTful principles. If your using them as a security feature of your app, you need to stop your coding and find another job. Use proper security measures to secure your app and use HTTP properly to make design/maintenance/etc easier and quicker. – James Butler Jun 16 '11 at 11:41
  • @James Butler: Funny you should say that, because the Citibank guys have _exactly_ followed RESTful principles and maintained no state. Which is the entire problem. As for GET vs POST, I recommend spending a few thoughts about account or session information being world-readable and listed in webserver and proxy logs. HTTPS/POST hides this information _and_ all other exchanged information _and_ maintains some authentication state. It does not magically prevent a programmer from being stupid, but it prevents the most trivial sniffing and spoofing attacks, and it keeps secrets secret. – Damon Jun 16 '11 at 14:17
  • 1
    @Damon: No No No No No No! The entire Citibank problem was caused by weak or non-existent authentication! Using POST just endears a false sense of security. Trivial sniffing is prevented by using SSL. POST also does not maintain any state by itself. Whatever you state you think you are maintaining by doing this would be better achieved by using HTTP headers. – James Butler Jun 16 '11 at 15:43
  • @Damon - using POST in this instance would not have affected the results at all. Instead of changing the parameter in the URL, the attackers would have just changed it using a proxy. The authentication model was at fault here. – Rory Alsop Jun 17 '11 at 09:53