Preventing access to JSON data in an Angular app - json

I got a (Flask) backend powering an API that serves JSON to an Angular app.
I love the fact that my backend (algorithms, database) is totally disconnected from my frontend (design, UI) as it could literally run from two distinct servers. However since the view is entirely generated client side everyone can access the JSON data obviously. Say the application is a simple list of things (the things are stored in a JSON file).
In order to prevent direct access to my database through JSON in the browser console I found these options :
Encrypting the data (weak since the decrypting function will be freely visible in the javascript, but not so easy when dealing with minified files)
Instead of $http.get the whole database then filtering with angular, $http.get many times (as the user is scrolling a list for example) so that it is programmatically harder to crawl
I believe my options are still weak. How could I make it harder for a hacker to crawl the whole database ? Any ideas ?

As I understand this question - the user should be permitted to access all of the data via your UI, but you do not want them to access the API directly. As you have figured out, any data accessed by the client cannot be secured but we can make accessing it a little more of PITA.
One common way of doing this is to check the HTTP referer. When you make a call from the UI the server will be given the page the request is coming from. This is typically used to prevent people creating mashups that use your data without permission. As with all the HTTP request headers, you are relying on the caller to be truthful. This will not protect you from console hacking or someone writing a scraper in some other language. #see CSRF
Another idea is to embed a variable token in the html source that bootstraps your app. You can specify this as an angular constant or a global variable and include it in all of your $http requests. The token itself could be unique for each session or be a encrypted expiration date that only the server can process. However, this method is flawed as well as someone could parse the html source, get the code, and then make a request.
So really, you can make it harder for someone, but it is hardly foolproof.
If users should only be able to access some of the data, you can try something like firebase. It allows you to define rules for who can access what.

Security Considerations When designing web applications, consider
security threats from:
JSON vulnerability XSRF Both server and the client must cooperate in
order to eliminate these threats. Angular comes pre-configured with
strategies that address these issues, but for this to work backend
server cooperation is required.
JSON Vulnerability Protection A JSON vulnerability allows third party
website to turn your JSON resource URL into JSONP request under some
conditions. To counter this your server can prefix all JSON requests
with following string ")]}',\n". Angular will automatically strip the
prefix before processing it as JSON.
For example if your server needs to return:
['one','two'] which is vulnerable to attack, your server can return:
)]}', ['one','two'] Angular will strip the prefix, before processing
the JSON.
Cross Site Request Forgery (XSRF) Protection XSRF is a technique by
which an unauthorized site can gain your user's private data. Angular
provides a mechanism to counter XSRF. When performing XHR requests,
the $http service reads a token from a cookie (by default, XSRF-TOKEN)
and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript
that runs on your domain could read the cookie, your server can be
assured that the XHR came from JavaScript running on your domain. The
header will not be set for cross-domain requests.
To take advantage of this, your server needs to set a token in a
JavaScript readable session cookie called XSRF-TOKEN on the first HTTP
GET request. On subsequent XHR requests the server can verify that the
cookie matches X-XSRF-TOKEN HTTP header, and therefore be sure that
only JavaScript running on your domain could have sent the request.
The token must be unique for each user and must be verifiable by the
server (to prevent the JavaScript from making up its own tokens). We
recommend that the token is a digest of your site's authentication
cookie with a salt for added security.
The name of the headers can be specified using the xsrfHeaderName and
xsrfCookieName properties of either $httpProvider.defaults at
config-time, $http.defaults at run-time, or the per-request config
object.
Please Kindly refer the below link,
https://docs.angularjs.org/api/ng/service/$http

From AngularJS DOCs
JSON Vulnerability Protection
A JSON vulnerability allows third party website to turn your JSON resource URL into JSONP request under some conditions. To counter this your server can prefix all JSON requests with following string ")]}',\n". Angular will automatically strip the prefix before processing it as JSON.
There are other techniques like XSRF protection and Transformations which will further add security to your JSON communications. more on this can be found in AngularJS Docs https://docs.angularjs.org/api/ng/service/$http

