<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/tips/12681

            0x00 簡介


            分布式掃描好多人都寫過,例如:

            burp的sqli插件

            Matt前輩的http://zone.wooyun.org/content/24172

            豬豬俠前輩的http://zone.wooyun.org/content/21289

            Ver007前輩的http://zone.wooyun.org/content/24333

            0x_Jin前輩的http://zone.wooyun.org/content/24341

            填上個坑填的心煩,想著也造個輪子,忙活了幾天,寫了一個簡單的雛形

            Github: https://github.com/liuxigu/ScanSqlTestchromeExtensions

            在此感謝bstaint、sunshadow的幫助

            Sqlmapapi本來就是為了實現分布式注入寫的,在被動掃描的基礎上 加節點就實現分布式了

            最初想的是用chrome插件來實現代碼注入

            1. 用js來獲取<a>標簽的同域url,用js是防止一些站的反爬蟲措施,還有對于a href指向相對鏈接的的情況,用js會自動補全域名.
            2. Chrome webRequest API OnBeforeRequest獲取即將請求的url

            設想獲取url后 喂給sqlmapapi, 將能注入的url寫入到文本里,js 的 FileSystemObject gg.. 本來是準備用php實現文件io的…

            talk is cheap show me the code.

            0x01 Chrome manifest.json


            #!js
            {  
              "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


            一:固定Admin Id

            Sqlmapapi啟動后 是這樣子:

            #!bash
            [email protected]:~/桌面/sqlmap# python sqlmapapi.py -s
            [22:02:17] [INFO] Running REST-JSON API server at '127.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每次都會變,這樣導致任務管理不方便,我們更改一下sqlmap的源碼

            定位到/sqlmap/lib/utils/api.py 的server函數

            p1

            看到644行的os.urandom,直接改成一個固定字符串就行了

            例如 我改成了DataStore.admin_id = hexencode('wooyun')

            以后就固定是Admin ID: 776f6f79756e

            還有個更簡單的辦法

            p2

            p3

            return True

            二:sqlmap掃描任務結束自動寫入文本

            判斷當前任務是否掃描完成 訪問http://127.0.0.1:8775/admin/ss/list

            #!python
            {
                "tasks": {
                    "4db4e3bd4410efa9": "terminated"
                }, 
                "tasks_num": 1, 
                "success": true
            }
            

            Terminated代表任務已終止,

            http://127.0.0.1:8775/scan/4db4e3bd4410efa9/data

            #!python
            {
                "data": [], 
                "success": true, 
                "error": []
            }
            

            “data”存放了sqlmapapi檢測時用的payload, “data”非空就代表當前任務是可注入的,sqlmapapi并沒有自帶回調方式…輪詢浪費開銷,這里我選擇修改源碼

            p4

            定位到scan_data函數 ,可以看到,假如可注入,就會從data表檢索數據并寫入到json_data_message,表名為data, 代碼向上翻,定位到將數據入庫的代碼

            在StdDbOut類里,第230行,在insert前 插入

            #!python
            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'
                                        )
            

            記得加載三個模塊

            #!python
            import json
            import requests
            from contextlib import closing
            

            本意是獲取能注入的url寫入到文本里,在源碼里沒找到繼承這個類的地方…懶得去找了

            訪問http://127.0.0.1:8775/option/id/list

            #!python
            Response:
            {
                "options": {
                    ......
                    "url": http://58.59.39.43:9080/wscgs/xwl.do?smid=02&bgid=01&bj=8
                    ……
                    }
                "success":{
                    ...
                }
            

            p5

            0x03 inject.js code


            1.

            那么要過濾掉javascript::偽協議和無sql操作的href

            看到有這樣寫的:

            #!js
            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):
            

            甚至這樣的:

            #!js
            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
            

            這兩種方式假如遇到這樣的url: http://xxx/aaa/ ,就會造成無意義的開銷.

            判斷是否可以進行get注入測試,其實只需要

            str.match(/[\?]/); 無get參數的頁面會返回null

            我們這樣寫: /http(s)?:\/\/ ([\w\W-]+\/)+ ([\w\W]+\?)+/;

            再加上同域過濾,js中沒有php那樣可以在字符串中用{}引用變量的值,要在正則中拼接變量需要用RegExp對象:

            #!js
            var urlLegalExpr="http(s)?:\/\/"+document.domain+"([\\/\\w\\W]+\\?)+";
            var objExpr=new RegExp(urlLegalExpr,"gi");
            

            2.

            Js是在http response后執行的,要進行post注入,必須在OnBeforeRequest之前獲取,chrome提供了相關的api,這個沒什么可說的 ,看代碼吧

            inject.js code:

            #!js
            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<urlArray.length;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: ["<all_urls>"]},
                ["requestBody"]);
            
            
            chrome.webRequest.onBeforeSendHeaders.addListener(
                function(details) {
                    if(details.method=="POST" && !judgeUrl(details.url)){
                        //var cookieTemp="",uaTemp="",refererTemp="";
            
                        for(var ecx=0;ecx<details.requestHeaders.length;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: ["<all_urls>"]},
                ["requestHeaders"]);
            

            Sqlmap能用的選項都可以在http://ip:port/option/taskid/list里查看,用到哪項寫到payload里就行了,最好是做成實時刷新代理,之前寫過爬蟲的時候寫過一個python版的,有空的話會改成js加入到inject.js里.

            p6

            0x04 參考文獻



            p7

            馬上2016了,希望在年前把上個坑填完

            也祝各位心想事成

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线