According to this Angular 2 guide:
Don't expect the decoded JSON to be the heroes array directly. This server always wraps JSON results in an object with a data property. You have to unwrap it to get the heroes. This is conventional web API behavior, driven by security concerns.
('Heroes' is an array of objects).
The link in the above paragraph says :
Always return JSON with an Object on the outside
Always have the outside primitive be an object for JSON strings:
Exploitable:
[{"object": "inside an array"}]
Not exploitable:
{"object": "not inside an array"}
Also not exploitable:
{"result": [{"object": "inside an array"}]}
My Question is: Why shouldn't the server return something like a JSON array?
Say :
[
"apples"
,"oranges"
, "peaches"
]
How is this a security concern ?
To avoid JSON Hijacking:
The fact that this is a JSON array is important. It turns out that a script that contains a JSON array is a valid JavaScript script and can thus be executed. A script that just contains a JSON object is not a valid JavaScript file.
For example, if you had a JavaScript file that contained the following JSON: {“Id”:1, “Balance”:3.14} And you had a script tag that referenced that file:
<script src="http://example.com/SomeJson"></script>
You would get a JavaScript error in your HTML page. However, through an unfortunate coincidence, if you have a script tag that references a file only containing a JSON array, that would be considered valid JavaScript and the array gets executed.
So allowing JSON to be returned as anything but an object would make it possible to return a JSON array that contained code that could be run on the client level (in a context where the client isn't expecting it to be runnable, could be malicious, etc). Only returning JSON objects prevents this from happening.
This was rather bad advice that has since been removed from the angular tutorial.
The linked OWASP Cheet Sheet lists three ways to defend against JSON Hijacking. The one the tutorial picked is the hardest to implement correctly, because one must educate every single developer, and audit every single REST resource, rather than writing a single HttpInterceptor to extend CSRF-defenses to GET requests.
JSON hijacking can only occur due to browser bugs, which tend to be fixed quickly (this does not imply such attacks are impossible, but the easy exploits no longer work in modern browsers)
Related
I've read a lot about sanitizing and escaping of untrusted data, e.g. starting with this cheat sheet. But I didnt get the full picture yet. I am struggeling to understand, what principles I have to follow in order to parse JSON data safely.
Let's be more precise by means of an example. I retreive an Object in JSON format via an Ajax call from my server. The object shoudnt contain any malicious code, but.... you never now. So I parse the JSON data using JSON.parse in JS. The sesult is a multilevel JS object. I use the object in various way, e.g. creating table code via JS and writing it in the DOM.
Is this approach safe. Or do I have to somehow escape the invidual items of the object individually? Appreciate your help. Happy to concrete my example if necessary.
So, I'm originally a native application developer (mostly C++), but I've found myself working on a small business Coding project for a friend. I'm used to self contained native applications and I'm struggling with a current problem on my project:
I have an AppInstance class in PHP which is implemented as a singleton (I've heard that most of the time this isn't really the best way to do things, and I concede this). This class contains a few basic operating parameters for the application (mostly simple strings and numbers), as well as an array of complex objects (objects composed of other objects, arrays and other members and methods). I'd like to be able to pass any/all of this application data between this original PHP script (which initializes all of the values that my program needs to run, and outputs the default HTML of my UI).
I then begin to handle user input actions with Javascript. Some of these inputs require information from the original PHP script. Because the processing of these inputs requires a bit more computation, I'd like to use AJAX to call this processing on the server (in PHP) and return the output. However, Because this processing requires some of the objects from the original PHP script, I'm trying to figure out how I should pass these objects around in the most efficient way?
I've read that I can use JSON encode to effectively serialize my objects and send them to JS (the UI in this case), and these objects can be returned to PHP (see this). But my question really is a multi-part:
Would it be more efficient to perform all calculations and processing on the server (in PHP, rather than doing it all on the client-side in JS)?
If the answer to #1 is "Yes", my first inclination is to serialize the PHP object to a file on the server, and have the new PHP script read and deserialize the object. Is there a more efficient method than this and,if not, should I serialize in JSON or PHP's serialize() format?
Edit: I should probably mention that some of my objects also possess resource variable, as I know this has some effect on serialization.
In terms of efficiency I would be looking at whatever reduces the number of network (AJAX) calls, as this will usually be your largest overhead. This is hard to comment on in your case because I don't know how often a client is going to be making such calls. A bigger worry for me is security, as Javascript would be able to manipulate values it gets from the AppInstance. I personally would consider an API which only exposes actions you permit.
I'm looking for most elegant way of "dumping" simple JavaScript object into JavaScript source-code generated on-fly.
Purpose:
Assume we have node.js server generating HTML. We have an object x on server side. The object is simple - only strings/ints/arrays in it (so, it's JSON-able). I want to "embed" object x into HTML being generated, to be available for JavaScript code which will run on the browser. So the code:
console.log(x);
will dump exactly the same data on both server-side and browser-side.
For example - imagine I'm going to pass some additional config/data to JavaScript running on browser.
Obvious solutions:
Encoding as JSON and send as AJAX/Websocket is not a part of this question as we have to embed the object in the HTML. I don't want additional HTTP requests - everything should be passed in one go.
Encoding as JSON and simply attach to variable sounds initially good, but involves some additional escaping steps.
Using util.inspect() works for me, in this way:
var toHtml = 'var x = ' + util.inspect(theXonServer, {depth:9}) + ';';
but I'm not sure if it's "elegant" (and secure and error-prone and...)
Any better suggestions ? Standard way of doing that ?
The Wrong Way to Pass Data
It's common to get advice to just stringify some JSON and dump it into a <script> tag. This is bad advice. Don't do it.
It's important to understand why this is a bad idea.
When you string-build JavaScript, you're opening yourself up to all sorts of quirks of the language that you'd absolutely be required to understand to make sure that there are no issues.
One such quirk is that within a <script> element, the first occurrence of </script> will close the <script> element. It doesn't matter that it's in a string, the script will be closed, and the rest of the contents after that point will be treated as HTML.
HTML escaping doesn't work because JS doesn't like HTML entities.
what might start as:
<script>
window.xss = <%= JSON HERE %>
</script>
could turn into:
<script>
window.xss = {"username":"Robert Hackerman</script><script src='nefarious.js'></script>"}
</script>
Don't risk it.
The Right Way to Pass Data...
...When the Page is Rendering
The much safer way that prevents any script execution is via [data-*] attributes. You must HTML-escape the contents, but that's OK in attributes. I'm using a <script> element because it's implied that the script will be using the data.
What would start as:
<script data-foo="<%= HTML ENCODED JSON HERE %>" src="yourscript.js"></script>
Would turn into:
<script data-foo="{"username":"Robert Hackerman</script><script src='nefarious.js'></script>"}" src="yourscript.js"></script>
And if you want access to that data, you can just access the attribute value, or use the dataset api (if your target browsers support it):
var fooElement = document.querySelector('[data-foo]');
var rawData = fooElement.dataset.foo;
// or
var rawData = fooElement.getAttribute('data-foo');
var data = JSON.parse(rawData);
console.log(data);
...After the Page has Rendered
If the page has already loaded, and you want to access some data, just use an AJAX request. You'll be able to safely read in a JSON data source, which can be piped through JSON.parse to access the data object.
Util.inspect vs JSON.stringify
You only need util.inspect if your object is circular. If it's JSON encodable in 99.9% of cases you can just output it to the source with JSON.stringify.
Using JSON
There are edge cases to this - not only are JS objects more expressive than JSON (functions etc), JSON objects can do things JS objects can't (in edge cases of encoding). So make sure not only is your object serializable correctly, it's also deserializable correctly. I also assume you didn't do anything crazy like override the array constructor (which would make JS objects behave differently from JSON ones).
Security
As for security, unless your object can contain sensitive data (and it really shouldn't, whitelist it first) there should not be any related issues.
Overall option 2 is a standard approach that is quite commonly used - including on this very site.
It usually works for simple data which is most data you need to share (numbers and strings).
It saves the round trip.
It's used very often in big sites and in practice.
I am trying to access a result in a dictionary held in a Python global variable within JavaScript.
var selected = jQuery('.target option:selected').text()
var list = "${c.persons_by_permission["+selected+"]}"
If I directly access the dictionary without the using the variable:
var list = "${c.persons_by_permission['stringID']}"
Then the code works.
However, when I am trying to use the variable to access the dictionary I get a syntax error (I believe its because of the curly braces).
I have tried escaping the braces with:
var list = "${{c.persons_by_permission["+selected+"]}}"
But it gives more syntax exceptions.
Any ideas?
EDIT:
This is not an issue of whether I can use Python and javascript together, it is more of a question of escaping the curly brackets
I am using pylons, so if I try:
alert("${c.persons_by_permission['Documents']}")
I will get the results I need. The issue is that I cannot find a way of passing a variable into the javascript in place of 'Documents'
I'm making a few (reasonable) assumptions here…
Your Python is running on your webserver
Your JavaScript is running on your client
As far as the Python is concerned it is outputting text. It doesn't care that the browser might interpret it as HTML, JavaScript or whatever. It just generates some text and then sends it to the browser.
With HTTP you get to make a request and have a response. You cannot stop a response half way through to get data back from the client.
You cannot pass data from client side JS back to the Python process that generated the JS. That process will have finished running.
You can either:
Send all the data to the client in the first place (and then select the bits you want in JS instead of in Python)
Have the JavaScript make a new HTTP request to the server and process the response in JS (this is known as Ajax and there are no shortage of tutorials out there for this)
I don't know what execution environment you are using,but I am almost certain that python and javascript are not executing at the same time.
${c.persons_by_permission['stringID']} looks to me like some kind of template directive. If so, this works because the directive is processed at template processing time. Your other form is just an expression in javascript that evaluates in javascript to a string.
If my JSON data-file comes from a database result set and that result set is empty, how do I tell OFC2 to display an error message, instead of crashing because of a malformed JSON string?
Add tags for javascript and actionscript-3 to this question and you should get a load more views and useful responses than you currently are, with more precise details than I am giving. Post the actual JSON string that is causing you the problem and that you would like to be guarded against. That way people can suggest a regexp to catch it, treating it as a string rather than as JSON data at some point before JSON.decode() happens.
In more detail:
You can catch it in two places. One route is to switch over to using the javascript interface to OFC2 and use client side javascript to detect the bad string. This allows you to modify the JSON string client side. See http://teethgrinder.co.uk/open-flash-chart-2/tutorial-5.php for that approach. One downside is that the clients must have javascript enabled for this to work.
Alternatively, since OFC2 is LGPL, you or an actionscript developer can dive into the OFC2 source code and do the same thing there. I am not an actionscript developer so you are better off ensuring you get a reply from one.
The main thing is to add those two tags to this question. 22 Views is way too low for a question with a bounty of 500. Hope this helps.
Several solution avenues are possible, depending on your level of access to the server and your knowledge of JavaScript and/or any server-side platforms.
With access to database
Depending on the kind of data you are displaying, it might be possible to add dummy records for those queries that would otherwise have returned an empty set. If you have access to the query definition, you may check for the empty set in the DB-query. For example, if you're on MS SQL Server you could check the condition with some T-SQL statements.
With access to server
If you have access to the server side script generating the dataset, add a condition that returns some default value that OFC2 will handle correctly.
With access to another server or serverlocation
If you don't have access to the specific script, you may consider creating a new script at another location that queries the original script and replaces empty results with the default value.
Client-side only
You can add the JavaScript open_flash_chart_data function (see tutorial) to replace empty datasets. OFC2 can use that function as data source.
Hope this helps.