Securing oauth bearer token against attacks such as XSS, CSRF in javascript apps - security

I am a bit unclear about how to secure (or protect) bearer tokens when using pure JavaScript applications.
I know when user request token to the server it can come with a validity of 14 days or 24 hours. but once the user has token there is no neat (assured) way of securing this from XSS or CSRF attacks (am I missing something?).
Now lets say user is logged into the web application and the browser has this token which is valid for 14 days. If the user is accessing another web application which is trying to do XSS (or CSRF) then the token is exposed to the third party application and this application can make calls to the my application using this token (?)
I have tried to search online but nothing concrete (or something which is easy to understand) coming up for pure js apps and how to protect the token. Or there isn't a good way to do it in js atm. and you just hope (and pray) that the attack will not take place within the validity of token (i.e. 14 days :|)?
Any thoughts or inputs are welcome to this.
Thanks
Edit: It prob. goes without saying but we are assuming the use of SSL certificate.

So, a very quick summary. CSRF occurs because a request to a HTTP end point automatically includes cookies (as it should) plus required headers as described by the server and doesn't require a user to physically do something. They simply visit a web page with the CSRF vector on.
CSRF is generally said to be possible if there is no use of a unique "secret" passed firstly to the client and back to the server to verify that the user indeed intended to make the call. Generally speaking, web browsers are shaping the main ways to protect against CSRF for any type of application. CSRF on OWASP
As you've pointed out, you use a bearer token (sent as a HTTP header) - but you are still protected because requests need to originate from the same origin by default. IF the server allows calls from all origins which is returned in the HTTP headers (which tells your user's web browser if it is allowed) then on their heads be it Same origin policy here.
As for XSS, as long as your cookies at the very least have the "HTTP" flag they are invisible to javascript code on any page the user visits anyway. Plus strictly speaking XSS vectors including the theft of cookies for your site would need to be performed on your site generally speaking. Off the top of my head I can't think of anyway to steal them unless a user is physically on your site. If you set the "Secure" flag this is even better as it forces "Server" only too and ensures the cookie will only be sent when a TLS/SSL connection has been established. XSS on OWASP
Here is a screenshot of cookies listed with the Secure and HTTP flags:
As an extra, make sure you always enforce TLS connections as otherwise they could become victim to a MITM (Man in the middle) attack on a public WIFI network that forces a protocol downgrade to a weak version of SSL that is susceptible to POODLE or non at all. Please read up on HSTS as it will most definitely reinforce everything I have mentioned and really help to prevent the token from being stolen HSTS OWASP and HSTS info wikipedia

Related

Do I need to use CSRF tokens in a cookie-based API?

