Support Locating the CSRF Vulnerability - html

I'm analysing a project that uses Spring Security and AngularJS. I know there is a CSRF vulnerability within a specifc form, but I'm unable to get my head around it.
The server sets a CSFR Token as a cookie (not HTTP only, not Secure) for each session. It remains the same for each session. On form submission, AnagularJS takes this cookie and appends it to a custom HTTP header, as shown below.
My understanding is that this is the best method of protecting a site, double submit. With the assumtion that it's already XSS secure, it will not be possible for another site to set a custom header on a HTTP request?
I've searched many forums and many say this is the best method of using a CSRF token, even better than putting within a hidden field in the form.
I'd like ask if anyone knows why this method isn't secure and if it is vulnerable to CSRF.
Many thanks!
P.S - I should add the CSRF token appears to be a randomly generated value, not linked to the session. If I use burpsuite to edit both the header and cookie, to any value, the server will still accept it.
I'm attempting to locate the CSRF vulnerability and then I can work on repairing it.

Related

Does adding anti CSRF token in hidden field really protect against CSRF attacks? [duplicate]

This question already has answers here:
Understanding CSRF
(4 answers)
What is a CSRF token? What is its importance and how does it work?
(5 answers)
Why can't a malicious site obtain a CSRF token via GET before attacking?
(2 answers)
Closed 2 years ago.
If an attacker can read hidden fields then how is sending anti CSRF token in a hidden field useful?
I am preparing for an interview and came across CSRF.I know that CSRF is possible because whenever our browser sends a request to the website we are logged in it automatically sends cookies with it too. For the authentic server to know if the user really made a request, this article suggests that a anti CSRF token should be added as an hidden value in every request sent by the browser. This way the authentic server will know which request was forged and which was not as an attacker cannot predict the anti CSRF token.
But this post says that an attacker can easily see the hidden values. Doesn't this make the above suggested mitigation useless? I am confused.
Context and attention to detalis are important.
For starters, the answer to Web security, are there issues with hidden fields (no sensitive data)? doesn't say that an attacker can "easily" see the hidden values, but that it would be "just as easy" as seeing query string parameters - that's a comparative, not absolute.
Then you have to consider who the attacker is. Debating hidden fields vs. query parameters implies simply hiding values that the user isn't supposed to see - the attacker is a regular user accessing the page.
CSRF on the other hand, in the most generic case, involves a third-party tricking the user into submitting a form; the attacker is the third-party and (unless other vulnerabilities are present) isn't able to just read the user's data.
And finally, the protection technique described in the blog post you linked doesn't rely merely on a hidden field, but it couples it with a token stored in a cookie - this is known as the Double Submit Cookie pattern and is a textbook CSRF protection mechanism. An adversary would need to match both the form and cookie tokens to perform a successful attack.
So yes, the solution outlined in the blog post does prevent CSRF attacks.

Security To Implement On Persist Cookie REST Api Website / Mobile Apps

