Create a plug-in II that automatically detects whether XSS exists on the page

Source: Internet
Author: User

Create a plug-in II that automatically detects whether XSS exists on the page

Preface:

The changes in this version are a little larger than those in the previous version. First, the entire code architecture is modified, which is more intuitive and easy to modify and locate. In addition, in this version, I fixed two bugs in the previous version (which will be mentioned later) and added the pseudo static detection XSS (path and file at URL ).

0 × 01 website structure:

I changed xss.htmlto getxss.html. Added formxss.html to accept form xss (this function will be used in the next chapter ). Store the logs in the logs file. As follows:


If you modify the log file, you must modify the nginx configuration file. The nginx code after nginx configuration is as follows:

location /getXSS.html{    access_log E:/WWW/xss/logs/getXSS.log xss;}location /formXSS.html{    access_log E:/WWW/xss/logs/formXSS.log xss;}


The following ajax Code uses logs/xxx.html as the accepted address.

0 × 02 code architecture:

When writing, I want to make this plug-in more than just "website XSS Vulnerability Detection", and then add some other Vulnerability Detection scripts. In addition, the judgment is added so that the script can be run at the appropriate time. For example, if the current webpage URL has no parameters, the XSS Vulnerability Detection script of the URL parameter will not be run, it can also greatly improve the script running efficiency. So I wrote a few common variables out, and the function can be called directly without declaring them (the JavaScript variable declaration is upgraded), and then I used if to determine which scripts to use under the Declaration. Then, every function is encapsulated into a function.

The architecture is as follows:

Variable Declaration

Variable operations (before if, to prevent if from jumping directly to the function without running)

If (to which function)

Function

Variable declaration:

Var onlyString = 'woainixss'; // Unique Identifier var protocol = window. location. protocol; // The network protocol used by the website (http, https, etc.) var host = window. location. host; // The primary domain name of the website (*. com ,*. cn, for example, test.cn) var href = window. location. href; // The complete URL of the website (Protocol + domain name + parameter + anchor) var hostPath; // The string used to store the parameters removed from the website (Protocol + domain name + anchor) var urlPath; // an array used to store the URL path of a website (for example, test.cn/test/xss/123 urlPath = ['test', 'xss', '123'])


Variable operation:

