Fragment of passive Scanning
0x00 Introduction
Distributed scanning has been written by many people, for example:
Sqli plug-in of burp
Matt's predecessor http://zone.wooyun.org/content/24172
Pig's predecessor's http://zone.wooyun.org/content/21289
Ver007 predecessor http://zone.wooyun.org/content/24333
0x_Jin predecessor's http://zone.wooyun.org/content/24341
I was upset about filling in a trap and thought about creating a wheel. I was busy for a few days and wrote a simple prototype.
Github: https://github.com/liuxigu/ScanSqlTestchromeExtensions
We would like to thank bstaint and sunshadow for their help.
Sqlmapapi was originally written to implement distributed injection, and added nodes to implement distributed scanning.
The first thought was to use the chrome plug-in for code injection.
Js is used to obtain the same domain url of tags. js is used to prevent anti-crawler measures from some websites. js will automatically complete the domain name if a href points to a relative link. chrome webRequest API OnBeforeRequest get the url to be requested
Suppose you get the url and feed it to sqlmapapi. Write the injected url into the text. The FileSystemObject gg of js is intended to implement file io using php...
Talk is cheap show me the code.
0x01 Chrome manifest. json
{ "name": "sqlInjectionTest", "version": "0.1", "description": "you know...", "manifest_version": 2, "content_scripts": [{ "matches":["*://*/*"], "js": ["inject.js"] }], "permissions": [ "*://*/*", "webRequest", "webRequestBlocking" ], "browser_action": { "default_icon": "icon.png" , "default_title": "scan url inject" } }0x02 Sqlmapapi. py code 1: Fixed Admin Id
After Sqlmapapi is started, it is like this:
Root @ kali :~ /Desktop/sqlmap # python sqlmapapi. py-s [22:02:17] [INFO] Running REST-JSON API server at '2017. 0.0.1: 8775 '.. [22:02:17] [INFO] Admin ID: 7c4be58c7aab5f38cb09eb534a41d86b [22:02:17] [DEBUG] IPC database:/tmp/sqlmapipc-5JVeNo [22:02:17] [DEBUG] REST-JSON API server connected to IPC database
AdminID changes every time, which makes Task Management inconvenient. Let's change the source code of sqlmap.
Go/sqlmap/lib/utils/api.pyServer Function
You can see the OS. urandom IN THE 644 rows and change it to a fixed string.
For example, I changedDataStore.admin_id = hexencode('wooyun')
Admin ID: 776f6f79756e
There is a simpler way
Return True
Ii. Automatic text writing after the sqlmap scan task ends
Determine whether the current task has been scanned and accessed http: // 127.0.0.1: 8775/admin/ss/list
{ "tasks": { "4db4e3bd4410efa9": "terminated" }, "tasks_num": 1, "success": true }
Terminated indicates that the task has been Terminated,
Http: // 127.0.0.1: 8775/scan/4db4e3bd4410efa9/data
{ "data": [], "success": true, "error": [] }
"Data" stores the payload used for sqlmapapi detection. If "data" is not empty, it indicates that the current task can be injected. sqlmapapi does not have its own callback method... Polling is a waste of overhead. Here I choose to modify the source code
Goscan_dataFunction, you can see that, if it can be injected, the data will be retrieved from the data table and writtenjson_data_messageThe table name is data. The code is flipped up and the Code for storing data into the database is located.
In the StdDbOut class, 230th rows are inserted before insert.
with open('/tmp/'+str(self.taskid)+'.txt','a+') as fileHandleTemp,/ closing(requests.get('http://127.0.0.1:8775/option/'+str(self.taskid)+'/list', stream=True)) as reqTemp: fileHandleTemp.write( json.loads(reqTemp.text)['options']['url']+'/n'+ json.loads(reqTemp.text)['options']['data']+'/n'+ json.loads(reqTemp.text)['options']['Cookie']+'/n'+ json.loads(reqTemp.text)['options']['Referer']+'/n' )
Remember to load three modules
import jsonimport requestsfrom contextlib import closing
The intention is to get the injected url and write it into the text. The source code does not find the place that inherits this class... Too lazy to find
Access http: // 127.0.0.1: 8775/option/id/list
Response:{ "options": { ...... "url": http://58.59.39.43:9080/wscgs/xwl.do?smid=02&bgid=01&bj=8 …… } "success":{ ... }
0x03 inject. js code 1.
Filter out javascript: pseudo protocol and href without SQL operations.
As shown in the following code:
if re.match('^(javascript|:;|#)',_url) or _url is None or re.match('.(jpg|png|bmp|mp3|wma|wmv|gz|zip|rar|iso|pdf|txt|db)$',_url):
Even like this:
filename=urlpath[i+1:len(urlpath)] print "Filename: ",filename res=filename.split('.') if(len(res)>1): extname=res[-1] ext=["css","js","jpg","jpeg","gif","png","bmp","html","htm","swf","ico","ttf","woff","svg","cur","woff2"] for blacklist in ext: if(extname==blacklist): return False
These two methods may cause meaningless overhead if such a url is: http: // xxx/aaa.
To determine whether a get injection test can be performed, you only need
Str. match (/[/?] /); If the page does not have the get parameter, null is returned.
Let's write:/http (s )? : // ([/W/W-] + //) + ([/w/W] + /?) + /;
In addition, with the same domain filtering, the value of the variable can be referenced with {} in the string without php in js. To splice the variable in the regular expression, the RegExp object must be used:
var urlLegalExpr="http(s)?:////"+document.domain+"([/////w//W]+//?)+";var objExpr=new RegExp(urlLegalExpr,"gi");
2.
Js is executed after http response. To perform post injection, it must be obtained before OnBeforeRequest. chrome provides related APIs. There is nothing to say about this. Check the code.
Inject. js code:
main();function main(){ var urlLegalExpr="http(s)?:////"+document.domain+"([/////w//W]+//?)+"; var objExpr=new RegExp(urlLegalExpr,"gi"); urlArray=document.getElementsByTagName('a'); for(i=0;i
if(objExpr.test(urlArray[i].href)){ sqlScanTest(urlArray[i].href); } }}function sqlScanTest(url,payload){ sqlmapIpPort="http://127.0.0.1:8775"; var payload=arguments[1] ||'{"url": "'+url+'","User-Agent":"wooyun"}'; Connection('GET',sqlmapIpPort+'/task/new','',function(callback){ var response=JSON.parse(callback); if(response.success){ Connection('POST',sqlmapIpPort+'/scan/'+response.taskid+'/start',payload,function(callback){ var responseTemp=JSON.parse(callback); if(!responseTemp.success){ alert('url send to sqlmapapi error'); } } ) } else{ alert('sqlmapapi create task error'); } } )}function Connection(Sendtype,url,content,callback){ if (window.XMLHttpRequest){ var xmlhttp=new XMLHttpRequest(); } else{ var xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function(){ if(xmlhttp.readyState==4&&xmlhttp.status==200) { callback(xmlhttp.responseText); } } xmlhttp.open(Sendtype,url,true); xmlhttp.setRequestHeader("Content-Type","application/json"); xmlhttp.send(content); } function judgeUrl(url){ var objExpr=new RegExp(/^http(s)?:////127/.0/.0/.1/); return objExpr.test(url);}var payload={};chrome.webRequest.onBeforeRequest.addListener( function(details){ if(details.method=="POST" && !judgeUrl(details.url)){ var saveParamTemp=""; for(var i in details.requestBody.formData){ saveParamTemp+="&"+i+"="+details.requestBody.formData[i][0]; } saveParamTemp=saveParamTemp.replace(/^&/,''); //console.log(saveParamTemp); payload["url"]=details.url; payload["data"]=saveParamTemp; } //console.log(details); }, {urls: [""]}, ["requestBody"]);chrome.webRequest.onBeforeSendHeaders.addListener( function(details) { if(details.method=="POST" && !judgeUrl(details.url)){ //var cookieTemp="",uaTemp="",refererTemp=""; for(var ecx=0;ecx
switch (details.requestHeaders[ecx].name){ case "Cookie": payload["Cookie"]=details.requestHeaders[ecx].value; break; case "User-Agent": payload["User-Agent"]=details.requestHeaders[ecx].value; break; case "Referer": payload["Referer"]=details.requestHeaders[ecx].value; break; default: break; } } sqlScanTest("test",JSON.stringify(payload)); return {requestHeaders: details.requestHeaders}; } }, {urls: [""]}, ["requestHeaders"]);
All options available for Sqlmap can be viewed in http: // ip: port/option/taskid/list. You can write the items used to payload. It is best to create a real-time refresh proxy, I wrote a python version when I was a crawler. If I had time, I would add it to inject in js. js.