understanding of CSRF token - http

I read this post Understanding CSRF - Simple Question
But I still do not understanding how the CSRF token can prevent a CSRF token.
The main problem which confused me is that why the attacker can make any http request to my site, but he cannot read back the response?
1、If I post a http request to get token before every post request, attacker also can make an "get token" request to get token.
2、If I set token to the hidden input while the .html page is loading, attacker also can make a "get html" request to get the this .html page and read the value of hidden page.
I just don't understand why the attacker can make request but can not read the response?

The attacker cannot make the request himself at all. What he can do is trick his victim (or the victim's browser) to make that request. So any response would go back to the victim's browser, too.
The problem here is that the attacker can choose the URL, and even without seeing any response, accessing that URL may have harmful consequences for the victim.
The reason why the attacker needs to trick the victim into making the request (as opposed to just accessing the URL himself) is that if the victim does it, the victim's session cookies will also be sent along, so it looks like an authenticated action for the server.
If I set token to the hidden input while the .html page is loading, attacker also can make a "get html" request to get the this .html page and read the value of hidden page.
The attacker can only get a hidden input for his own session, not for the victim's session. This hidden input will be different from session to session (otherwise there is not point).
The CSRF token makes sure that every (critical) request includes a random piece of data that must match the user's session. This way, an attacker cannot just guess what the complete URL would be, and trick someone into clicking on it.

Related

Routes using cookie authentication from previous version of Paw no longer work on new version

I have a route that uses an authentication cookie set by another route. I've created it like this:
This method no longer works in the new version. Paw complains that there is no set-cookie header in the response from the Authenticate request.
It seems this is because Paw now takes the cookies and handles them differently from other headers. I like this approach because it should make this sort of authentication easier, but, unfortunately, it's not working like I would expect.
Here's how I have configured a newer request:
So, I've set the cookie header to the Response Cookies dynamic value which, I believe, should pass along the cookies set previously. I would think I should select the Authenticate request from the dropdown (since it's the response from this request that actually sets the cookie, but the cookie value disappears if I do that. Instead, I have left the request value as Current Request since that seems to contain the correct value.
I've also noticed the Automatically send cookies setting which I thought might be an easy solution. I removed the manual cookie header from my request leaving this checked in hopes it might automatically send over any cookies from the cookie jar along with the request, but that doesn't seem to work either. No matter what I try, my request fails to produce the desired results because of authentication.
Can you help me understand how to configure these requests so that I can continue using Paw to test session-authenticated routes?
Here are a couple of things that will make you understand how cookies work in Paw (starting from version 2.1):
1. Cookies are stored in Jars
To allow users to keep multiple synchronous sessions, cookies are stored in jars, so you can switch between sessions (jars) easily.
Cookies stored in jars will be sent only if they match the request (hostname, path, is secure, etc.).
2. Cookies from jars are sent by default, unless Cookie header is overridden
If you set a Cookie header manually, cookies stored in jars wont' be sent.
And obviously unless Automatically Send Cookies is disabled.
3. The previous use of "Response Headers" was hacky. Use Response Cookies.
In fact, Set-Cookie (for responses) and Cookie (for requests) have different syntaxes. So you can't send back the original value of Set-Cookie (even though it seemed to be working in most cases).
The new Response Cookies dynamic value you mentioned has this purpose: send back the cookies set by a specific request.
Now, in your case, I would use a Response Cookies dynamic value all the time. As you have only 1 request doing auth / cookie setting, it might be the easiest to handle. Also, maybe check Ignore Domain, Path, Is Secure and Date to make sure your cookie is always sent even if you switch the host (or something else).
Deleting the cookies in the cookie jar and hitting the authentication endpoint again seems to have fixed the problem. Not sure why, but it seems to be working now either manually sending a cookie or using the Automatically send cookies setting.

http authorization not sent for resources on page?

I'm successfully setting up an HTTP Digest Authorization between the web browser and the server. But some of the resources on the same page to the same host are failing because the browser isn't sending the authorization for them.
For example,
Page https://myhost/A/B/C/D/E/ is loaded, browser sends Authorization header.
Page contains IMG ref to https://myhost/A/B/C/D/E/F.JPG, browser sends Authorization header.
Page also contains IMG ref to https://myhost/A/B.JPG, but for some reason browser does not send Authorization header. Server returns 401 Unauthorized but browser does not retry with authorization or pop up a username/password field, it simply displays the "broken image" icon.
I have looked a bit at how HTTP Authorization and I don't see anything mentioned regarding the scope of a request. Nevertheless, because I am explicitly sending back a 401 if the browser doesn't send Authorization for a request, I would expect it should work.
How can I fix this problem?
HTML authorization is governed by RFC 2617, which in section 1.2 says:
The realm value (case-sensitive), in combination with the canonical
root URL (the absoluteURI for the server whose abs_path is empty; see
section 5.1.2 of [2]) of the server being accessed, defines the
protection space.”. Later in the same section it says: “The protection
space determines the domain over which credentials can be
automatically applied. If a prior request has been authorized, the
same credentials MAY be reused for all other requests within that
protection space for a period of time determined by the authentication
scheme, parameters, and/or user preference.
So as long as the two URLS are in the same "protection space" the browser is supposed to resend the same credentials. However in this case the problem is that they are not. If authorization occurs in the https://myhost/A/B/C/D/E/ space, then the browser may not see a need to send authorization for https://myhost/A/B.JPG.
Section 2 mentions:
A client SHOULD assume that all paths at or deeper than the depth of
the last symbolic element in the path field of the Request-URI also
are within the protection space specified by the Basic realm value of
the current challenge. A client MAY preemptively send the
corresponding Authorization header with requests for resources in that
space without receipt of another challenge from the server.
So the solution is to make sure that the WWW-Authenticate header sent by the server sends a domain=/ entry, so that everything under that will be considered in the same protection space.

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

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.

Browser not sending `Authorization` header set on deep url to root url

When I ask user for HTTP Basic Auth at some URL, browser sends Authorization header only for this and some other URLs.
Testcase script written in PHP:
http://testauth.veadev.tk/
There are three URLs to ask for credentials (you can use any random).
Logout link (drops current credential after pressing "Cancel" button in browser auth form, not working in IE).
Links to root URL and some test deeper URLs.
Questions:
Why browser not sending Authorization header at / URL if HTTP/1.0 401 Unauthorized was sent at /system/dev?
To repeat: open clean http://testauth.veadev.tk/, click Auth2, enter any credentials, you'll be forwarded to / after that. You'll see Auth: null which means no credentials header was sent by browser.
Why does browser send Authorization header at / if HTTP/1.0 401 Unauthorized was sent at /dev?
To repeat: open clean http://testauth.veadev.tk/, click Auth1, enter any credentials, you'll be forwarded to / after that. You'll see something like Auth: string 'Basic dHQ6dHQ=' (length=14) which means credentials header was sent by browser.
If you repeat first case and then click Auth1 you'll have credentials at Root and all other pages. Why?
If you click Auth3 (/some/deep/and/long/url) and you'll have credentials at Page3 (/some/deep/and/long/3) and nowhere else. Why?
To clear credential state between tests either restart your browser or click Logout, Cancel in Auth form and Root to return back (Firefox, Google Chrome).
What are the rules of sending Authorization header?
RFC 2617, section 2 states:
A client SHOULD assume that all paths at or deeper than the depth of
the last symbolic element in the path field of the Request-URI also
are within the protection space specified by the Basic realm value of
the current challenge. A client MAY preemptively send the
corresponding Authorization header with requests for resources in that
space without receipt of another challenge from the server.
If you are using Digest Challenge, section 3.2 states that you may specify a domain in the WWW-Authenticate header to indicate what the protection space will be. I would try setting that to something like domain=/. I am not sure if this will work with Basic authorization, but it wouldn't hurt to try it; if not, Digest authorization is not much more difficult to work with and is a bit more secure.

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