Translation:Tianyi_TingVerification Comments:Newghost
Note * The author published this article earlier. Some methods may not be the best solution.But the attacks against such vulnerabilities are still visible, such as the early stages:QQMail email leakage vulnerability. Until now, you have opened an external link makeup in some mailboxes, and there are still security warnings.The following describes the attack principles and preventive methods.
Not long ago, I wrote an article titled a subtle JSON vulnerability, which mentioned that this vulnerability may cause leakage of sensitive information. Targeting the features of this vulnerability, the JavaScript array constructor is overwritten to steal (expose) JSON returned arrays. Currently, most browsers cannot prevent such attacks.
However, by talking to Scott Hanselman from Microsoft, I learned that another method may affect more browsers. At last week's Norwegian Developer Conference, I demonstrated the Json hijacking vulnerability.
Before I proceed, let me first talk about the potential impact of this vulnerability.
This vulnerability occurs when the JSON service is exposed and sensitive data is returned. The JSON array is returned and the GET request is responded; the browser that sends this request enables JavaScript and supports the _ defineSetter _ method.
If we do not use JSON to send sensitive data or only respond to packet requests, this vulnerability does not exist on our website.
I don't like to use flowcharts to show this process. I will try to describe it in charts. On the first page, we can see that the uninformed victim logs on to the vulnerability website, which returns an authentication cookie.
We may have received some spam emails with links. The sender claims that there is a funny video. These large volumes of spam are specially crafted.
But in fact, these links point to bad guys own websites. When we click the link, the next two steps will be quickly performed. First, our browser sends requests to these websites.
Second, those websites will respond to HTML containing JavaScript. These JavaScript will contain a script tag. When the browser detects the script flag, it sends a GET request for downloading the script to the websites with the cookie for authentication.
In this way, the bad guys disguise themselves as the victim's browser and use their identities to send a JSON request containing sensitive data. Then, load JSON into executable JavaScript, so that hackers can obtain the data.
For better understanding, we can look at the actual code of an attack. If the vulnerability website returns a JSON response containing sensitive data, it can be sent as follows:
[Authorize]publicJsonResultAdminBalances(){ varbalances=new[]{ new{Id=1,Balance=3.14}, new{Id=2,Balance=2.72}, new{Id=3,Balance=1.62} }; returnJson(balances);}
It should be noted that the above demonstration is not specifically for ASP. NET or ASP. net mvc. I just happened to use ASP. NET MVC to demonstrate this vulnerability.
If this is a HomeController method, we send a GET request to/Home/AdminBalances and return the following JSON text:
[{“Id”:1,”Balance”:3.14},{“Id”:2,”Balance”:2.72},{“Id”:3,”Balance”:1.62}]
Note that the Authorize attribute is used when I define this method to verify the identity of the requester. Therefore, an anonymous GET request will not obtain sensitive data.
Important: This is a JSON array. The text that contains the JSON array is a valid JavaScript script and can be executed. A script containing only JSON objects is not a valid JavaScript executable file.
For example, if we have a JavaScript document that contains the following JSON code:
{“Id”:1,”Balance”:3.14}
There is a script tag pointing to this document:
<script src=”http://example.com/SomeJson”></script>
In this way, we will get a JavaScript error in the HTML page. However, if there is an unfortunate coincidence that if we have a script tag that points to a document containing only one JSON array, this label will be mistaken for a valid JavaScript and the array will take effect.
Next let's take a look at the HTML pages on the servers of those with ulterior motives.
Note * here we can see that your data is returned using Json Object instead of Json Array,This vulnerability can be prevented to a certain extent.
What do you see? The hacker is changing the Object prototype. The special method _ defineSetter _ is used to overwrite the default behavior of the JSON Object ..
In this example, an anonymous function is called when a named ID can be set to any object at any time, this function will use the alert function to display the attribute value. Note that the script only sends the data back to the bad guys without sending sensitive data.
As mentioned earlier, the bad guy needs to enable us to access his malicious webpage shortly after logging on to the website with the vulnerability and the session is still valid. It is typical to launch phishing attacks through emails containing malicious website links.
If you still click the link to log on to the original website, the browser will load the script referenced in the script tag and send your authentication cookie to the website. Until we connect to the original website, we send a valid authentication request for JSON data, and will receive valid data in our browser response. These words may be familiar to me, because it is a real variant that forges cross-site requests. I have previously written this case.
Because _ defineSetter _ on IE8 is an invalid method, it is invisible on IE8. I have tried both Chrome and Firefox.
It is easy to avoid this vulnerability: Or never send a JSON array, or only access http post to obtain the required data. For example, in ASP. net mvc, you can use AcceptVerbsAttribute to implement:
[Authorize][AcceptVerbs(HttpVerbs.Post)]publicJsonResultAdminBalances(){ varbalances=new[]{ new{Id=1,Balance=3.14}, new{Id=2,Balance=2.72}, new{Id=3,Balance=1.62} }; returnJson(balances);}
One problem with this method is that many JS libraries such as jQuery send JSON requests in GET mode by default, rather than POST. For example, $. getJSON initiates a GET request by default. Therefore, for such JSON access, we need to be sure that we use the POST request initiated by the client library.
ASP. NET and wcf json server actually use the "d" attribute in the object and wrap their JSON. This is discussed in another article:
It seems strange that data must be obtained through these attributes, but this requires a client proxy to remove the "d" attribute so as not to affect the end user.
In ASP. net mvc, the vast majority of developers do not generate client proxies, but use jQuery and Other Similar libraries. This makes it awkward to use the "d" attribute.
Note * In fact, the MVC method is a bit complicated. here we can see that the JSON hijacking vulnerability is based on the execution of the JSON return object on the browser of the victim, in fact, Google uses a more intelligent method by adding the "endless loop" command to prevent hackers from running this script. Refer to this article:Why does Google's JSON Response Start With while (1?
How about checking the Header (Http-Header?
Some may have questions: "Why don't I use a special header to check the JSON service before responding to a GET request? Like X-Requested-With: XMLHttpRequest or Content-Type: application/json ". I think this may be a transition, because most client libraries send one or two headers, but the browser does not respond to the GET request of the script tag.
The problem is: in the past, users may send valid json get requests. In this case, this vulnerability may be hidden between normal requests of the user's browser. In this case, when the browser sends a GET request, the request may be cached in the buffer zone of the browser and the proxy server. We can try to set the No-Cache header. In this way, we trust the browser and all the proxy servers to correctly implement the high-speed Cache and trust users not to be accidentally overwritten.
Of course, if we use SSL to provide JSON text, this specific cache problem will be easily solved.
Note * here we can see that it is better not to cache your ajax requests. However, it seems that all js libraries do not enable cache by default.
Where is the real problem?
In an article published by Mozilla Developer Center, object and array initialization settings should not call the setters method when assigning values. I agree to this. Although some comments said: Maybe the browser really should not execute the script.
However, at the end of the day, assigning responsibilities does not make your website safer. These browser quirks will appear from time to time. As website developers, we need to solve these problems. Chrome2.0.172.31 and Firefox3.0.11 also have this weakness. IE8 does not have this problem because it does not support this method and I have not tried it in IE7 or IE6.
In my opinion, in the current client library, the default method for secure access to JSON should be POST, and we should choose GET instead of other methods. What do you think? How do you solve this problem on other platforms you know? I 'd like to hear your thoughts