http cache-control and authentication - rest

I would like to aks if anyone been solving Client(browser) side caching of authenticated content?
Task:
cache the CONTENT for non-authenticated users
cache the CONTENT for authenticated users
There is a challenge here as you want to make sure that those calls are not shared between different authenticated users / non-authenticated users.
I read something that http header Vary: Authenticated can be used, but I haven't seen any good example or explanation.

Related

Is allowing global CORS in my case security issue

I have rest api which is publicly available with REST API key authentication, but I want to allow private network to access api without authentication. Is it safe to add global CORS
Access-Control-Allow-Origin: *
Note that I am doing authentication in haproxy:
acl private_ip src -m reg -i (^127\\.0\\.0\\.1)|(^10.*)|(^172\\.1[6-9].*)|(^172\\.2[0-9].*)|(^172\\.3[0-1].*)|(^192\\.168.*)|(^::1$)|(^[fF][cCdD])|(0:0:0:0:0:0:0:1)
I read that setting CORS "*" could cause some security issues in case when there is IP authentication, but as I am not sure how "src" IP address in haproxy is obtained I can't be sure if this security risk is present in my case?
It is strongly recommended against to use IP authentication and a permissive CORS policy together.
CORS allows for script on a page served from one host to process a response from a call to a resource on another host when normally a well-behaved browser would stop script on the page from reading the response. For example where a page on webserver.com includes an AJAX call to a resource on api-server.com.
CORS is enforced by the browser, so if your attacker can make a call to your API then they are able to ignore your CORS header, and this is transitive to anything they can get another user to do by serving them a malicious page.
API authentication (whether by token or by IP) is a server-side protection that allows you to filter your response to the request. Consider the case where your attacker has access to your network. They can make a request to your API and your IP authentication lets them get the data. CORS is not the solution to that, but you of course secure your network well and only your users have access to it.
However, if the attacker controls a website (say, compromised.example.com) then they can send a user on your network a link to their page. When your user goes to the page, they are served a script that makes a call to your API. Because you permit the request based on IP, you provide the response.
This is where CORS comes in. If you have a header allowing '*' on your API responses, then the browser on your network will happily provide the requesting page (served from the attacker who is not on your network) with the response.
So the attacker has unauthenticated access to your API if they can get one of your network's users to browse to their malicious page and exfiltrate any responses that a user on your network can get.

Is it bad to have access token in OAuth redirect URL

I am building an oauth login flow and I am not sure if I have done it wrong because I will need to send the bearer token back via redirect URL, like /oauth2/redirect?token=[TOKEN]. But isn't it not recommended to have token passed along through URL? As it is pointed out in this thread:
Don't pass bearer tokens in page URLs: Bearer tokens SHOULD NOT be passed in page URLs (for example, as query string parameters).Instead, bearer tokens SHOULD be passed in HTTP message headers or message bodies for which confidentiality measures are taken. Browsers, web servers, and other software may not adequately secure URLs in the browser history, web server logs, and other data structures. If bearer tokens are passed in page URLs, attackers might be able to steal them from the history data, logs, or other unsecured locations.
I must have missed something in the whole flow and would like to understand more about this matter. Any input is appreciated!
UPDATE
Might not be correct but this is my understanding after some digging. The three means to pass token:
URL (not preferable)
Auth header
Request body
But under the oauth redirect use case, option 2 and 3 not feasible. So option 1 is the only option available. If really needed, token can be encrypted to ensure security.
I think this only means, that you should not use a GET request when the server requires the token, instead you should use POST or whatever is appropriate. In a GET request the parameters are included in the URL and those can end up in logs or other histories, other request types will send the paramters separat from the request URL.
P.S. BTW if you are not implementing the OAuth server yourself, you won't have to send a redirect url containing the token.
The basic auth header which provides a little extra security as it's required to be through TLS:
In the case of a "Basic" authentication like shown in the figure, the exchange must happen over an HTTPS (TLS) connection to be secure.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
Also, the headers aren't logged in easy places like browser history.
From the spec,
it SHOULD NOT be used
unless it is impossible to transport the access token in the
"Authorization" request header field or the HTTP request entity-body.
https://www.rfc-editor.org/rfc/rfc6750#section-2.3

Do I need CSRF protection for /login endpoint?

