只有一百行的xss掃描工具——DSXS源碼分析


0x00 廢話

DSXS是一個只有一百行代碼的xss掃描器,其作者剛好就是寫sqlmap的那位,下面來看一下其掃描邏輯。0x01部分文字較多,感覺寫的有點啰嗦,如果看不下去的話就直接看最后的0x02的總結部分。

0x01 掃描邏輯

程序有兩個非並行的邏輯,第一個邏輯是檢測dom型xss,第二個邏輯是檢測經過后端的xss。在執行兩個邏輯之前,程序會先判斷目標路徑上是否有參數值為空的情況,有則賦為1,比如:baidu.com/?id=99&name=&age=轉換成baidu.com/?id=99&name=1&age=1。轉換完成后,進入xss檢測邏輯部分。

第一個邏輯:dom型xss

首先根據dom_filter_regex去掉響應包中的內容,然后在響應中查找dom_patterns,如果存在,則提示可能存在dom-xss

第二個邏輯:經過后端的xss

首先要知道這里有一個核心的正則表達式list,一共有九個元組,每個元組都代表輸出點在dom結點中的一個確定的位置,比如:script標簽內、單引號內、注釋內。。然后對應每個位置,還有對應的攻擊方法,比如在單引號內就需要用單引號逃逸,即單引號在響應中不能被轉義,如果被轉義就完了。其中每個元組有四個元素,詳細看下面:

REGULAR_PATTERNS = (                                                                        # each (regular pattern) item consists of (r"context regex", (prerequisite unfiltered characters), "info text", r"content removal regex") # 格式(匹配有可能存在xss的字符串的正則,攻擊成功需要哪些字符未經過濾,說明(簡易表達匹配格式),獲取響應包后首先篩掉的字符的regexp)
    (r"\A[^<>]*%(chars)s[^<>]*\Z", ('<', '>'), "\".xss.\", pure text response, %(filtering)s filtering", None),
    (r"<!--[^>]*%(chars)s|%(chars)s[^<]*-->", ('<', '>'), "\"<!--.'.xss.'.-->\", inside the comment, %(filtering)s filtering", None),
    (r"(?s)<script[^>]*>[^<]*?'[^<']*%(chars)s|%(chars)s[^<']*'[^<]*</script>", ('\'', ';'), "\"<script>.'.xss.'.</script>\", enclosed by <script> tags, inside single-quotes, %(filtering)s filtering", r"\\'"),
    (r'(?s)<script[^>]*>[^<]*?"[^<"]*%(chars)s|%(chars)s[^<"]*"[^<]*</script>', ('"', ';'), "'<script>.\".xss.\".</script>', enclosed by <script> tags, inside double-quotes, %(filtering)s filtering", r'\\"'),
    (r"(?s)<script[^>]*>[^<]*?%(chars)s|%(chars)s[^<]*</script>", (';',), "\"<script>.xss.</script>\", enclosed by <script> tags, %(filtering)s filtering", None),
    (r">[^<]*%(chars)s[^<]*(<|\Z)", ('<', '>'), "\">.xss.<\", outside of tags, %(filtering)s filtering", r"(?s)<script.+?</script>|<!--.*?-->"),
    (r"<[^>]*=\s*'[^>']*%(chars)s[^>']*'[^>]*>", ('\'',), "\"<.'.xss.'.>\", inside the tag, inside single-quotes, %(filtering)s filtering", r"(?s)<script.+?</script>|<!--.*?-->|\\"),
    (r'<[^>]*=\s*"[^>"]*%(chars)s[^>"]*"[^>]*>', ('"',), "'<.\".xss.\".>', inside the tag, inside double-quotes, %(filtering)s filtering", r"(?s)<script.+?</script>|<!--.*?-->|\\"),
    (r"<[^>]*%(chars)s[^>]*>", (), "\"<.xss.>\", inside the tag, outside of quotes, %(filtering)s filtering", r"(?s)<script.+?</script>|<!--.*?-->|=\s*'[^']*'|=\s*\"[^\"]*\""),
)

