1. 程式人生 > >XSStrike原始碼閱讀(2)——四種模式

XSStrike原始碼閱讀(2)——四種模式

1.bruteforcer模式

功能介紹

根據使用者提供的payloads檔案去暴力測試每一個引數,以此來確定是否存在xss漏洞(說起來也就是一個兩層迴圈)。

具體實現

XSStrike3.0 bruteforcer.py原始碼如下:

import copy
from urllib.parse import urlparse, unquote

from core.colors import run, good, bad, green, end
from core.requester import requester
from core.utils import getUrl, getParams, verboseOutput

def bruteforcer(target, paramData, payloadList, verbose, encoding, headers, delay, timeout):
    GET, POST = (False, True) if paramData else (True, False)
    
    #輸出此次掃描目標的相關資訊:主機地址,url,以及引數字典(都是在verbose模式下才輸出)
    host = urlparse(target).netloc  # Extracts host out of the url
    verboseOutput(host, 'host', verbose)
    url = getUrl(target, GET)
    verboseOutput(url, 'url', verbose)
    params = getParams(target, paramData, GET)
    if not params:
        print('%s No parameters to test.' % bad)
        quit()
    verboseOutput(params, 'params', verbose)
    for paramName in params.keys():
        progress = 1
        paramsCopy = copy.deepcopy(params)
        for payload in payloadList:
            print ('%s Bruteforcing %s[%s%s%s]%s: %i/%i' % (run, green, end, paramName, green, end, progress, len(payloadList)), end='\r')
            if encoding:
                payload = encoding(unquote(payload))
            paramsCopy[paramName] = payload
            response = requester(url, paramsCopy, headers,
                                 GET, delay, timeout).text
            if encoding:
                payload = encoding(payload)
            if payload in response:
                print('%s %s' % (good, payload))
            progress += 1
    print ()

其中涉及到兩個相對重要的函式:

getparams

先上原始碼:

def getParams(url, data, GET):
    params = {}
    if '=' in url:
        data = url.split('?')[1]
        if data[:1] == '?':
            data = data[1:]
    elif data:
        if core.config.globalVariables['jsonData'] or core.config.globalVariables['path']:
            params = data
        else:
            try:
                params = json.loads(data.replace('\'', '"'))
                return params
            except json.decoder.JSONDecodeError:
                pass
    else:
        return None
    if not params:
        parts = data.split('&')
        for part in parts:
            each = part.split('=')
            try:
                params[each[0]] = each[1]
            except IndexError:
                params = None
    return params

該函式的主要功能就是將需要測試的引數都轉換成一個字典返回。但是讀者可能也知道引數有四種形式:get引數,post引數(a=b形式),post引數(json形式),path(路徑中也可能存在xss)
當然,如果是json或者path,在xsstrike.py中就已經進行了處理,並作為data引數傳了過來,所以直接賦值給params就行。

requester

使用requests庫去請求伺服器,於此同時設定了一些頭資訊

2.singleFuzz模式

主要功能

waf探測,fuzz測試

具體實現

1.waf探測部分

waf探測其實思想很簡單,就是發起一個一定會觸發waf的惡意請求,獲取到這個請求的返回內容,然後利用已知waf的特種去匹配返回內容,如果匹配到某種或多種waf的特徵,就取最佳匹配的那一個。這裡獲取最佳匹配是有一個小小的演算法的:

我們以http請求的返回狀態碼、返回文字、返回頭資訊這三個基本資訊作為判斷waf的依據,例如:

360
上面是360web防火牆的特徵,如果網站裝有360web防火牆的話,我們的惡意資料在被其攔截過後,它會返回給我們一個響應,而這個響應的狀態碼(status_code)為403,返回的http頭中會有X-Powered-By-360wzb,頁面中會出現/wzws-waf-cgi/字樣,然後我們給這三個特徵分別加權,code權重為0.5,page權重為1,headers權重為1,這樣當匹配到疑似多種waf特徵的時候,我們只取權重最高的那一個作為我們最後的判斷結果。

2.fuzz測試

fuzz測試大家應該都知道,一般用於檢測waf的過濾情況或相關特性。方法就是使用相關的各種payloads去挨個測試每個引數,具體方法當然是帶著這些payloads去請求,如果請求沒有被攔截就說明fuzz通過,否則就是這個payloads被waf遮蔽了。
在這款工具中,作者考慮到fuzz測試由於請求頻率過高很容易被waf 遮蔽掉ip,所以也是採用了一定的延時策略。而且採用了在payloads被waf拒絕掉後,間隔一定時間再發起正常請求這種方式來判斷waf是否遮蔽了使用者的ip。
fuzz測試的一些payloads也是放在了config.py中:

fuzzes = (  # Fuzz strings to test WAFs
    '<test', '<test//', '<test>', '<test x>', '<test x=y', '<test x=y//',
    '<test/oNxX=yYy//', '<test oNxX=yYy>', '<test onload=x', '<test/o%00nload=x',
    '<test sRc=xxx', '<test data=asa', '<test data=javascript:asa', '<svg x=y>',
    '<details x=y//', '<a href=x//', '<emBed x=y>', '<object x=y//', '<bGsOund sRc=x>',
    '<iSinDEx x=y//', '<aUdio x=y>', '<script x=y>', '<script//src=//', '">payload<br/attr="',
    '"-confirm``-"', '<test ONdBlcLicK=x>', '<test/oNcoNTeXtMenU=x>', '<test OndRAgOvEr=x>')

3.scan模式

主要功能