This question is a mirror of a bug report I made on parse’s help forum
Now, I know that the one on parse’s site is not a question but a report, and I do not want to leave here just a mirror of the report, but just check that my concerns are well-founded, with people that probably have more experience with me.
The problem is that it seems like parse is not generating the HMAC signature in the right way.
- First test: I took a proxy (Charles proxy), set up a breakpoint on an update request and change a field leaving the signature untouched. Execute the request. The server accept the request and the fields are updated accordingly to it (even the field modified in the breakpoint of course).
- Second test: instead of modifying the request i just changed the signature to make sure the server is actually testing the signature value, the request got rejected as expected.
- Third test: Instead of modifying just the value of an existent field, add a fresh new field to the request and execute. The server accept the request, updates the field, if the field added doesn’t exist it adds it to the updated row, otherwise it just update it.
Now, are my concerns well-founded? Did I misunderstand the OAuth RFC in any parts regarding the signature generation? How is it possible that Parse’s employees/users do not ever notice such a HUGE bug?
Please, I know that this question can generate a broad discussion, but since the importance of this question (and not only for me, but for all parse’s users) leave the time for someone informed to leave a valid response.
I’m digging inside Parse iOS SDK to find out why this is actually happening. After some research and a little of reverse engineering of their static library I found that they are using a modified (probably they just modified the names of the methods prefixing them with ‘PF’) library called OAuthCore. After having discovered this I’ve got the confirmation by looking to an old open source version of their SDK (found googling for the modified library names). Now, the library does its job and work as expected, sticking enough to the RFC. The problem is that, obviously, OAuth does not cover the entire HTTP request but just part of it. What I was expecting, and how should be IMHO, is that when you make a request for updating a field (or making a purchase? logging in? Send sensitive data?) the ‘dirty’ fields should be sent as request’s parameters, so that they would be included in the signature/verification process done through the OAuth protocol. Instead update requests (specifically made through the call of a POST request directed to https://api.parse.com/2/update) are made setting the POST request’s body to the json string representing the actual update. To be honest this was clear even before all of this, since by looking at the request I should have realized that the json text was being sent as the raw body of the request instead of a x-www-form-urlencoded body (thus having the query parameters urlencoded and &-concatenated in the request’s body).
While this is now the “correct” behaviour I feel like this is not like it should be in a production environment used by thousands of people. What I’ll do now is trying to patch it without breaking functionality, should I manage to do that I’ll share the patch.
Still hoping to get a response from Parse directly.
EDIT 2: Parse has closed my question as a not-question but a bug report. No comments on the major security flaws their implementation implies.
Below the copy of the reported bug
I was playing around with the Parse iOS SDK and I found a major bug
that seriously threat the security of the apps developed using parse
as a backend.
Now, I’m sorry if I’m not using the bug issue reporting tool but I do
not own a facebook account and I’m not willing to.
Premise: Parse APIs seems to conform to OAuth protocol 1.0a (RFC
5849). The relevant part of the RFC that involve this bug is at
page 18, signature.
In oauth, according to the above mentioned RFC, each request should
have an authentication header composed like:
OAuth realm="Example", oauth_consumer_key="0685bd9184jfhq22", oauth_token="ad180jjd733klru7", oauth_signature_method="HMAC-SHA1", oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D", oauth_timestamp="137131200", oauth_nonce="4572616e48616d6d65724c61686176", oauth_version="1.0"
This will ensure not only that a request is authorized but even
request integrity since the HMAC signature will enforce this. As a
matter of fact the signature should be calculated by using a
normalized string composed by the request parameters and signed with
the client shared concatenated to the token shared secret (see section
3.4.2, page 25 of the RFC). In this way a malicious user should not EVER be able to modify the request before it reaches the server. The
server in fact should check for the signature to match the whole
request, rejecting it if it doesn’t.
Sadly enough Parse seems not to totally conform to the above. By using
a simple proxy I’m able to totally modify requests, from changing the
user ID performing the request, change the value of a parameter in the
request, ADD A FIELD AND A VALUE THAT WERE NOT INCLUDED IN THE REQUEST
Now it is really easy to imagine the drawbacks that all of this can
lead to. In particular I’m thinking to the mobile developers that
enable in-app purchases in their app, relying that parse is secure
enough for them that their users will not be able to “cheat”, thus
losing the income and nullifying the efforts they made for their app.
Now, while I was able to test it on the other SDKs, I’m pretty sure
the same bug is reproducible there too, or even worse the problem is
that the server is not checking the signature at all.
Waiting response from a Parse employee about this bug.