Securing intercom webhooks with signed notifications: what data gets hashed? - webhooks

I’m trying to secure my Intercom webhook endpoints and I'm following the instructions outlined here:
https://developers.intercom.com/intercom-api-reference/reference#signed-notifications
https://www.intercom.com/help/apps-in-intercom/apps/webhooks
The problem is, neither of those resources are clear about what data actually gets hashed to create the signature and I’ve tried a bunch of different things and still not getting a match.
Does anyone know what part of the notification request is used to generate the sha1 hash that’s included in that x-hub-signature header?

I recommend looking through the intercom-webhooks GitHub repo for example code in a variety of programming languages for how to handle the webhook signature.
The signature is computed using the entire payload of the POST request.

Related

Give a digital signature after friend request to use after to prove friendship in social apps?

I am building some kind of social app with the concept of 'friends' where friends can do actions regarding one or more of their friends,
I would rather not ask the DB if the friendship does exist every time someone sends any kind of request for an action.
An idea I came up with is after a friendship is approved a digital signature will be sent to each user which can be checked in the server for each request which should cost less than asking the db.
Then I can maybe change the async key everyday or so and force the user to ask for a new digital signature in which case I do approach the db to test friendship (it's good for security but also a must if users want to cancel friendships).
What I ask is if this is a terrible idea? Maybe I'm not seeing something. Or just any link to any information about these kind of scenarios would be great.
The idea of handing out a digital signature can be done, though I am not sure if it would actually be any faster then querying the database, seeing as databases are meant to be incredibly fast.
Lets move on with the idea that it is indeed a good idea. You would need a token of sorts that has the information about who is your friends and it has to have been validated by the server. This, to me, seems like something you could use a JSON Webtoken (JWT) for.
Here is the basics on JWTs.
JWTs have three parts to them: Header, payload and signature. The header defines how long the token will be valid for and the payload can contain the list of friends (or IDs of friends). The signature is a hash of the entire thing, signed with the private key of the server, thus verifying that the server has approved this token as valid until time X. The entire thing is encoded before sending.
You would then send the JWT in a HTTP header of some sort, probably the Authorization header. The server could then quickly decode the JWT (there are libraries for this in a lot of languages, JWTs are a pretty good standard) and thus not need to query the database. The size of the JWT does need to be send though, and thus I am not sure you will actually gain any speed from this.

Parse.com API security concerns

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.
EDIT:
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
AT ALL.
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.
Regards, Antonio
It is impressing that you have digged into the framework to check security issues. I am not expert in oauth. But I just want to comment about your worry about in-App purchase. It is not neccessary to worry about in-app purchase because that is handled completely by App Store. Any purchase will be handled by iOS' StoreKit.framework. Parse has nothing to do with in-app purchase. If you want to check if a person has bought anything, you only need to use the functions brought by StoreKit.framework, not Parse.

Do I need to secure the body of a REST request using oAuth?

I'm building a REST API and using oAuth for authorization. My question is do I need to do anything about the body of the request in the case of PUT and POST requests that contain data? I'm using SSL if that makes any difference.
It seems to me that the url is verified by the oAuth signature, but the contents of the body could be anything. I'm not sure if that's a problem, though, because if the URL is correctly signed then they have provided the correct credentials to do an insert or update. I am using nonce to prevent replay attacks as well, but I want to avoid creating a security issue due to misunderstanding how to treat the request body.
Thanks for any suggestions.
I found an answer looking through some OAuth libraries. It's not officially part of the spec but some services and libraries use "xoauth_body_signature" and "xoauth_body_signature_method" in the request headers to send a signature of the body contents.
Apparently there's some challenges implementing and discussions can be found by googling for xoauth_body_signature. It doesn't seem like a lot of people are doing it.

How to prevent a "replay" with Javascript SDK authResponse

I'm using the Javascript SDK to make a web page that is entirely static HTML and Javascript (i.e., it's not dynamically produced web markup via some web app). This web page occasionally uses Javascript to POST data to a server--data which should be tied to a particular Facebook user. I use FB.getLoginStatus to determine who the user is. This gives me authRepsonse JSON data which looks like this:
authResponse:
accessToken:"AAAC91..."
expiresIn: 3786
signedRequest:"Ws93YNGWQeOi..."
userID: "670..."
I can send the signedRequest to the server and decode it and validate it there (using my app's secret key), and then I know that the user is, in this case, "670...", so I can presumably safetly perform whatever operation is supposed to happen on the server. Here's the data I extract from the signed request:
{"algorithm"=>"HMAC-SHA256",
"code"=>
"2.AQAKT...|5hVFYWcu5a...",
"issued_at"=>1323403518,
"user_id"=>"670..."}
My question is, what prevents an adversary (who somehow got ahold of the encoded authResponse above) from just "replaying" the signedRequest data to my server at a much later time?
The "issued_at" param at first looked promising, but I don't have anything to compare that issued_at time to to see if I should accept this signedRequest or not. The "expiresIn" is another time related parameter, but it's not signed, so I can't trust it. Maybe "code" provides me with extra info, but I don't see how to decode that.
I expect I'm just thinking about this wrong, or using the API in a way I'm not supposed to. Any insights? Thanks.
First of all using an Message Authentication Code (MAC) is a fundamentally insecure approach to the problem of authentication. You should be storing this information as a server side state, so that this is never a threat. By using a cryptographic hash function as an HMAC you introduce the possibility of someone brute forcing your secret key. Cryptography should only be used when there is no other solution, instead you are using it to introduce a weakness. This is a gross misuse of cryptography.
That being said, you have an issued_at timestamp. Just take the current timestamp and subtract. make sure that value is greater than your session timeout.

I need resources for API security basics. Any suggestions?

I've done a little googling but have been a bit overwhelmed by the amount of information. Until now, I've been considering asking for a valid md5 hash for every API call but I realized that it wouldn't be a difficult task to hijack such a system. Would you guys be kind enough to provide me with a few links that might help me in my search? Thanks.
First, consider OAuth. It's somewhat of a standard for web-based APIs nowadays.
Second, some other potential resources -
A couple of decent blog entries:
http://blog.sonoasystems.com/detail/dont_roll_your_own_api_security_recommendations1/
http://blog.sonoasystems.com/detail/more_api_security_choices_oauth_ssl_saml_and_rolling_your_own/
A previous question:
Good approach for a web API token scheme?
I'd like to add some clarifying information to this question. The "use OAuth" answer is correct, but also loaded (given the spec is quite long and people who aren't familiar with it typically want to kill themselves after seeing it).
I wrote up a story-style tutorial on how to go from no security to HMAC-based security when designing a secure REST API here:
http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/
This ends up being basically what is known as "2-legged OAuth"; because OAuth was originally intended to verifying client applications, the flow is 3-parts involving the authenticating service, the user staring at the screen and the service that wants to use the client's credentials.
2-legged OAuth (and what I outline in depth in that article) is intended for service APIs to authenticate between each other. For example, this is the approach Amazon Web Services uses for all their API calls.
The gist is that with any request over HTTP you have to consider the attack vector where some malicious man-in-the-middle is recording and replaying or changing your requests.
For example, you issue a POST to /user/create with name 'bob', well the man-in-the-middle can issue a POST to /user/delete with name 'bob' just to be nasty.
The client and server need some way to trust each other and the only way that can happen is via public/private keys.
You can't just pass the public/private keys back and forth NOR can you simply provide a unique token signed with the private key (which is typically what most people do and think that makes them safe), while that will identify the original request coming from the real client, it still leaves the arguments to the comment open to change.
For example, if I send:
/chargeCC?user=bob&amt=100.00&key=kjDSLKjdasdmiUDSkjh
where the key is my public key signed by my private key only a man-in-the-middle can intercept this call, and re-submit it to the server with an "amt" value of "10000.00" instead.
The key is that you have to include ALL the parameters you send in the hash calculation, so when the server gets it, it re-vets all the values by recalculating the same hash on its side.
REMINDER: Only the client and server know the private key.
This style of verification is called an "HMAC"; it is a checksum verifying the contents of the request.
Because hash generation is SO touchy and must be done EXACTLY the same on both the client and server in order to get the same hash, there are super-strict rules on exactly how all the values should be combined.
For example, these two lines provides VERY different hashes when you try and sign them with SHA-1:
/chargeCC&user=bob&amt=100
/chargeCC&amt=100&user=bob
A lot of the OAuth spec is spent describing that exact method of combination in excruciating detail, using terminology like "natural byte ordering" and other non-human-readable garbage.
It is important though, because if you get that combination of values wrong, the client and server cannot correctly vet each other's requests.
You also can't take shortcuts and just concatonate everything into a huge String, Amazon tried this with AWS Signature Version 1 and it turned out wrong.
I hope all of that helps, feel free to ask questions if you are stuck.

Resources