Any holes in securing a HTTP request with HMAC using ONLY the HTTP method and URL? - http

I want to redirect my users browser using HTTP code 303 to a GET URL that I secure using HMAC. Because the request will come from the users browser, I will not have fore-knowledge of the request headers. So I am generating the HMAC hash using the values of the HTTP method and URL only. For example, the URL I want the browser to do to might be:
GET /download
?name=report.pdf
&include=http://url1
&include=http://url2
This create report.pdf for me, containing the contents of all the urls specified using the include query param.
My HMAC code will change this URL to be
GET /download
?name=report.pdf
&include=http://url1
&include=http://url2
&hmac-algorithm=simple-hmac
&hmac-signature=idhihhoaiDOICNK
I can issue HTTP 303 to the user using this URL, and the user will get their report.pdf.
As I am not including the request headers in the signature, I am wondering two things:
1) Can a would-be attacker take advantage of the fact that I am not signing the request headers?
2) Is there a better way to achieve what I am trying to do?

When I realised that what I am talking about here is a signed URL, I checked the Amazon Docs and found "REST Authentication Example 3: Query String Authentication Example" in this document: http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html.
This example is about a signed URL for use through a browser. About signing the headers, the document says:
You know that when the browser makes the GET request, it won't provide a Content-Md5 or a Content-Type header, nor will it set any x-amz- headers, so those parts are all kept empty.
In other words, Amazon leave the headers out of the signature.
Amazon make no mention of potential security holes, so until I hear otherwise (or get hacked :) ), I will assume my approach above is fine.

Related

Is it possible to verify whether the GET came from a button or typed in URL bar?

Im wondering if I can detect whether some webpage was reached by a link (button, link, redirect, ...) or by typping in the URL bar.
Im using Clojure for web programming, and I wish I could block the access to some page when the request came from a "typed url".
Right now I am encoding the urls so the user can't have access to the "real" url.
Thanks in advance.
Short answer is no. Your aproach is correct.
And with a bit of skills one can also send arbitrary HTTP requests, GET or POST, modifying cookies, headers and the body of the request, so if this is about security, your approach to use encrypted data seems the only one possible to ensure that the URL is not tampered or manually typed.
The HTTP Referer header can be also faked, the same as a url parameter. There is no more security on using a http header or a url encoded parameter.
Courtesy of Wikipedia:
The HTTP referer (originally a misspelling of referrer[1]) is an HTTP header field that identifies the address of the webpage (i.e. the URI or IRI) that linked to the resource being requested. By checking the referrer, the new webpage can see where the request originated.
I assume you can access the HTTP header fields. If the user were to type in the URL into the address bar, there would be no HTTP referer.

Securing user/password for REST API

