W13Scan 漏洞掃描器之XSS外掛模組編寫示例

tdaxia發表於2020-12-08

一、背景

上週將W13Scan目錄結構整理了一番,覺得要深入研究還得從程式碼層,於是嘗試編寫一下外掛;框架本身已經整合了XSS掃描外掛;

本篇文章的XSS外掛的編寫單純是為了學習這個框架,所以只支援GET型,瞭解外掛的編寫方法和原理即可。

W13scan 是基於Python3的一款開源的Web漏洞發現工具,它支援主動掃描模式和被動掃描模式,能執行在Windows、Linux、Mac上。

二、框架結構

在編寫外掛之前,我們需要對框架本身的目錄結構有一定了解,由於W13Scan本身的文件不是太詳細,我自己整理了一下,目錄結構圖下所示

├── api     通過API呼叫啟動掃描
├── certs   HTTPS證照存放目錄
├── data    html輸出模板存放目錄
├── fingprints  指紋資料
│         ├── framework     框架
│         ├── os            作業系統
│         ├── programing    
│         └── webserver     web服務
├── lib     框架核心目錄
│         ├── api
│         ├── controller
│         ├── core
│         ├── helper
│         ├── parse
│         ├── proxy
│         └── reverse
├── output      掃描結果輸出目錄
├── scanners    掃描器外掛
│         ├── PerFile       針對每個檔案,包括引數啥的
│         ├── PerFolder     針對url的目錄,會分隔目錄分別訪問
│         ├── PerServer     對每個domain的
├── thirdpart
│         ├── requests
└── w13scan.py  啟動入口

在上方目錄結構中,我們看到外掛都放在scanners目錄中,入口檔案則為w13scan.py檔案,因此這兩個位置就是我們需要重點所關注的;現在我們需要去分析框架的執行流程。

三、執行流程

使用pycharm編輯器開啟檔案 w13scan.py,可以看到入口檔案中的如下程式碼

def main():
    # 檢查版本資訊
    version_check()

    # 獲取絕對路徑
    root = modulePath()
    # 解析命令列引數
    cmdline = cmd_line_parser()
    # 初始化執行
    init(root, cmdline)

在上方程式碼中可以看到執行了初始化init(root,cmdline)方法,按住ctrl然後用滑鼠點選跳轉到方法詳情,編輯器自動開啟了檔案 lib/core/option.py,可以看到初始化的具體流程

def init(root, cmdline):
    cinit(autoreset=True)
    setPaths(root)
    # 指紋資訊
    banner()
    # 從config.py讀取配置資訊
    _init_conf()
    # 從cmdline讀取配置
    _merge_options(cmdline)
    # 設定埠資訊
    _set_conf()
    initKb()
    # 載入外掛
    initPlugins()
    # 輸出配置資訊
    _init_stdout()
    patch_all()

在上方程式碼中可以看到,裡面有一個initPlugins()方法,同樣按住ctrl然後點選方法名字,編輯器會自動開啟檔案 lib/core/option.py,可以看到外掛初始化的整個過程

def initPlugins():
    # 載入檢測外掛
    for root, dirs, files in os.walk(path.scanners):
        # 獲取外掛下的檔案列表
        files = filter(lambda x: not x.startswith("__") and x.endswith(".py"), files)
        # 對每一個檔案進行處理
        for _ in files:
            # 獲取檔名
            q = os.path.splitext(_)[0]
            # 判斷外掛白名單
            if conf.able and q not in conf.able and q != 'loader':
                continue
            # 判斷外掛黑名單
            if conf.disable and q in conf.disable:
                continue
            # 檔案絕對路徑
            filename = os.path.join(root, _)
            # 載入該檔案
            mod = load_file_to_module(filename)

在上方程式碼中可以看到初始化外掛,其實就是掃描了外掛目錄的檔案列表,然後挨個載入檔案。

四、分析除錯

為了證實這個猜想,我在遍歷的位置進行了程式碼除錯,加了print()方法,來驗證我的猜想,程式碼如下所示

            # 獲取檔名
            q = os.path.splitext(_)[0]
            print(q)
            print("\n")
            # 判斷外掛白名單
            if conf.able and q not in conf.able and q != 'loader':
                continue

找了一個靶場系統,然後使用w13scan的掃描命令執行,執行命令如下所示

python  w13scan.py  -u "http://192.168.152.135:8888/home/index.php?m=tiezi&a=index&bk=6"

命令執行,在控制檯看到如下資訊

(w13scan) D:\mycode\tools\w13scan\W13SCAN>python  w13scan.py  -u "http://192.168.152.135:8888/home/index.php?m=tiezi&a=index&bk=6"
 ________________
< w13scan v2.1.0 >
 ----------------
     \
      \
        ,__, |    |
        (oo)\|    |___
        (__)\|    |   )\_
             |    |_w |  \
             |    |  ||   *
             Cower....
loader
analyze_parameter
backup_file
....外掛列表,省略....
net_xss
swf_files
[11:23:49] [INFO] Load scanner plugins:29