You might want to consider using JSON Web Tokens for this. I'm not sure how to implement this in Flask but here is a decent example of how it can be done with a Nodejs backend. This example at least shows how you can implement it in Angularjs.
http://www.kdelemme.com/2014/03/09/authentication-with-angularjs-and-a-node-js-rest-api/
Update: JWT for Flask:
https://github.com/mattupstate/flask-jwt

Related

Django request.body.decode security

I have a view set up to work with datatables; it accepts the data posted by datatables in JSON format, so I use:
json.loads(request.body.decode('utf-8'))
to grab the data I need to search, sort, and paginate my tables via ajax. All of this works, but I'm worried that loading the body of the request in this way could leave me open to attacks, especially since I could be loading arbitrary data in that line.
What can/should I do to make sure this doesn't leave the code open to exploitation?
Note: I am using csrf tokens in each request. I'm worried more about direct attacks from a malicious user of the system.

How to build a secure stateless authentication system for a client-side dart application

i'm building a stateless authentication system for a Dart frontend and have discovered that it's quite tricky to build a stateless authentication system that's actually secure.
The stack is as follow: Dart application that does JSON POSTs to a Spring MVC backend using Jackson to convert back and forth between JSON and Java objects. Everything will be behind SSL when it goes into production.
Scenario 1: User logs in, I keep a session on the Java side - this is not stateless and will cause problems when load balancing the backend.
Scenario 2: Upon hitting the login button, a POST is done by Dart to the Authentication controller which verifies the credentials and passes back a token (which could be a bunch of UUIDs concatenated together). The token comes back to the frontend - This token combined with the username will then have to be passed along with each request. The dart application now needs to store this token somewhere, since a Dart application compiles to JavaScript, cookies seems to be not an option (JavaScript can't access cookies ?). HTML5 localstorage comes to mind, but from what I've read, it's pretty easy to hijack that token if any form of XSS vulnerability is available (and I'm guessing browser plugins and toolbars that inject JavaScript into the page can also access this token).
Scenario 3: Just like in scenario 2, I get passed back a token from the Spring MVC backend, but instead of storing it in HTML5 localstorage, I keep in a JavaScript variable and pass it on if a new window is opened.
The same problem applies here, since it's inside a javascript variable, any kind of XSS vulnerability or browser plugin can nab that token and hijack the session.
So it seems for a stateless "session", HTML5 localstorage is the most convenient, but it's not secure. Is there a way to secure it or is there an alternative way that will allow me stateless authentication in the browser?
I got a fairly decent answer on Information Security which suggests using cookies with HttpOnly and Secure flags being set on them:
https://security.stackexchange.com/questions/84860/how-to-build-a-secure-stateless-authentication-system-for-a-client-side-javascri/84861#84861
I had to switch to servlet3 to allow setting HttpOnly flag:
Set http-only on cookies created in Spring MVC Controller
On the Dart side, I had to switch from BrowserClient as it doesn't allow cross-domain cookies:
Dart BrowserClient POST not including my cookies
I think about the question, i would save only the token in the session/local storage. All other data could be in a kind of user background controller, which can load needed data by the token(like the user profil).
The hijacking think is bad without ssl. You could try something like a hash comprising (Browser / OS / Plug in data...) as kind of controll but that would be pseudo. I think you need ssl.

Angular.js : CORS HttpInterceptor that transforms $http.get into $http.jsonp request transparently