I know
this question has already been asked so many times, but after hours of searching I still don't have a clear answer to my problem.
Even projects like https://github.com/pillarjs/understanding-csrf have been abandoned and have not answered to new questions and doubts over the years like this.
PROBLEM
Let's say I have:
a back-end on back.domain.com and
a front-end on front.domain.com.
My back-end is a simply nodejs app with these rest endpoints:
POST /login:
accepts JSON body like: {"username": "myname", "password": "mypass"}
verify credentials
if OK gives 200 and create a cookie with session
if NOT gives 401
GET /players:
check session in cookie
if OK gives 200 with {"players": "[...]"}
if NOT gives 401
POST /player/1:
check session in cookie
if OK gives 200 and edit player
if NOT gives 401
My front-end app has:
/login page with a form (with username and password fields) for issue a POST request to back.domain.com/login
/players which request a GET request to back.domain.com/players
a button which issues a POST request to back.domain.com/player/1
QUESTIONS
Do I need CSRF protection in this scenario?
I think YES, I need because an attacker can issue a request to back.domain.com/player/1 from malicious.site.com and use my session cookie to edit player because I'm logged in (and I still have a session cookie) on my domain.com.
Do I need CSRF protection (e.g. an X-CSRF-Token header) when I the first time login on back.domain.com/login?
In this scenario I still don't have any session cookie in my browser.
And also I don't know where to get my CSRF token for X-CSRF-Token authorization header too.
I read on https://fractalideas.com/blog/making-react-and-django-play-well-together-single-page-app-model they are creating a dedicated endpoint on back-end for this and they explain it's not a security vulnerability.
What do you think about?
You are correct.
You DO need CSRF protection any time BOTH of the following are true:
the browser is automatically providing the authentication mechanism (most common way this is done is with a cookie)
the operation is state-changing on your backend
Of your three endpoints, only one meets both of those conditions.
GET /players/: get is not a state-changing operation. No CSRF protection needed.
POST /player/1/: authentication provided by cookie; post is state-changing. Needs CSRF protection!
POST /login/: the browser is not automatically providing the authentication information; it’s coming from data the user has intentionally typed in and submitted. No CSRF protection needed.
You’ll find other schools of thought - this other stack overflow post indicates the possibility of privacy-violation attacks, but the method described stretches credulity a bit in my opinion. And in any case you are right - if your frontend and backend are being served by totally different servers, your frontend won’t have the CSRF token before the user logs in.

Authentication on RESTful API on GET requests

So REST architecture implements GET, POST, PUT and DELETE requests. I would like to talk about GET requests. http://example.com/api/students this is a GET request under the REST architecture that will give me a list of students in the database.
My question is about authentication. it seems the best way to authenticate on a GET request would be by using an Access Token, like http://example.com/api/students?token=randomstring
How is this handled serverside, I mean a secuencial process, to prevent somebody from stealing another user's access token and using it. Is the token refreshed on every request and returned along the results or something like that?
First of all - you should never put credentials (access tokens) in URLs. Its not exactly wrong or prohibited per se - its just bad practice since it makes it impossible to share URLs without exposing secret credentials (think about what would happen if you copied the URL into an e-mail and send it to a friend). Credentials in URLs simply makes it too easy to accidentally expose them to others.
Take the token and stuff it into the HTTP Authorization header instead - that's why we have it. There are many different ways to use that header, but in your case you would want to use the "bearer" token method. Here is an example from the RFC (https://www.rfc-editor.org/rfc/rfc6750):
GET /api/students HTTP/1.1
Host: example.com
Authorization: Bearer rAndomSTRiNg
On the server you check the validity of the token before doing anything else. To prevent others from stealing it you enforce SSL/TLS on the connection.
The token may need to be refreshed - but that depends on how you obtained it and the rest of your infrastructure. Usually you do not need to refresh it for every request - only after a certain time when it is expired.
You may want to look at OAuth2 which defines four basic ways of obtaining access tokens.

How do CSRF tokens protect from malicious GET followed by POST in another tab

I know I am missing something, but please help me understand. Consider this situation:
I have a website called goodbank.com. URL http://goodbank.com/transfer/ serves a HTML page on GET with a form to transfer money to another account. The form has a random token to prevent CSRF attack. On the server, token validity is checked on POST and the corresponding controller allows only authenticated sessions.
Let's say that in my browser, I login to goodbank.com/. In another tab, I go to robgoodbank.com. As part of the served page, it has javascript to do AJAX request to goodbank.com/transfer/ to get a valid form. It then fills in other fields in the form and does a POST. My account is cleaned out :(
How does existing protection schemes protect against such an attack?
Thanks in advance.
Unless your server allows Cross Origin Resource Sharing, the browser will reject the XMLHttpRequest. As per the link, the XMLHttpRequest sends the Origin header containing the domain from which the request originates. If the server does not respond with Access-Control-Allow-Origin containing a wildcard of that domain, the browser will reject the request. There are actually a number of Access-Control- headers to control access including allowable methods, etc.
For extra protection, your server should check the Origin if it is present and the Referer HTTP header, which will be "http://robgoodbank.com" in your example, and you can also reject the request.
These are by no means foolproof, but do provide extra layers of protection. There are mechanisms (such as extensions) to spoof the Referer, but those would have been employed by the user unless their browser has been compromised in some way. If their browser has been compromised they are in a lot more trouble...