人話版如下:

這個表說了,下面說一下檢測的大體流程。首先是發送payload,然后查找payload的輸出點,接着再看這個輸出點對應上邊表中的哪個位置。找到對應的位置之后再看如果在這個位置要利用成功需要哪些字符不被轉義,然后在響應中查找payload,確定payload中‘不可被轉義的特殊字符’前是否被加上了反斜杠\,如果有則認為被轉義,並繼續往下找,直到每個不可被轉義的字符至少在響應中未被轉義地出現了一次,才會認為存在漏洞。

下面根據代碼說一下。

62-65行是dom-xss檢測,是屬於上面的第一個邏輯,這里就不再展開。從67行往下看,首先是分別進行GET和POST請求,然后到了69行。
這里在url和post-data中查找鍵值對(參數)的位置,然后對每個參數進行以下的測試。

從72行可以看到,首先賦值兩個長度為5的隨機字符的字符串:prefix和suffix
然后使用一個for循環,針對larger_char_pool和smaller_char_pool進行單獨的測試(這兩個list分別是:(''', '"', '>', '<', ';') 和('<', '>')。之所以要用兩個list的原因是防止后端使用waf/ids時對payload進行攔截,所以使用了一個smaller_payload來避免過於明顯的payload[即有較少的特殊字符]) 。

進入75行,這里先構造payload,payload格式為prefix+pool中所有字符的隨機排序+suffix,如果這個pool是larger_char_pool,則這里在payload之前加一個單引號'原因如下:
1) .試圖觸發xss
2) .故意構造一個錯誤的sql語句用於報錯,試圖在報錯信息中尋找觸發點

這里暫且把prefix與suffix中間的部分稱為vector。構造完payload之后直接發送,然后獲取返回內容。如果這個pool是larger_char_pool,那么這里就要去掉prefix之前的單引號',這個單引號的作用剛剛已經說了,至此已經完成了它的使命,這里自然要從響應中去掉,防止干擾。

然后到77行,下面開始使用regular_patterns對相應內容進行測試,首先根據content_removal_regex去掉響應中的內容(因為payload有重合部分,所以要通過這種方式來避免重合的檢測,即表中每個元組的第四個元素),然后在響應中尋找(prefix+...+suffix) [注:這里的規則大致是prefix.*suffix,不指定中間的部分為vector,因為vector有可能被后端轉義掉了],暫時稱之為response-payload。

如果可以找到,就說明這個參數的值是會被輸出到響應中的(先不管有沒有過濾),下面的邏輯就要檢測這個參數是否可以利用。首先需要確定response-payload的輸出點在哪個位置(script標簽內?注釋內?引號內?等等,詳見REGULAR_PATTERNS),然后再根據輸出點來確定在這個位置利用成功需要哪些字符不被過濾。
ok,邏輯大概理清楚了,下面是程序的實現。首先是輸出點定位,在第80行,程序將response-payload插入到regular_patterns的regex(每個元組的第一個元素)中的chars位置,如果可以在響應中匹配到regex,就說明定位成功。然后下一步就是檢查字符過濾情況,程序通過在82行調用_contains函數來確定“不可被過濾的字符”在響應中是否被過濾(即判斷這些字符前是否有反斜杠\),對prefix和suffix中vector位置的字符串進行檢測,_contains代碼如下:

這里如果沒有被過濾,這認為可能存在漏洞。

0x02 總結

至此,這個代碼分析結束。來個總結,dom xss的檢測方法就是通過正則表達式來對一些有可能造成危害的函數進行匹配,並且匹配其參數是否可控。至於經過后端型xss,這里先是通過正則判斷輸出點在dom樹中的位置,然后確定如果想要觸發xss需要哪些字符不被過濾,接着再根據響應包中的payload中的特殊字符前是否有反斜杠來確定其是否被過濾從而確定是否滿足上面的條件,滿足則存在漏洞。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM