高效率開發Web安全掃描器之路(一)

2022-11-30 12:00:39

一、背景

經常看到一些SRC和CNVD上厲害的大佬提交了很多的漏洞,一直好奇它們怎麼能挖到這麼多漏洞,開始還以為它們不上班除了睡覺就挖漏洞,後來有機會認識了一些大佬,發現它們大部分漏洞其實是通過工具挖掘的,比如說下面是CNVD上面的白帽子大佬

我想成為大佬要怎麼做

我一直覺得自己是一個有夢想的人,我也想有一天自己的ID能出現在排行榜中,於是我憑藉著自己那一點開發知識,認真研究了一下市面上的安全工具,以及怎麼開發安全工具。

安全工具分析

經過我得研究發現市面上的安全工具其實只有兩類,一類是面向某個漏洞的工具比如SQLMap,另外一個一類是綜合掃描工具,比如AWVS;

作為一個只想挖漏洞的我,我更偏向於綜合型的掃描器開發,可是綜合型的掃描器開發難度真的很大,要清晰地瞭解各種漏洞的原理,而且還需要把他們使用程式碼去實現,如果是我一個人從頭開發我壓根做不到啊。

但我並不打算放棄,我準備集結天下之利器,為我掃描器所用;理想是有了,但現實是我要怎麼實現,這可真實苦惱了我。

二、 要做的東西

我想要做的掃描器核心目的就是要使用簡單,另外就是我可以隨心所欲的修改;我希望是我只要給他一個URL地址,它就可以幫我掃描網站的漏洞,以及這個主機本身的漏洞

細緻的拆解了一下,我覺得最需要的功能有這幾個

  1. 能自動收集URL地址,爬蟲收集和爆破收集
  2. 能從URL中提取主機IP
  3. 能快速檢測常見的熱門POC
  4. 能自動識別網站的指紋資訊
  5. 能對IP進行埠快速掃描
  6. 能對埠的banner識別出服務
  7. 能檢測出SQL隱碼攻擊漏洞
  8. 能檢測出反射性XSS漏洞
  9. 能夠通過指紋資訊,使用對應的POC工具
  10. 能夠快速擴充套件功能,且不影響整體邏輯

第一版本差不多就是這些功能吧,功能雖然不算多,但如果完全從頭開始實現開發時間可不少。

三、思路分析

為了達到高效率的同時又能自主可控,我決定做一個有水平的縫合俠,簡單理解就是我要把很多工具巧妙的融入到我開發的工具來,這裡需要考慮的第一個問題是每個工具的使用方法、輸入的引數、輸出的結果都是不一樣的,工具A的結果工具B不一定認識。

要解決這個問題,說簡單也簡單說難也難,總之我是摸著石頭過河成功了;原理是自己給每個工具做一個殼,外部要呼叫工具A需要先呼叫工具A的殼,然後才會傳到工具A,當工具A返回了結果,工具A的殼也會最先拿到,然後將結果解析出來並按照統一的格式輸出就可以了。

通過這個簡單的辦法,我相當於把其他的安全工具變成了我得一個函數,我需要的時候呼叫這個函數就可以了。

按照我前面提到的需求,我梳理了一下要試用的工具有這幾個:

序號

序號 需求 工具
1. 爬去URL的有 RAD
2. 爆破URL的有 DIRMAP
3. 提取主機IP 正則
4. 快速檢測熱門POC xray
5. 識別網站的指紋 dismap
6. 對IP埠快速掃描 masscan
7. 能對埠的banner識別出服務 nmap
8. 能檢測出SQL隱碼攻擊漏洞 sqlmap
9. 能檢測出反射性XSS漏洞 xsser

這些工具都是比較常見的工具,我第一步需要對他們的使用方法熟悉,以xray工具為例

xray的使用命令如下所示

./xray_linux_amd64 webscan --url "http://192.168.1.100/" --json-output /tmp/11.json

當xray執行完畢之後,他會將結果輸出到指定位置,但是資料格式並不是我所期望的,我需要將它的格式讀入,然後再轉換成我所需要的格式。

這裡我用PHP寫了一個簡單的指令碼,他做了這幾件事情:

  1. 定義了引數來源位置和結果輸出位置
  2. 獲取引數中的URL,並執行xray工具
  3. 獲取xray的執行結果,並解析成自定義格式
  4. 將最終的結果寫入到輸出位置

程式碼範例如下所示

<?php
//獲取輸入的引數
$inputFile = "/data/share/input_".getenv("xflow_node_id").".json";
$outputFile = "/data/share/output_".getenv("xflow_node_id").".json";

//沒有input,直接返回
if (!file_exists($inputFile)) {
    var_dump($outputFile, json_encode(['code' => 0, 'msg' => "{$inputFile}檔案不存在", 'data' => []], JSON_UNESCAPED_UNICODE));
    return 0;
}
//讀取上游資料
$inputData = json_decode(file_get_contents($inputFile), true);

$url = $inputData['url'];
$data = execTool($url);

//將結果寫入到指定位置,供蜻蜓平臺匯入資料
file_put_contents($outputFile, json_encode($data, JSON_UNESCAPED_UNICODE));


//將工具執行
function execTool($url)
{

    $hash = md5($url);
    $resultPath = "/tmp/{$hash}/tool.json";
    //清理之上一輪的結果
    if (file_exists($resultPath)) unlink($resultPath);
    //建立資料夾
    if (!file_exists(dirname($resultPath))) {
        mkdir(dirname($resultPath), 0777, true);
    }

    $result = [];

    $toolPath = "/data/tools/xray";
    if (!file_exists($toolPath)) die("xray 工具目錄不存在:{$toolPath}");

    $path = "cd $toolPath && ";
    // 通過系統命令執行工具
    $cmd = "{$path} ./xray_linux_amd64 webscan --url \"{$url}\" --json-output {$resultPath}";
    echo $cmd;
    exec($cmd, $result);

    $toolResult = file_exists($resultPath) ? file_get_contents($resultPath) : '[]';
    $toolResult = json_decode($toolResult, true);
    print_r($toolResult);
    return $toolResult;
}

再來sqlmap封裝的例子,首先需要知道sqlmap的使用的方法,如下所示

sqlmap -u "http://192.168.1.100/index.php?id=1"  --batch  --random-agent 

當sqlmap執行完畢之後,我需要知道他的執行結果在什麼位置,並將結果解析出來,按照規範化的格式輸出到指定地址。

這裡我同樣用PHP寫了一個指令碼,做了這幾件事情:

  1. 定義了引數來源位置和結果輸出位置
  2. 獲取引數中的URL,並執行sqlmap工具
  3. 獲取sqlmap的執行結果,並解析成自定義格式
  4. 將最終的結果寫入到輸出位置
<?php
//獲取輸入的引數
$inputFile = "/data/share/input_".getenv("xflow_node_id").".json";
$outputFile = "/data/share/output_".getenv("xflow_node_id").".json";

//沒有input,直接返回
if (!file_exists($inputFile)) {
    file_put_contents($outputFile, json_encode([]));
    return 0;
}
//讀取上游資料
$list = json_decode(file_get_contents($inputFile), true);
print_r($inputFile);
print_r($list);
$data = [];
//處理資料
foreach ($list as $val) {
    $url = $val['url'];
    $toolPath = "/data/tools/sqlmap/";

    print_r("開始掃描URL:{$url}".PHP_EOL);
    execTool($url, $toolPath);

    //錄入檢測結果
    $tempList = writeData($toolPath, $url);
    print_r("掃描URL:{$url}完成".PHP_EOL);
    print_r($tempList);
    $data = array_merge($data, $tempList);
}

print_r($data);
//將結果寫入到指定位置,供蜻蜓平臺匯入資料
file_put_contents($outputFile, json_encode($data, JSON_UNESCAPED_UNICODE));


function writeData($toolPath, $url)
{

    $arr = parse_url($url);
    $file_path = $toolPath . 'result/';
    $host = $arr['host'];
    $outdir = $file_path . "{$host}/";
    $outfilename = "{$outdir}/log";

    //sqlmap輸出異常
    if (!is_dir($outdir) or !file_exists($outfilename) or !filesize($outfilename)) {
        print_r("sqlmap沒有找到注入點: $url");
        return [];
    }
    $ddd = file_get_contents($outfilename);
    print_r($ddd);

    exec("rm -rf $outdir");

    return [["raw" => $ddd]];
}

function execTool($v, $toolPath)
{

    $arr = parse_url($v);
    $blackExt = ['.js', '.css', '.json', '.png', '.jpg', '.jpeg', '.gif', '.mp3', '.mp4'];
    //沒有可以注入的引數
    if (!isset($arr['query']) or (strpos($arr['query'], '=') === false)) {
        print_r(["URL地址不存在可以注入的引數".PHP_EOL, $v]);
        return false;
    }
    $file_path = $toolPath . 'result/';
    $cmd = "cd {$toolPath}  && python3 ./sqlmap.py -u '{$v}' --batch  --random-agent --output-dir={$file_path}";
    exec($cmd);
    return true;
}



通過前面xray和sqlmap兩個工具封裝的例子,你回發現其實每個工具封裝的流程都差不多,差一點只是程式的輸出結果解析而已,所以到現在位置我解決了掃描器的能力問題。

四、動手實踐

現在只需要我把幾個功能連線起來就行了,這裡需要考慮一個新的問題;sqlmap所需要的引數確是具體的多個URL地址,也就是說在呼叫sqlmap之前,我需要把URL都收集好再呼叫sqlmap,這裡就有資料依賴問題。

這個問題也好辦,我們需要準備三張表: 目標表、功能依賴表、資料存放表。

目標表

ID URL create_time

功能表

ID tool_name pre_tool_name create_time

資料表

ID tool_name url result create_time

我們可以首先從目標表中獲取一個要掃描的目標,然後讀取所有的功能,for迴圈功能表,只需判斷當前有沒有依賴問題,或者依賴問題已經解決,那麼就可以得到所需的依賴資料,直接執行功能即可。

執行完成結果可以在結果頁面看見,這裡是我的執行結果。

虛擬碼如下所示:

<?php

$id = getTarget();
$toolLst = getToolList();

foreach($toolList as $val){
    //判斷當前工具上級依賴為空或者上級工具已執行 
    if($val['pre_tool_name'] == ''   or  上級工具已經執行){
        //開始使用工具對URL掃描
        scanUrl();
        //儲存結果
        svaeResult();
        
    } else(){
        //上級工具還沒執行完成,先跳過
        continue;
    }
}

這是我寫好的指令碼,大家可以簡單改改應用,目前我寫的指令碼已經整合到了蜻蜓安全平臺裡面,你可以一鍵複製使用

http://qingting.starcross.cn/scenario/detail?id=1931

目前我已經整合了46常見的款工具,放在GitHub中開源,地址:https://github.com/StarCrossPortal/QingTing


作者:湯青松
日期:2022-11-29
微信:songboy8888