I've been looking into if it's possible to create a web based version of my Chrome Plugin
now that it's relying completely on Trakt.TV's JSON API.
According to angular's documentation, it's possible to intercept HTTP requests at several levels, one is the HTTP Backend itself (mainly used for testing though) and the other is HTTPInterceptor.get
The basic idea is to wrap calls to Trakt.TV's JSONP api through http://json2jsonp.com/ and have them returned transparently to get around cross site scripting restrictions. This would not only be very useful for my own project, but for a lot of other people daeling with the same issues too (therefore i'll release the module after it's done, but I want to do it properly)
The basics should be simple:
Hook the $http.get request at the right level
Overwrite the original request made
Cancel an optional other request already set up
Hook it through $http.jsonp(http://json2jsonp.com/)
Return the original promise's success/fail when done
Questions:
Has anyone built anything like this yet? (Github searches revealed nothing)
Would you suggest using the HTTPBackend or the HTTPInterceptor?
why can't you just use the jsonp helper function?
httpBakend is a mockup service to fake a backend server is not used on live code. http interceptors would do what you want you just need to attach the callback function name to your request if the url contains what ever name you want to filter and then in the response interceptor you have to pass response to the callback function so the json to be evaluated. be aware that interceptors will inspect every request makde by angular which is not very eficien, unless you are only doing calls to the tv service.
like i said before a better approach is to use $http.jsonp function
https://docs.angularjs.org/api/ng/service/$http#jsonp
a word about interceptors they need to be defined as services and then be passed to HttpProvider during your apps configuration.

Customizing json rendering for sling's userManager

I am trying to build my application's admin UI using sling's userManager REST interface, but I would like to customize the json rendering. For example, I would like the response of "Get group" to include the members only if the requestor is a member.
I started by adding libs/sling/group/json.esp but I don't understand how I can get hold of the default response and customize it. Even if I had to query and form the json from scratch, where can I find information about APIs available to get this data from JCR/Sling?
I found that I could use ResourceTraversor to dump the resource object in json form but using new Packages.org.apache.sling.servlets.get.impl.helpers.ResourceTraversor(-1, 10000, resource, true) in the esp throws up an error
There are a few things to note here.
First, you should avoid putting your code under the libs directory. Your app code should live under the apps directory. When attempting to resolve a servlet for a URI, Sling will check apps before it checks libs so if you need to completely override functionality delivered with Sling, you would place your code in apps.
Second, what is (probably, depending on how you have things setup) happening when you request http://localhost:8080/system/userManager/group/administrators.tidy.1.json is the request is being handled by Sling's default GET servlet, because it finds no other script or servlet which is applicable. For research purposes it might be worth looking at the code for the default get servlet, org.apache.sling.servlets.get.impl.DefaultGetServlet, to see what it's using to render JSON. If you need to handle the rendering of a user group in a manner different than what the default GET servlet is doing, then you would need to create a servlet which is listening for requests for resources of type sling/group. It would probably be ideal to create a servlet for this purpose and register it with OSGI. http://sling.apache.org/site/servlets.html provides the various properties you would need to set to ensure the servlet resolver finds your servlet. Your servlet then would handle the request and as such would have direct and easy access to the requested resource.
Third, the particular need you specified is that you do not want the group members to render unless the requesting user is a member of the group requested. This is more of an access control issue than a rendering issue. Sling and Jackrabbit, out of the box, make as few assumptions as possible concerning how you might want your application to be setup. That being the case, you need to establish the access controls that are applicable for your particular use case. The wiki post on Access Control in the Jackrabbit wiki ( http://wiki.apache.org/jackrabbit/AccessControl ) goes into this to an extent.
Using directions from Paul Michelotti's answer, I researched further and found a suitable solution to my problem.
Sling accepts request filters (javax.servlet.Filter) through SCR annotations like the one below
#SlingFilter(scope = SlingFilterScope.REQUEST, order = Integer.MIN_VALUE)
Every request is passed down to the filter before it is processed by the servlet. Using the resourceType, I was able to distinguish requests to group.1.json and group/mygroup.1.json. Since the filter also has access to the current user, I was able to decide to deny the request if it did not abide by my security model and return a 404 status code.
Please refer to this page for details on filters. You can also check out the sample project urlfilter for directions on usage.

Using MVC3's AntiForgeryToken in HTTP GET to avoid Javascript CSRF vulnerability

In regards to this Haacked blog, I'm hesitant to implement the proposed anti-JSON GET hijacking solutions since
The recommended solutions to mitigating JSON hijacking involve non-REST-full JSON POSTs to GET data
The alternate solution (object wrapping) causes problems with 3rd party controls I don't have source-code access to.
I can't find a community-vetted implementation that implements the Alternative Solution (listed below) on how to compose the security token, or securely deliver it within the webpage. I also won't claim to be enough of an expert to roll my own implementation.
Referrer headers can't be relied upon
Background
This blog describes a CSRF issue regarding JSON Hijacking and recommends using JSON POSTs to GET data. Since using a HTTP POST to GET data isn't very REST-full, I'd looking for a more RESTfull solution that enables REST actions per session, or per page.
Another mitigation technique is to wrap JSON data in an object as described here. I'm afraid this may just delay the issue, until another technique is found.
Alternative Implementation
To me, it seems natural to extend the use ASP.NET MVC's AntiForgeryToken with jQuery HTTP GETs for my JSON.
For example if I GET some sensitive data, according to the Haacked link above, the following code is vulnerable:
$.getJSON('[url]', { [parameters] }, function(json) {
// callback function code
});
I agree that it isn't RESTfull to GET data using the recommended POST workaround. My thought is to send a validation token in the URL. That way the CSRF-style attacker won't know the complete URL. Cached, or not cached, they won't be able to get the data.
Below are two examples of how a JSON GET query could be done. I'm not sure what implementation is most effective, but may guess that the first one is safer from errant proxies caching this data, thus making it vulnerable to an attacker.
http://localhost:54607/Home/AdminBalances/ENCODEDTOKEN-TOKEN-HERE
or
http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE
... which might as well be MVC3's AntiForgeryToken, or a variant (see swt) thereof. This token would be set as an inline value on whatever URL format is chosen above.
Sample questions that prevent me from rolling my own solution
What URL format (above) would you use to validate the JSON GET (slash, questionmark, etc) Will a proxy respond to http://localhost:54607/Home/AdminBalances with http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE data?
How would you deliver that encoded token to the webpage? Inline, or as a page variable?
How would you compose the token? Built in AntiforgeryToken, or by some other means?
The AntiForgeryToken uses a cookie. Would a backing cookie be used/needed in this case? HTTP Only? What about SSL in conjunction with HTTP Only?
How would you set your cache headers? Anything special for the Google Web Accelerator (for example)
What are the implications of just making the JSON request SSL?
Should the returned JSON array still be wrapped in an object just for safety's sake?
How will this solution interop with Microsoft's proposed templating and databinding features
The questions above are the reasons I'm not forging ahead and doing this myself. Not to mention there likely more questions I haven't thought of, and yet are a risk.
The Asp.net MVC AntiForgeryToken won't work through HTTP GET, because it relies on cookies which rely on HTTP POST (it uses the "Double Submit Cookies" technique described in the OWASP XSRF Prevention Cheat Sheet). You can also additionally protect the cookies sent to the client by setting the as httponly, so they cannot be spoofed via a script.
In this document you can find various techniques that can be used to prevent XSRF. It seems the you described would fall into the Approach 1. But we have a problem on how to retrieve the session on the server when using Ajax HTTP GET request since the cookies are not sent with the request. So you would also have to add a session identifier to you action's URL (aka. cookieless sessions, which are easier to hijack). So in order to perform an attack the attacker would only need to know the correct URL to perform the GET request.
Perhaps a good solution would be to store the session data using some key from the users SSL certificate (for example the certs thumb-print). This way only the owner of the SSL certificate could access his session. This way you don't need to use cookies and you don't need to send session identifiers via query string parameters.
Anyway, you will need to roll out your own XSRF protection if you don't want to use HTTP POST in Asp.net MVC.
I came to this problem and the solution was not so trivial however there is a fantastic blog to get you started this can be used with get and post ajax.
http://johan.driessen.se/posts/Updated-Anti-XSRF-Validation-for-ASP.NET-MVC-4-RC
If you place the following in the global name space all your post/gets can take advantage having an anti forgery token and you don't have to modify your ajax calls. Create an input element in a common page.
<form id="__AjaxAntiForgeryForm" action="#" method="post">#Html.AntiForgeryToken()</form>
The following javascript will read the anti forgery tokken and add it to the request header.
// Wire up the global jQuery ajaxSend event handler.
$(document).ajaxSend(namespace.ajax.globalSendHandler);
// <summary>
// Global handler for all ajax send events.
// </summary>
namespace.ajax.globalSendHandler = function (event, xhr, ajaxOptions) {
// Add the anti forgery token
xhr.setRequestHeader('__RequestVerificationToken', $("#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]").val());
};
I think it is legitimate to use AntiforgeryToken (AFT) within an ajax http GET request provided that it is embedded in a form that already provides the AFT and associated cookie. The ajax handler can then do the validate on the server just how it would in a normal form post.