在上方的資訊中,看到scanners目錄下的檔案列表,所以驗證了我的猜想;

接下來我就可以正式編寫外掛了,為了防止編寫過程中對外掛目錄造成損壞,我將scanners目錄複製了一份,如下圖所示


在上圖中,我將scannsers目錄複製到當前目錄的scannsers目錄,如果編寫過程中需要參考或者還原直接拷貝過來即可

接著我回到scanners目錄,在目錄裡面有29個外掛,除錯的時候不是太方便,我先將其他外掛都刪除,為了參考外掛怎麼編寫的,我留下一個,如下圖所示

在上圖中,我只留下了一個backup_file.py外掛,用於編寫自己的外掛參考;同時我將這個外掛改成自己外掛的名字,如下圖所示

在上圖中,我將外掛檔名子改為了xss_test.py,再次執行,看看是否能正確執行,執行結果如下圖所示

在上圖中可以看到依然是可以執行的,同時外掛名字也發生了變化,變成了xss_test檔案

五、編寫外掛

現在我們就開始編輯xss_test.py外掛,使用pycharm開啟後,看到的程式碼如下圖所示

在上圖中可以看到外掛程式碼裡面有兩個方法audit_check,我做了下分析,audit才是對外的方法,_check方法是外掛內部的方法,我們不需要,直接刪除即可;

接著我們新建一個audit方法,同時備份之前的audit方法為audit_bak作為參考,如下圖所示

在上圖中,我新建了一個audit方法,並接收了請求頭資訊和要請求的URL地址,並給出了要實現XSS漏洞檢測的三個步驟:

  1. 準備poc
  2. 傳送請求
  3. 判斷返回資料裡面是否包含了poc

接著我就開始實現這三個步驟,首先去準備poc程式碼,如下程式碼所示

        # 接收頭資訊
        headers = self.requests.headers
        # 我們不要URL地址中的引數部分
        url = self.requests.netloc
        # 從這裡單獨接收引數,字典型別
        params = self.requests.params
        # 這裡備份一下字典,不要使用同一個記憶體地址
        paramsBak = params.copy()

        # 1. 準備poc
        payloads = [
            "1'\"()&%<acx><ScRiPt >prompt(915149)</ScRiPt>",
            "<svg/onload=alert(1)>",
            "\"><script>alert(document.cookie)</script>"
        ]

接著我需要將poc程式碼和URL地址結合,生成一個帶有攻擊引數的連結地址,程式碼如下所示

        # 每一個payloads都測試一遍
        for payload in payloads:
            # 每一個引數都需要測試
            for key, val in params.items():
                # 每次只測試一個引數,所以需要將之前的字典覆蓋
                params = paramsBak.copy()
                # 將字典裡的值改變,然後放到另外一個函式生成一個URL地址
                params[key] = payload
                nUrl = self.createUrl(url, params)

生成如下URL地址:

http://192.168.152.135:8888/home/index.php?m=<svg/onload=alert(1)>&a=index&bk=6

或者如下:

http://192.168.152.135:8888/home/index.php?m=tiezi&a=<svg/onload=alert(1)>&bk=6

依次將poc程式碼替換到原有請求引數當中,接下來就是使用python去請求這個地址,並檢視返回結果是否包含了poc程式碼,如果包含了poc程式碼說明後端沒有做過濾處理,程式碼如下所示

                # 2. 傳送請求
                r = requests.get(nUrl, headers=headers, allow_redirects=False)
                # 如果返回值是200,說明頁面可以訪問
                if r.status_code == 200:
                    # 3.判斷返回資料裡面是否包含了poc,包含了說明存在XSS
                    if payload in r.text:
                        # 將結果返回給框架,統一儲存
                        result = self.new_result()
                        result.init_info(nUrl, "XSS檢測", VulType.BRUTE_FORCE)
                        # 儲存掃描結果
                        result.add_detail("payload請求", r.reqinfo, "請求返回結果", "外掛備註資訊", nUrl, "", PLACE.GET)
                        self.success(result)

程式碼的含義在上面的備註資訊中已經有說明,就不再過多贅述了,接下來我們再次執行W13Scan,執行命令如下所示

python  w13scan.py  -u "http://192.168.152.135:8888/home/index.php?m=tiezi&a=index&bk=6"

命令執行之後,控制檯輸出的資訊如下所示

在上圖中可以看到我們的外掛已經成功執行,並檢測到了XSS漏洞

六、結果驗證

接下來我複製其中一個帶有poc的URL地址,放到瀏覽器去執行,如下圖所示

在上圖中可以看到瀏覽器觸發了XSS程式碼,彈出了cookie值,至此編寫XSS檢測外掛就完成了,當然這個外掛還不夠完善,有興趣的可以自己再深入研究~

完整的poc程式碼可以參考:

https://gitee.com/songboy/codes/kodyj714izqbpgv8cu2n390

作者:湯青松

日期:2020-12-08

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章