So my current state is I have a REST API web server (ASP.Net Web API), a website in plain Html which communicates with the server via ajax / angular post and get, also I have a mobile application which communicates via ajax / angular post and get.
I use Basic Auth header to secure the request, the web server will decrypt the content of the auth header and do the verification after.
What kind of attacks would the system be vulnerable to? Also what kind of security should I implement.
I read about the CSRF attacks and I think my system have no protection against it, but I have no idea how to implement it on REST API.
Also what about the cookie stealing attacks. Because my system uses persist cookies to store the auth token, how to deal with this kind of attack?
To prevent CSRF attacks, both your backend (ASP.NET Web API) and frontend (Angular) must be configured to prevent such an attack.
Taken from https://angular.io/guide/security#xsrf:
To prevent XSRF, the application must ensure that a user request originates from the real application, not from a different site. The server and client must cooperate to thwart this attack.
In a common anti-XSRF technique, the application server [backend] sends a randomly generated authentication token in a cookie. The client code reads the cookie and adds a custom request header with the token in all subsequent requests. The server compares the received cookie value to the request header value and rejects the request if the values are missing or don't match.
This technique is effective because all browsers implement the same origin policy. Only code from the website on which cookies are set can read the cookies from that site and set custom headers on requests to that site. That means only your application can read this cookie token and set the custom header. The malicious code on evil.com can't.
With that in mind, here's another quote from Angular HttpClient Docs which explains how you can implement it.
Taken from https://angular.io/guide/http#security-xsrf-protection:
When performing HTTP requests, an interceptor reads a token from a cookie, by default XSRF-TOKEN, and sets it as an HTTP header, X-XSRF-TOKEN. Since only code that runs on your domain could read the cookie, the backend can be certain that the HTTP request came from your client application and not an attacker.
By default, an interceptor sends this header on all mutating requests (POST, etc.) to relative URLs but not on GET/HEAD requests or on requests with an absolute URL.
your server needs to set a token in a JavaScript readable session cookie called XSRF-TOKEN on either the page load or the first GET request. On subsequent requests the server can verify that the cookie matches the X-XSRF-TOKEN HTTP header, and therefore be sure that only code running on your domain could have sent the request. The token must be unique for each user and must be verifiable by the server; this prevents the client from making up its own tokens. Set the token to a digest of your site's authentication cookie with a salt for added security.
Key points to take note would be:
When the angular app is loaded, it should make an API call first to your backend to retrieve an authentication token that is saved as a cookie that with the name "XSRF-TOKEN". Probably somewhere on root component (app.component.ts) ngOnInit() sounds like a good place.
By default, the authentication token will be automatically injected in the http header on all mutating requests such as POST. (Take note of this though, it is undocumented: Angular 6 does not add X-XSRF-TOKEN header to http request). Unless you return a custom-named cookie, then you have to use Angular's HttpClientXsrfModule.
With that in mind, your ASP.NET Web API should also be validating the XSRF-TOKEN as it receives requests.
With regards to your second question, cookie hijacking is done via XSS.
XSS vulnerabilities generally occur when an application takes user input and outputs it to a page without validating, encoding or escaping it.
Angular by default sanitizes inputs for tags. However, this is provided you do things "the angular way". If you use third-party libs, such as jQuery, to manipulate the DOM instead of using Angular's renderer2 module, you might lose this protections.
Taken from: https://angular.io/guide/security#xss:
In the same way, if you interact with other libraries that manipulate the DOM, you likely won't have the same automatic sanitization as with Angular interpolations. Avoid directly interacting with the DOM and instead use Angular templates where possible.
For cases where this is unavoidable, use the built-in Angular sanitization functions. Sanitize untrusted values with the DomSanitizer.sanitize method and the appropriate SecurityContext.
To increase security, you should also sanitize any mutating requests (such as PUT or POST) in your backend.
It is difficult to provide you with code examples because your question seem to be a more theory-based question.
I hope you will take a read on those links that I have hyperlinked above. They are definitely more detailed and well-explained. I hope it will at least point you in the right direction of what to get started on.

CSRF attack - GET and POST request on same page

One web application has a delete button. Once clicked that web application do GET request first which will return POST form with token key.
Asking Yes or No. if yes, resource is deleted.
How I can achieve this for CSRF attack? I can submit first request hidden in iframe but I need that token to submit second POST request.
Ajax fails due to CORS.
So is it even possible on one page
Send GET request
Parse response and get token
Submit POST form with token to trigger CSRF
I think this is essentially the standard protection against CSRF, a token is generated upon page generation (a GET), and it's verified upon submit (POST) that actually changes application state (deletes an object in your case). So conceptually it looks good to me.
The devil is in the details though. How is the token generated (what algorithm and/or random generator is used, how much entropy it has) and how is it then verified? Is it stored somewhere or stateless? When do you generate a new token and when do you reuse an old one? These are some questions that must be taken into account as always when protecting against CSRF.
One special question that comes to mind for your scenario is whether the confirmation page has all the details about what will be done. A simple "Are you sure?" would not be adequate in your case I think.