I have an API in Next.js (NextAuth.js) that only the frontend will be using. It uses cookies for authentication. My question is could a malicious website change the user's data using CSRF? Should I implement CSRF tokens or can I prevent malicious websites from changing the data without it?
If authentication is based on something that the browser sends automatically with requests (like cookies), then yes, you most likely need protection against CSRF.
You can try it yourself: set up a server on one origin (eg. localhost:3000), and an attacker page on another (eg. localhost:8080, it's the same as a different domain, controlled by an attacker). Now log in to your app on :3000, and on your attacker origin make a page that will post to :3000 something that changes data. You will see that while :8080 will not receive the response (because of the same origin policy), :3000 will indeed receive and process the request. It will also receive cookies set for :3000, regardless of where the user is making the request from.
For mitigation, you can implement the synchronizer token pattern (csrf tokens), double submit, or you can decide to rely on the SameSite property of cookies, which are not supported by old browsers, but are supported by fairly recent ones, so there is some risk, depending on who your users are.

HTTP Referer for Single Sign On

As part of a project with a partner, we are required to provide single-sign-on service on our app. Basically, people will log in through our partner's website, then they are redirected to ours. The redirected request will have the user's data in the HTTP header fields.
Here's where it gets "iffy". The process of authenticating if this request is valid or not is dependent on the value of the HTTP Referer field. Our partner tells us to check this field to see that the source is a legitimate one.
Now I know (and I'm glad to be proven wrong) that this field is easy enough to forge, and since no other method of authentication is given to us, a malicious user could easily construct a false HTTP request and gain access to our web app.
I'm a programmer first, and admittedly know very little about the intricacies of HTTP. So are my concerns real? Would using SSL (somehow) void this concern?
Remember that rule number one is never trust client input. Like any other client input, the Referer header is trivial to forge. SSL does nothing for you because you still rely on client input. Also, note that browsers SHOULD NOT send Referer to http pages when referred by https pages.
Additionally, consider that many privacy-conscious people and proxies (that individuals may not have any control over) might strip Referer headers from their requests, breaking your scheme.
To do this properly, you need to use something like OAuth or OpenID, where the protocols have been designed to be secure.
The HTTP Referrer header is unreliable: depending on the browser used it may not be sent.
Does http-equiv="refresh" keep referrer info and metadata?
Yes - It is forgeable.
No - A client can just as easily send a (fake) HTTPS request as a (fake) HTTP request. The only difference is the connection is encrypted. It says nothing about the data transmitted.
That being said, it is another precaution that can be used. It should not be relied upon for security, however.
I would look at Microsoft Federation -- it's likely overkill, but it shows one way to implement SSO securely.

How to fix CSRF in the HTTP protocol spec?

What changes to the HTTP protocol spec, and to browser behaviour, would be required to prevent dangerous cases of cross-site request forgery?
I am not looking for suggestions as to how to patch my own web app. There are millions of vulnerable web apps and forms. It would be easier to change HTTP and/or the browsers.
If you agree to my premise, please tell me what changes to the HTTP and/or browser behaviour are needed. This is not a competition to find the best single answer, I want to collect all the good answers.
Please also read and comment on the points in my 'answer' below.
Roy Fielding, author of the HTTP specification, disagrees with your opinion, that CSRF is a flaw in HTTP and would need to be fixed there. As he wrote in a reply in a thread named The HTTP Origin Header:
CSRF is not a security issue for the Web. A well-designed Web
service should be capable of receiving requests directed by any host,
by design, with appropriate authentication where needed. If browsers
create a security issue because they allow scripts to automatically
direct requests with stored security credentials onto third-party
sites, without any user intervention/configuration, then the obvious
fix is within the browser.
And in fact, CSRF attacks were possible right from the beginning using plain HTML. The introduction of nowadays technologies like JavaScript and CSS did only introduce further attack vectors and techniques that made request forging easier and more efficient.
But it didn’t change the fact that a legitimate and authentic request from a client is not necessarily based on the user’s intention. Because browsers do send requests automatically all the time (e. g. images, style sheets, etc.) and send any authentication credentials along.
Again, CSRF attacks happen inside the browser, so the only possible fix would need to be to fix it there, inside the browser.
But as that is not entirely possible (see above), it’s the application’s duty to implement a scheme that allows to distinguish between authentic and forged requests. The always propagated CSRF token is such a technique. And it works well when implemented properly and protected against other attacks (many of them, again, only possible due to the introduction of modern technologies).
I agree with the other two; this could be done on the browser-side, but would make impossible to perform authorized cross-site requests.
Anyways, a CSRF protection layer could be added quite easily on the application side (and, maybe, even on the webserver-side, in order to avoid making changes to pre-existing applications) using something like this:
A cookie is set to a random value, known only by server (and, of course, the client receiving it, but not a 3rd party server)
Each POST form must contain a hidden field whose value must be the same of the cookie. If not, form submission must be prevented and a 403 page returned to the user.
Enforce the Same Origin Policy for form submission locations. Only allow a form to be submitted back to the place it came from.
This, of course, would break all sorts of other things.
If you look at the CSRF prevention cheat sheet you can see that there are ways of preventing CSRF by relying upon the HTTP protocol. A good example is checking the HTTP referer which is commonly used on embedded devices because it doesn't require additional memory.
However, this is weak form of protection. A vulnerability like HTTP response splitting on the client side could be used to influence the referer value, and this has happened.
cookies should be declared 'local' (default) or 'remote'
the browser must not send 'local' cookies with a cross-site request
the browser must never send http-auth headers with a cross-site request
the browser must not send a cross-site POST or GET ?query without permission
the browser must not send LAN address requests from a remote page without permission
the browser must report and control attacks, where many cross-site requests are made
the browser should send 'Origin: (local|remote)', even if 'Referer' is disabled
other common web security issues such as XSHM should be addressed in the HTTP spec
a new HTTP protocol version 1.2 is needed, to show that a browser is conforming
browsers should update automatically to meet new security requirements, or warn the user
It can already be done:
Referer header
This is a weaker form of protection. Some users may disable referer for privacy purposes, meaning that they won't be able to submit such forms on your site. Also this can be tricky to implement in code. Some systems allow a URL such as http://example.com?q=example.org to pass the referrer check for example.org. Finally, any open redirect vulnerabilities on your site may allow an attacker to send their CSRF attack through the open redirect in order to get the correct referer header.
Origin header
This is a new header. Unfortunately you will get inconsistencies between browsers that support it and do not support it. See this answer.
Other headers
For AJAX requests only, adding a header that is not allowed cross domain such as X-Requested-With can be used as a CSRF prevention method. Old browsers will not send XHR cross domain and new browsers will send a CORS preflight instead and then refuse to make the main request if it is explicitly not allowed by the target domain. The server-side code will need to ensure that the header is still present when the request is received. As HTML forms cannot have custom headers added, this method is incompatible with them. However, this also means that it protects against attackers using an HTML form in their CSRF attack.
Browsers
Browsers such as Chrome allow third party cookies to be blocked. Although the explanation says that it'll stop cookies from being set by a third party domain, it also prevent any existing cookies from being sent for the request. This will block "background" CSRF attacks. However, those that open full page or in a popup will succeed, but will be more visible to the user.

CSRF protection only for requests with side effect (POST, DELETE, PUT)?

As far I understand Cross-Site Request Forgery attacks they "only" used to change state on Server side.
Assume:
I have a REST Web Application, and I am sure that HTTP GET requests does not change my application persistent state (no side effects)
I use a session-specific key to authorize the requests
Do I need to verify the session-specific key for GET Request?
It's not really a question of the request method (GET and POST can both make changes to persistent state), as each can be exploited by various CSRF attack vectors. When you talk about a "session-specific key", I assume you're talking about a synchroniser token pattern (more on this in OWASP Top 10 for .NET developers part 5: Cross-Site Request Forgery (CSRF)). Obviously this is intended to protect against the browser making unauthorised requests on your behalf under the orchestration of a third party.
So the question is really "Does my app require protection against CSRF?" It sounds like there's no change to persistent data in your app anyway so on the surface of it, the answer is "no". You generally only find anti-request forgery tokens in places where a CSRF attack would have an adverse impact so it sounds to me like it's something you don't need to worry about.

Mitigating the 'firesheep' attack in the application layer?

What methodologies do people recommend for mitigating the 'Firesheep' method for website applications?
We have thought about this and from a usability perspective, other than encrypting all traffic to a site, mitigating the attack can be somewhat of a problem for web developers.
One suggestion we came up with was to use path based cookies, and encrypt traffic for a specific path where account operations or personalised interaction happens. This however complicates usability however, in as much as the rest of the site (the un-encrypted - un-authenticated) bit does not know who the user would be.
Does anyone have any other suggestions for mitigating this vector of attack, while maintaining a usable level of usability?
Firesheep is nothing new. Session hijacking has been going on for more than two decades. You don't need "encrypt" your cookie, thats handled by your transport layer. Cookies must always be a cryptographic nonce.
Usually hackers just set their own cookie by typing this into the address bar javascript:document.cookie='SOME_COOKIE', FireSheep is for script kiddies that fear 1 line of JavaScript. But it really doesn't make this attack any easier to perform.
Cookies can be hijacked if you don't use HTTPS for the entire life of the session and this is apart of OWASP A9 - Insufficient Transport Layer Protection. But you can also hijack a session with XSS.
1)Use httponly cookies. (Makes it so JavaScript cannot access document.cookie, but you can still do session riding with xss)
2)Use "secure cookies" (Horrible name, but its a flag that forces the browser to make the cookie HTTPS only.)
3)Scan your web application for xss using Sitewatch(free) or wapiti (open source)
Also don't forget about CSRF! (Which firesheep doesn't address)
Well I found an interesting article on GitHub that describes a method of mitigating the firesheep attack.
https://github.com/blog/737-sidejack-prevention
Anybody tried taking advantage of the "Web Storage" in HTML 5 to store a shared key (passed during SSL-encrypted responses during authentication) that is used by javascript to alter the session cookie over time?
That way, the stolen (unencrypted) session cookies would only be valid for a short amount of time.
My guess is that Web Storage is segmented by port (in addition to host), so it wouldn't be possible. Just throwing that idea out there in case anybody wants to run with it.
When user logs-in, store the IP-address in the session.
On each subsequent request from this session, check that the IP-address matches the one stored in the session.

Resources