How to make a cross-domain form CSRF and replay resistant? - html

I'm contemplating making a project, but I'm wondering if cross-site request forgery would make it impossible to secure.
Basically, I want to have a web service that generates a form using the usual tricks(JSON-P and iframes) on another domain's page. So WebService.example.com generates a form's HTML, and it's shown to the user on User.example.com
This form, I assume will have to use the injected iframe trick to submit the form from javascript. Because anyone would be able to just get the same data from WebService.example.com, how can I ensure that it's actually only coming from User.example.com? Preferably, without having to have any server-side code running on User.example.com.
Note, I'll be using ASP.Net for the WebService, but I'd like it explained in a language/framework agnostic manner

This is pretty hard to do without using server side scripts on both domains.
If you change your architecture and just use Cross-Domain Messaging (host the form etc in the top domain, use iframe for communication) then you could use the XDM to verify that it is indeed the intended domain you are talking to.
If you only target HTML5-capable browsers then use postMessage, if you want broader support, and things like RPC etc then use easyXDM, which abstracts all of the hassle with cross-domain messaging.
Actually, you can host your form in either document, you just need to use the XDM-communication in order to do a successful 'handshake', verifying the origin.

Related

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.

Accessing form data inside iframe

Is it possible to access form data with javascript inside iframe from external source?
For example: I have a web store on example.com. If I use payment gateway stripe.com with iframe integration https://stripe.com/checkout is it possible to access input data user inserts in iframe popup on interval 1s?
I would like to be sure that i case one hacks into my website, one cannot access payment details of customers.
Is it possible to access form data with javascript inside iframe from external source?
No. This is prevented by the Same Origin Policy.
If I use payment gateway stripe.com with iframe integration https://stripe.com/checkout is it possible to access input data user inserts
Not in a straightforward JS way, but there have been a number of clickjacking attacks against content in iframes. See for example http://www.contextis.com/documents/5/Context-Clickjacking_white_paper.pdf
However in this case the point is moot, as:
I would like to be sure that i case one hacks into my website, one cannot access payment details of customers.
This is not achievable. If your site is compromised (either at the server or at the client via XSS), the attacker can change the parent page to make it pop up a fake checkout iframe instead of using the real Stripe script, one that leaks entered payment details.
This is a risk with all iframe-based checkouts: the user can't verify the origin and HTTPS details of an iframe, so they have to trust those of the parent page (merchant).

Using a completely decoupled frontend with user authentication

I'm playing with the idea of having a completely decoupled HTML5 frontend, but still user authentication for a web app. Is this possible or will I run into some heavy browser security issues?
The idea is to have all static content delivered through a CDN on like example.com, and having it fetch dynamic data (and user authentication) through a separate subdomain, like api.example.com.
This would speed up the loading time of the site, and I could keep the frontend stuff in a completely separate repo so that the developers don't have to worry about setting up the backend to develop and test new features.
Is this already possible in some JS framework perhaps, backbone.js, angular.js, ember.js, knockout.js ?
It definitely is, but I think it is more about approach rather than technology. I have implemented what you describe for a project (it's online but don't want to do a shameless plug here, if interested to check it out I can post the link). My stack is java in the backend exposing a REST api for both autentication and business logic. The client is a backbone.js application. I explicitely decided NOT to use sessions at all. It is completely stateless. This of course means that the user must be re-authenticated at every request.
When the user logs in through a slightly modified OAuth endpoint, it gets a token that must be passed at every request. Cookie works in this case as they are handled automatically by the browser. If not passed as cookie, the backend expect it as a parameter. The frontend communicates using the REST endpoints. It's a single-page application, full client side, this means that the backend serves a page that is basically empty, that include few JS files that are the application itself. No other pageload occurs. Logout is done by simply deleting the cookie or not sending the authToken, the server cannot and doesn't have to "forget" about the user. Token are nice as they can be invalidated, both expilcitely or by changing the password. I've chosen this approach as it made it easy to develop desktop app and browser plugin for my webapp without touching a single line of backend code.

how to safe/hide json data in firebug like facebook

whenever, i request to server using jQuery-ajax for retrieve data that is shows in firebug so that is unsafe or hackable.
even facebook and google+ hide their json data, but how?
You could use a library like crypto-js to encrypt all data that is sent to and from the server. However, most of the time, that is an overkill when you already use https (since you should make your application hack resistant via server side validation and safety is ensured by the real encryption offered by https).

Is there a way, aside from SSL, to allow secure input on webpages?

I want to set up a project page on GitHub, so that it acts as a live site.
The site would require an API sid & token (both just long strings of text) that, in a self-hosted environment, the user would just add to the config file.
If I host this through GitHub project pages, users will supply their sid/token through a form. The page with the form will need to be served over SSL so that the sid/token aren't transferred as cleartext. The problem is that GitHub project pages don't allow SSL.
So, if I can find another secure way to take input through a form aside from using SSL, then I can host this whole thing a hosted service through GitHub project pages.
The project would be open source, so I don't expect any sort of encoding/hashing scheme to work, since the methods would be public.
The sid/token are being used in curl calls to an API which is sent over SSL. Perhaps there's a way to direct the form input directly to that SSL URL instead of having it go through the non-SSL GitHub project page...
Any ideas?
You can just give the action attribute of the form the HTTPS URL of the target script, if that's possible.
You could also use some kind of Challenge-Response encryption/hashing scheme using Javascript. The algorithm for that would be something like this:
Server generates unique, random token, saves it and sends it to the client along with the form HTML.
On the client side, Javascript intercepts the form submission and hashes the sensitive form data with the server-generated token as a salt.
Server can now check whether the hash is equal to its own calculated hash value
HOWEVER
A man-in-the-middle attacker with the ability to modify traffic (for example through ARP poisening, DHCP or DNS spoofing) could always strip all your client-side protection mechanisms from the served HTML. Have a look at SSLStrip for a tool to rewrite HTTPS URLs to unsecure HTTP URLs on the fly. The challenge-response could be defeated something like this:
Save token sent by the server, remove the Javascript from the HTML form.
As the form submission is not intercepted now, we get the raw input data.
Hash the data using the same algorithm that the Javascript would have performed.
Thank you for all the fish.
You see, an intercepting attacker can probably defeat any defense mechanism you try to make up.