If (href. indexOf ("? ")! = "-1") {// If the url exists? String (exist? Basically there is a parameter.) hostPath = href. slice (0, href. indexOf ("? "); // Remove the parameter, leaving only" protocol + domain name + anchor "} else {hostPath = href; // does not exist? Assign the complete url to the hostPath .} UrlPath = hostPath. split ("/"). splice (3); // use the separator "/" to split the path into arrays.


Because there will be two // After the protocol, and one/after the domain name such as. com will be discarded. Only the path is left. The feedback is as follows:

Because the excess "/" exists, three more arrays will be added and removed using splice (3.
If judgment:

If (location. search! = "") {// When the parameter is not blank, jump to parameter_Xss ();} if (href. split ("/") [3] In the parameter_Xss function. = "") {// When there is a string after the third/in the complete URL, it will jump to the pseudo dostatic_xss ();} if ($ ("form") in the pseudo dostatic_xss function "). length> 0) {// when a form exists on the page, it will jump to the form_Xss ();}


Function:
Function parameter_Xss () {...} // URL parameter detection XSS
Function pseudo static_xss () {...} // pseudo static detection XSS
Function form_Xss () {...} // form detection XSS

0 × 03: URL parameter detection xss bug modification:

The first bug I found during the test was my negligence. When debugging code, I did not consider the various possible environments. The following is the problem code:

var onlyString = 'woainixss';var protocol = window.location.protocol;var hrefHost = window.location.host;var parameter = location.search.substring(1).split("&");var url = protocol + "//" + hrefHost + "/?";for(var i = 0;i  parameter.length;i++){    url += parameter[i].split("=")[0] + "=" + onlyString + parameter[i].split("=")[1] + '"&';}

What is the problem with this code? This occurs when the url variable is assigned a value. I did not consider the path issue. Add a parameter to the domain name with a unique identifier. For example, the test webpage is test.cn/test/xss/123? A = 1 & B = 2, but the url is test.cn /? A = 1 & B = 2. Ignore the path directly. As a result, the webpage to be detected cannot be correctly processed.

The modified code is as follows:
Var url = protocol + "//" + host + "/" + urlPath. join ("/") + "? ";
Do not worry about errors caused by the absence of paths. If the path does not exist, urlPath. join ("/") returns an empty string.

The second is the bug I mentioned in Section 1: When there are two parameters on the website, the code automatically adds a "unique identifier" to the value of each parameter, and then sends the data to ajax. If the first parameter exists in XSS, but the second parameter cannot be changed, otherwise the XSS cannot be triggered. This problem cannot be solved in the first version, and it can be solved perfectly in this version. The code I have rewritten is as follows:
Var I; // ivar parameter = location in the for loop. search. substring (1 ). split ("&"); // splits the URL character into a string var url = protocol + "//" + host + "/" + urlPath. join ("/") + "? "; // Concatenate new URL characters. (Example: http://test.cn/test/xss/123 ?) For (I = 0; I parameter. length; I ++) {// for Loop. The number of parameters is the number of times that var parameterData = parameter [I]; parameter [I] = parameter [I]. split ("=") [0] + "=" + parameter [I]. split ("=") [1] + onlyString; $. ajax ({url: url + parameter. join ("&"), type: 'get', ype: 'text', async: false ,}). done (function (data) {if (data. indexOf (parameter [I]. split ("=") [1])! = "-1") {$ ("body "). append ("+ host +" & $ xss = $ "+ parameter [I]. split ("=") [0] + "& $ url = $" + window. location. href + "& $ rand = $" + Date. parse (new Date () + "'style = 'display: none; '>") ;}}) parameter [I] = parameterData ;}

The following describes the meaning of the Code in the for statement.
Var parameterData = parameter [I];

Parameter [I] represents the character of the current parameter,


Because the following operation code changes the current parameter [I] value, and we need to change it back at last, we need to assign a value. At last, we need to input
Parameter [I] = parameterData;

This can be done in turn.

Parameter [I] = parameter [I]. split ("=") [0] + "=" + parameter [I]. split ("=") [1] + onlyString;
To redefine the current parameter, parameter [I]. split ("=") [0] is the string of the obtained parameter, as follows:


Parameter [I]. split ("=") [1] is used to obtain the value of the current parameter, as follows:


OnlyString is the "unique identifier". Except ajax, the remaining result is as follows:


The code for splicing URL parameters is put in ajax, that is, url + parameter. join ("&"). The result is as follows:


First, the first parameter is spliced with the "unique identifier" and then restored to its original state. Then splice the second parameter with the "unique identifier. In turn.

Compared with the last modified url, the Ajax code is url + parameter. join ("&"). Then, add async: false to make ajax synchronous. If it is asynchronous, it will only take the last result of the for loop, and change it to synchronous, so that ajax can be recycled normally. Nothing else.

0 × 04 pseudo static detection XSS:

At the beginning, I thought for a long time, "How can I determine whether a page is pseudo-static?". I also said on the Internet that I used document. lastModifie to view the last update time of the Web page. If the web page is static, the date time is different from the system time on our computer. If the webpage uses pseudo-static data, the date and time are exactly the same as the system time on our computer. However, I need to send two ajax requests to determine whether the time is different. It is a waste of efficiency. Later I Thought About It. Generally, pseudo-static rules set parameters as paths, as shown below:
Test.cn/test.php? Id = xss/123

After modification:
Test.cn/test/xss/123.

The following is the rule code for nginx Configuration:
Location/test {
Rewrite ^ (/. +) // test. php? Id = $1 last;
}

Then I only need to check the path and file of the current webpage. So when the if statement is made, I write if (href. split ("/") [3]! = ""){...} To determine whether the current webpage has a path.
Var fileURL; // variable that stores the file name string
Var fileUrlXss; // the character that Concatenates the object with a unique identifier
Var url; // url sent by ajax
Var xss = ""; // The xss parameter exists.

First, you need to check whether a file exists in the previous URL or xxx.html or xxx. php. If it exists, concatenate xxx with the "unique identifier" and send it again. Just a parameter, like a page of freebuf: http://www.freebuf.com/tools/74654.html tools, 74654 is actually a parameter. The toolsdirectory and the 74654.html file exist.

The following describes how to modify and discover whether XSS is stored when files exist.

We first determine whether a file exists and use
If (urlPath [urlPath. length-1]. indexOf (".")! = "-1 ")
That's all.

UrlPath is the data cut by the separator "/", and urlPath. length-1 is the last array. IndexOf (".") is to judge whether the last array has a "." string, because if it is a file, there must be. The output result is as follows:


Then when if is true, that is, when a file exists, we need to splice and send data.

FileURL = urlPath. pop (); // Delete and obtain the last array, and assign the value to the fileURL variable
(In fact, it is the file string, such as xxx.html and xxx. php ).

The following is a patchwork string:
FileUrlXss = fileURL. split (".") [0] + onlyString + "." + fileURL. split (".") [1]
FileURL. split (".") [0] is to get the file name (excluding the suffix)

OnlyString is a "unique string"

FileURL. split (".") [1] is the suffix string for obtaining files.

The patchwork result is:


Then, send the data to ajax.
The sent url is: protocol + "//" + host + "/" + urlPath. join ("/") + "/" + fileUrlXss

Protocol + domain name + path + file. The complete code is as follows:
$.ajax({    url: protocol + "//" + host + "/" + urlPath.join("/") + "/" + fileUrlXss,    type: 'get',    dataType: 'text',    async:false,}).done(function(data) {    if(data.indexOf(fileUrlXss) != "-1"){        xss += fileURL + "|";    }})
. Done (function (data ){...}) It is the code executed when ajax is successfully sent and the target website returns a 200 status code. Data is the HTML source code of the webpage after the Data is sent. Then match the if command to determine whether the source code of the webpage after the data is sent has the result of splicing the file name with the "unique string. If yes, add the file name string to the end of xss. The result is as follows:


Only + = is used to add the following path to the xss variable.

Let's talk about the code in else.
FileURL = "";
If (urlPath [urlPath. length-1] = ""){
UrlPath. pop ();
}

First, empty the file variables. If the subsequent strings are concatenated, they will only be spliced with null characters, without any impact. The code in if removes the "/" string.

Because in the previous "variable operations", there is such a piece of code:
UrlPath = hostPath. split ("/"). splice (3 );

The URL is split into an array by "/". However, there is a BUG here. In pseudo-static or normal links, there is often such a URL: test.cn/test/xss/123/, there is no file, and there is only a token. The result is an extra empty array, as shown below:

 



We need to remove the last empty array, but some URLs are test.cn/test/xss/123. this urlis not found in the bug, as shown below:


Therefore, we need an if judgment to determine whether the last array is null. If it is null, the last data is removed, that is, the pop function is used. The complete code is:
UrlPath. pop ();

OK. The file XSS detection is based on OK. The following describes how to check the URL path.
For (var I = 0; I urlPath. length; I ++ ){...}

In this case, urlPath stores the URL path array of the current webpage, and its length determines the number of paths. Here, the number of cycles is the same as the number of paths.

Then splice the current array value with the "unique string.
UrlPath [I] + = onlyString;

After splicing, splice with other variables and strings:
Url = protocol + "//" + host + "/" + urlPath. join ("/") + "/" + fileURL;


The following code can be used to solve the irreparable problem:
UrlPath [I] = urlPath [I]. substring (0, urlPath [I]. length-11 );

Because the woainixss character is 11 characters and is behind the original string, we only need to remove the last 11 characters of the string to restore.


OK. Now the ajax request is sent between them.

Because it is in the for loop, we need to use Asynchronous execution. That is, async: false.

Then, use if to determine whether the XSS vulnerability exists:
If (data. indexOf (urlPath [I])! = "-1 "){
Xss + = urlPath [I]. substring (0, urlPath [I]. length-11) + "| ";
}

As mentioned above, urlPath [I]. substring (0, urlPath [I]. length-11) is the string that removes the "unique identifier" and adds the existing vulnerability to the end of the xss variable. At this time, the last character must be |, we will remove it below.
After a For loop is completed, we use if to determine whether XSS exists outside the for loop.
If (xss = ""){
Return false;
} Else {....}

If xss is empty (XSS vulnerability does not exist), false is returned to jump out of the function. The code in else is the operation code when XSS exists. First remove the last string |.
Xss = xss. substring (0, xss. length-1 );

After removing the string, it is sent to our server.
$ ("Body"). append ("src = 'HTTP: // xss.cn/getXSS.html? Host = $ "+ host +" & $ xss = $ "+ xss +" & $ url = $ "+ window. location. href + "& $ rand = $" + Date. parse (new Date () + "'style = 'display: none; '> ");

This code is the same as the previous "URL parameter detection XSS" code. You don't need to modify it. Of course, if you don't want to send it, you can use alert to pop up the result. Alert (xss ).

The complete code is as follows:
Function pseudo dostatic_xss () {// pseudo static detection XSS var fileURL; var fileUrlXss; var url; var xss = ""; if (urlPath [urlPath. length-1]. indexOf (". ")! = "-1") {fileURL = urlPath. pop (); fileUrlXss = fileURL. split (". ") [0] + onlyString + ". "+ fileURL. split (". ") [1] $. ajax ({url: protocol + "//" + host + "/" + urlPath. join ("/") + "/" + fileUrlXss, type: 'get', dataType: 'text', async: false ,}). done (function (data) {if (data. indexOf (fileUrlXss )! = "-1") {xss + = fileURL + "|" ;}})} else {fileURL = ""; console. log (urlPath) if (urlPath [urlPath. length-1] = "") {urlPath. pop () ;}for (var I = 0; I urlPath. length; I ++) {urlPath [I] + = onlyString; url = protocol + "//" + host + "/" + urlPath. join ("/") + "/" + fileURL; $. ajax ({url: url, type: 'post', dataType: 'text', async: false ,}). done (function (data) {if (data. indexOf (urlPath [I])! = "-1") {xss + = urlPath [I]. substring (0, urlPath [I]. length-11) + "|" ;}}) urlPath [I] = urlPath [I]. substring (0, urlPath [I]. length-11);} if (xss = "") {return false;} else {xss = xss. substring (0, xss. length-1); $ ("body "). append ("+ host +" & $ xss = $ "+ xss +" & $ url = $ "+ window. location. href + "& $ rand = $" + Date. parse (new Date () + "'style = 'display: none; '> ");}}

End:

Form XSS query will be placed in the next chapter, because this function code is more complex than the total code of the previous two functions, the "closure" and "filter function" in JavaScript are used, and a for loop is added in the for loop. xss.cn (xss result feedback webpage) needs to be rewritten ). This feature is worth opening a chapter.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.