Yesterday, I read some nice articles about how to prevent Json Hijacking with Asp.Net MVC. The rule is: never send sensible data in json format over a get request. With a simple search on google, you can easily learn how to define a script that will be use to extract data from another use with the help of his auth cookie.
But after reading all these articles, I don't know why it's not possible to do Json Hijacking with Ajax Jquery post request. I read that Ajax requests are subject to the same origin policy but JQuery have a property to be able to do cross-domain request.
In this case, is it possible to do Json Hijacking with a script using $.postJSON on the document ready event? If yes or no, could you explain my exactly why?
Here is a simple bunch of code to do what I'm thinking:
$.postJSON = function (url, data, callback) {
$.post(url, data, callback, "json");
};
<script>
$(function(){
$.postJSON("/VulnerableSite/ControllerName/ActionName",
{ some data parameters }, function() {
// Code here to send to the bad guy the data of the hacked user.
}
});
</script>
Thank you very much.
but JQuery have a property to be able to do cross-domain request.
Yeah, but it works only with GET requests. You cannot do cross domain AJAX calls with POST requests. Also most modern browsers have already fixed the possibility to override the __defineSetter__ method. The idea of this attack relies on including a <script> tag pointing to your website from a malicious site. But the browser sends a GET request in order to retrieve this script and not POST. That's why it is safer to use POST to transmit sensitive information with JSON.
Related
I am having problems getting an image URL from a Wordpress JSON API and fill in an image tag.
Here's my non-working code:
$(document).ready(function() {
$.getJSON('http://interelgroup.com/api/get_post/?post_id=4683', {format: "json"}, function(data) {
$('#thumb').attr("src", data.post.thumbnail_images.full.url);
});
});
And the HTML is like:
<img id="thumb" src="#">
What am I doing wrong?
Help appreciated.
Thanks!
NOTE: My real case is dynamic (I am getting a dynamic list of post IDs and looping through them with $.each()), but for this case I am providing an example with an hardcoded post ID, so you can check the JSON returned.
Your problem is because you can't do cross request using Javascript, say websiteA.com wants to fetch information from websiteB.com with a plain XMLHttpRequest. That's forbidden by the Access Control.
A resource makes a cross-origin HTTP request when it requests a resource from a different domain than the one which served itself. For example, an HTML page served from http://domain-a.com makes an <img> src request for http://domain-b.com/image.jpg. Many pages on the web today load resources like CSS stylesheets, images and scripts from separate domains.
For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example, XMLHttpRequest follows the same-origin policy. So, a web application using XMLHttpRequest could only make HTTP requests to its own domain. To improve web applications, developers asked browser vendors to allow XMLHttpRequest to make cross-domain requests.
If you know the owner of the website you're trying to read, what you can do is asking them to add your domain to the whitelist in the page headers. If you do so, then you can do as much as $.getJSON as you want.
Another alternative could be using some sort of backend code to read that website and serve it locally. Say your website is example.com, you could have a PHP script that runs on example.com/retrieve.php where you can query that website, adding the "parameter" you need. After that, since example.com is your own website you can just do a $.getJSON to yourself. There's a simple PHP proxy you can use here with a bit of explanation on why you can do it this way.
A third option would be editing the Javascript code to use Yahoo! YQL service. Although there's no guarantee that'll work forever, you can use it to query the website on your behalf and then use it to print whatever you want to the screen. The downside is that this maybe is not ethically correct if you do not own the website you're trying to fetch (plus, they can add a robots.txt file preventing the access).
Hope that helps.
JSONP solves the problem. Just need to add a callback parameter and specify it is a JSONP, like:
$(document).ready(function() {
$.getJSON('http://interelgroup.com/api/get_post/?post_id=4683&callback=?', {format: "jsonp"}, function(data) {
$('#thumb').attr("src", data.post.thumbnail_images.full.url);
});
});
More info here: Changing getJSON to JSONP
Info on JSONP: https://en.wikipedia.org/wiki/JSONP
(extremely ignorant question, I freely admit)
I have a simple web page with a button and a label. When I click the button, I want to make a REST call to an entirely different domain (cross-domain, I know that much) and display the results (HTML) in the label.
With other APIs, I've played around with using JSON/P and adding a element on the fly, but this particular API doesn't support JSON so I'm not sure how to go about successfully getting through.
The code I have is:
function getESVData() {
$.get('http://www.esvapi.org/v2/rest/passageQuery?key=IP&passage=John+1', function (data) {
$('#bibleText').html(data);
app.showNotification("Note:", "Load performed.");
});
}
I get an "Access denied." Is there anyway to make this call successfully without JSON?
First off, JSON and JSONP are not the same. JSON is a way of representing information, and JSONP is a hack around the same-origin policy. JSONP works by requesting information from another domain, and that domain returns a script which calls a function (with the name you provided) with the information. You are indeed executing a script on your site that another domain gave to you, so you should trust this other domain.
Now when trying to make cross domain requests you basically have 3 options:
Use JSONP. This has limitations, including the fact that it only works for GET requests, and the server you are sending the request to has to support it.
Make a Cross Origin Resource Sharing (CORS) request. This also must be supported by the server you are sending the request to.
Set up a proxy on your own server. In this situation you set an endpoint on your site that simply relays requests. ie you request the information from your server, your server gets it from the other server and returns it to you.
For your situation, it the other server doesn't have support for other options, it seems like you will have to go with options 3.
I understand the way to make an ajax call in YUI 3 is using the IO utility.
I want to get the address of a location from Google's geocoding API.
<script type="text/javascript"><!--
YUI().use('io-base', function(Y) {
function complete(id, o) {
var data = o.responseText; // Response data.
alert(o.responseText);
};
Y.on('io:complete', complete, Y);
var request = Y.io("http://maps.googleapis.com/maps/api/geocode/json?language=en&sensor=false&latlng=12,34);
});
//-->
</script>
I get a reply with method OPTIONS and status code 405 Method Not Allowed.
I believe this is because of some "preflight" permission check. I do not receive the desired response. If I copy and paste the url into the browser, I see the json data.
I could post the ajax request to a php script on my own domain and get the json response with curl.
But why have this extra step if I could just get the data in javascript?
So what can I do to solve this? Is the IO utility not the right library to use?
You're making a cross-domain XHR request, and running into the "Same origin policy", a generic restriction in client-side JavaScript. See for example Why do I still receive 405 errors even though both URLs are from XXXX.com?
There are various ways to work around this problem:
1) Make a server-side request in PHP, as you suggest
2) Use the YUI jsonp module
3) Use the YUI YQL module, which proxies your request through Yahoo! servers and handles JSONP housekeeping for you
There are many other ways to tackle this problem, but those three should get you started.
Y.io has support for cross domain requests. See http://yuilibrary.com/yui/docs/io/#cross-domain-transactions
You need to properly config it with the "xdr" property, and load the "io-xdr" module, etc. This example uses it as well: http://yuilibrary.com/yui/docs/io/weather.html
I am able to execute a web service through the browser but when I try and execute it through xmlhttprequest in javascript I get this error: Origin [] is not allowed by Access-Control-Allow-Origin.
How can I call the webservice through javascript? I'd prefer not to use a framework and just use basic client-side javascript.
For reference this is an instance of the web service I'm trying to consume: http://musicbrainz.org/ws/1/track/?type=xml&query=track:alive
Thanks.
Not possible. You can't have an AJAX call to a different domain. It would need to be done by the server.
You cannot use XMLHttpRequest on a page hosted at one domain to retrieve information from another domain. The browser simply won't allow it.
One common workaround is quite reliable if you have some control over the resource you're retrieving. It's called "JSONP" and the technique is to simply append a <script> tag to the header (dynamically, using JavaScript). That script can of course be hosted on any domain, so there's no cross-site scripting restrictions. If the script were to consist simply of JSON data, it wouldn't do much good. But wrap that JSON data in a function call — a function you control on your side — and it works great.
someFunctionName( { ... } );
If the resource you're retrieving doesn't support JSONP, your only recourse is to write a script on your own server (hosted on the same domain as the page, of course) that retrieves the target data. You can then make a normal AJAX call to your own script.
XmlHttpRequest is for requests for the same domain - it is called "Same origin policy".
If you want to do cross-domain ajax request you have to use jsonp format.
I do not think that using plain JavaScript is good idea - much better solution
is ready-to-use framework e.g. jQuery or Mootools.
In jQuery you have got method $.getJSON to making simple JSON and JSONP requests.
More read about:
How exactly is the same-domain policy enforced?
http://api.jquery.com/jQuery.getJSON/
http://en.wikipedia.org/wiki/JSON#JSONP
NOT Possible, but you can create a proxy on your server, and access the data through the proxy:
Here is a proxy example in PHP:
proxy.php
<?php
//header('Content-type: text/xml');
$url = 'http://musicbrainz.org/ws/1/track/?type=xml&query=track:alivehttp://www.example.com/';
$xml = file_get_contents($url);
echo xml;
?>
You can now use proxy.php as your source url from javascript.
I know this is a long shot, but I figured I'd ask the question anyway.
I have an HTTPS page and am dynamically creating a form. I want to POST the form to an HTTP page. Is this possible without the browser popping up a warning? When I do this on IE8, I get the following message:
Do you want to view only the webpage content that was delivered securely?
Essentially, I'm asking about the inverse of question 1554237.
Sadly, I know of absolutely no way to not get warned when posting from HTTPS to HTTP. If you serve the form securely, the browser expects to submit the data securely as well. It would surprise the user if anything else was possible.
Nope, can't be done. Our good friend IE will always pop up that warning.
There is a way to do this if you write a back-end service of your own. So lets say you want to post an HTTP request to s1 using your front-end service fs1.
If you use Spring, you can use an ajax call from fs1 to a 'uri' that is recognized by your spring back-end, say bs1. Now, the service bs1 can make the call to the s1.
Pictorial representation here: http://i.stack.imgur.com/2lTxL.png
code:
$.ajax
({
type: "POST",
uri:/json/<methodName>
data: $('#Form').serialize(),
success: function(response)
{
//handle success here
},
error: function (errorResponse)
{
//handle failure here
}
})
You can solve this by either acting as a proxy for the form destination yourself (i.e. let the form submit to your server which in turn fires a normal HTTP request and returns the response), or to let access the page with the form by HTTP only.
If you don't need to actually redirect to the insecure page, you can provide a web service (authenticated) that fires off the request for you and returns the data.
For example:
From the authenticated page, you call doInsecure.action which you create as a web service over https. doInsecure.action then makes a manual POST request to the insecure page and outputs the response data.
You should be able to do this with the opensource project Forge, but it sounds like overkill. The Forge project provides a JavaScript interface (and XmlHttpRequest wrapper) that can do cross-domain requests. The underlying implementation uses Flash to enable cross-domain (including http <=> https) communication.
http://github.com/digitalbazaar/forge/blob/master/README
So you would load the Forge JavaScript and swf from your server over https and then do a Forge-based XmlHttpRequest over http to do the POST. This would save you from having to do any proxy work on the server, but again, it may be more work than just supporting the POST over https. Also, the assumption here is that there's nothing confidential in the form that is being posted.