Include Additional HTTPS Request Header Information in Form

Is there a way to include additional request headers in form data, other than action and method? I am hoping to send some authentication credentials cross domain without making the user re-enter their login credentials. ie I want to build an Authentication header directly from form submission.
The domain is SSL enabled, so I considered including credentials in the URL, but as explained here this is a bad idea, as those credentials may be secure over the connection, but can be accessed through the browser by other apps potentially.
Larger Picture
I have access to the cross domain username and password through an AJAX request to the client server (home domain). I want to take those credentials and submit them through a non-AJAX request, so a user can download a document securely without the URL being publicly accessible.
To the specific question, I believe the answer is no - you can't control sending any extra headers from the form itself. There are some other things you can send with a form, but they are not useful to what you want to do: W3 Form Tag Specification
What you could do is do a form POST, which is the standard way to communicate when sessions cookies are out of the question and a query string won't do; just use a hidden field with some sort of token/hash of the credentials. Avoid clear-text of passwords like the plague, and really try to avoid reversible encryption of them too. This is just one of those areas you have to be extra careful to avoid creating an easily exploitable security vulnerability.
But generally speaking it works just fine, and anything that can do an AJAX GET should be able to do an AJAX POST.

Cross Domain Form POSTing

I've seen articles and posts all over (including SO) on this topic, and the prevailing commentary is that same-origin policy prevents a form POST across domains. The only place I've seen someone suggest that same-origin policy does not apply to form posts, is here.
I'd like to have an answer from a more "official" or formal source. For example, does anyone know the RFC that addresses how same-origin does or does not affect a form POST?
clarification: I am not asking if a GET or POST can be constructed and sent to any domain. I am asking:
if Chrome, IE, or Firefox will allow content from domain 'Y' to send a POST to domain 'X'
if the server receiving the POST will actually see any form values at all. I say this because the majority of online discussion records testers saying the server received the post, but the form values were all empty / stripped out.
What official document (i.e. RFC) explains what the expected behavior is (regardless of what the browsers have currently implemented).
Incidentally, if same-origin does not affect form POSTs - then it makes it somewhat more obvious of why anti-forgery tokens are necessary. I say "somewhat" because it seems too easy to believe that an attacker could simply issue an HTTP GET to retrieve a form containing the anti-forgery token, and then make an illicit POST which contains that same token. Comments?
The same origin policy is applicable only for browser side programming languages. So if you try to post to a different server than the origin server using JavaScript, then the same origin policy comes into play but if you post directly from the form i.e. the action points to a different server like:
<form action="http://someotherserver.com">
and there is no javascript involved in posting the form, then the same origin policy is not applicable.
See wikipedia for more information
It is possible to build an arbitrary GET or POST request and send it to any server accessible to a victims browser. This includes devices on your local network, such as Printers and Routers.
There are many ways of building a CSRF exploit. A simple POST based CSRF attack can be sent using .submit() method. More complex attacks, such as cross-site file upload CSRF attacks will exploit CORS use of the xhr.withCredentals behavior.
CSRF does not violate the Same-Origin Policy For JavaScript because the SOP is concerned with JavaScript reading the server's response to a clients request. CSRF attacks don't care about the response, they care about a side-effect, or state change produced by the request, such as adding an administrative user or executing arbitrary code on the server.
Make sure your requests are protected using one of the methods described in the OWASP CSRF Prevention Cheat Sheet. For more information about CSRF consult the OWASP page on CSRF.
Same origin policy has nothing to do with sending request to another url (different protocol or domain or port).
It is all about restricting access to (reading) response data from another url.
So JavaScript code within a page can post to arbitrary domain or submit forms within that page to anywhere (unless the form is in an iframe with different url).
But what makes these POST requests inefficient is that these requests lack antiforgery tokens, so are ignored by the other url. Moreover, if the JavaScript tries to get that security tokens, by sending AJAX request to the victim url, it is prevented to access that data by Same Origin Policy.
A good example: here
And a good documentation from Mozilla: here