I have a web service REST API on a secure ASP.NET website which requires a login to work. What is the most secure way to request the username/password programatically? (just adding a ?username=me&password=mysecret to the URL doesn't seem all that secure to me (even though this is a HTTPS connection).
There are several ways to achieve what you need:
[WRONG WAY] One could pass the username and password along with the query string. In theory there is nothing wrong with this practice, but such a URL (http://example.com?username=me&password=mysecret) is usually cached by browsers, proxies, etc and thus leverage a potential risk that someone else can access to your protected data by using these stored data.
[GOOD WAY] In order to remove "almost all" risks related to caching abilities of browsers, proxies, etc. and moreover in order to use standard features of the HTTP protocol, you have to deal with the special HTTP Authorization header.
The HTTP Authorization header :
If you are using HTTP S connections, then you can use the Basic Access Authentication method.
The Authorization header is constructed as follows:
Username and password are combined into a string "username:password".
The resulting string literal is then encoded using Base64.
The authorization method and a space i.e. "Basic " is then put before the encoded string.
For example, if the user agent uses 'Aladdin' as the username and 'open sesame' as the password then the header is formed as follows:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
If you are using HTTP connections, then you should use the Digest Access Authentication method. Because it's more complicated and useless with HTTPS connections, I let you read more about it if you want (here maybe).

Are JSON web services vulnerable to CSRF attacks?

I am building a web service that exclusively uses JSON for its request and response content (i.e., no form encoded payloads).
Is a web service vulnerable to CSRF attack if the following are true?
Any POST request without a top-level JSON object, e.g., {"foo":"bar"}, will be rejected with a 400. For example, a POST request with the content 42 would be thus rejected.
Any POST request with a content-type other than application/json will be rejected with a 400. For example, a POST request with content-type application/x-www-form-urlencoded would be thus rejected.
All GET requests will be Safe, and thus not modify any server-side data.
Clients are authenticated via a session cookie, which the web service gives them after they provide a correct username/password pair via a POST with JSON data, e.g. {"username":"user#example.com", "password":"my password"}.
Ancillary question: Are PUT and DELETE requests ever vulnerable to CSRF? I ask because it seems that most (all?) browsers disallow these methods in HTML forms.
EDIT: Added item #4.
EDIT: Lots of good comments and answers so far, but no one has offered a specific CSRF attack to which this web service is vulnerable.
Forging arbitrary CSRF requests with arbitrary media types is effectively only possible with XHR, because a form’s method is limited to GET and POST and a form’s POST message body is also limited to the three formats application/x-www-form-urlencoded, multipart/form-data, and text/plain. However, with the form data encoding text/plain it is still possible to forge requests containing valid JSON data.
So the only threat comes from XHR-based CSRF attacks. And those will only be successful if they are from the same origin, so basically from your own site somehow (e. g. XSS). Be careful not to mistake disabling CORS (i.e. not setting Access-Control-Allow-Origin: *) as a protection. CORS simply prevents clients from reading the response. The whole request is still sent and processed by the server.
Yes, it is possible. You can setup an attacker server which will send back a 307 redirect to the target server to the victim machine. You need to use flash to send the POST instead of using Form.
Reference: https://bugzilla.mozilla.org/show_bug.cgi?id=1436241
It also works on Chrome.
It is possible to do CSRF on JSON based Restful services using Ajax. I tested this on an application (using both Chrome and Firefox).
You have to change the contentType to text/plain and the dataType to JSON in order to avaoid a preflight request. Then you can send the request, but in order to send sessiondata, you need to set the withCredentials flag in your ajax request.
I discuss this in more detail here (references are included):
http://wsecblog.blogspot.be/2016/03/csrf-with-json-post-via-ajax.html
I have some doubts concerning point 3. Although it can be considered safe as it does not alter the data on the server side, the data can still be read, and the risk is that they can be stolen.
http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx/
Is a web service vulnerable to CSRF attack if the following are true?
Yes. It's still HTTP.
Are PUT and DELETE requests ever vulnerable to CSRF?
Yes
it seems that most (all?) browsers disallow these methods in HTML forms
Do you think that a browser is the only way to make an HTTP request?

Which is better, pass username/password as parameters in HTTP header or HTTP Body?

I am implementing an REST server.
I am going to receive the username, requestid and password for each request from user.
I have two choice, i can ask for users to pass those three parameters in http body or in http header.
Which will be better way of implementation and why?
Thanks in advance.
Header!
If I understand your question, you have something that you are going to pass with every single request. That means if you want to support safe requests like GET and HEAD, you only have two choices: The HTTP headers or the URL (typically via query parameters).
Since it includes authentication information, you should avoid putting it in the URL. Other than that, you say it is encrypted and an added layer of protection would be to do it over SSL but the header and body are equally safe/vulnerable, so it makes no difference from a security standpoint.
Putting it in the header also decouples it from the application state and also from the media type, which is a good thing. If you want to support JSON, XML and XHTML forms it makes no difference to your authentication parameters.

Sending info with a HTTP redirect that the browser should send to the redirected location?

Is this possible.. for example, imagine I respond to a request with a 302 (or 303), and I inform the browser to do a request to a given location.. is there a header that I can send with the HTTP 302, so that the subsequent request from the browser would include that header?
I know I could do this with the location header, as in redirect and specify the information in the url as a query string.. but I'm wondering if there is a better way.. it seems that it should be a legit scenario..
'Content has moved, go here .. oh and you'll want to take this with you to give to the redirect location'
I'm guessing a big fat no!
Thanks in advance.
Edit
The reason for this is in respect to PRG patterns, where you have a GET url and POST url, given that you post data and it isn't acceptable, the server redirects you to the GET, and does some 'magic' in order to 'send data' to that GET, using most often session state to store a variable.
However this can breakdown in scenarios where many of these PRG requests are happening, granted this isn't a common scenario and generally nobody need worry about this.. but if you do- you'll need a way to identify the requests, this can be done with query string parameters send in the 302.. so that a specific entry can be put in session state according to that request.
The question was regarding trying to remove the 'request key' from the url, and making it more implicit.. cookies 'appear' to work, but they only make the window for screw ups smaller.
It would be great to say when you go the 'location' i've specified, send these parameters.
Edit
Just to note, I'm not trying to get the browser to send arbitrary headers to the location, but if there is ANY headers designed to hint the context of the request (like the querystring parameters could).
A redirect response itself doesn't contain any data. You can redirect using a URL with query parameters, but the new "location" will need to know how to consume those parameters.
No, that’s not possible. You cannot force the client to something. You just can say “this is not the right location, but try that location instead”. But it’s not guaranteed that the client will send the same request or another request to that new location. And telling the client to add a specific header field in that subsequent request to the new location is also not possible.

Resources