dom xss->半自動化

2022-11-24 12:00:31

  前幾天看了兩篇文章,覺得很不錯,寫一筆,就當筆記記錄。

  第一篇文章:https://jinone.github.io/bugbounty-dom-xss/

  作者寫了自己通過自動化挖dom xss,差不多賺了3w刀左右。他分享了一些不錯的漏洞案例。這裡很感謝作者,無私分享思路出來,也給大家有了喝口湯的機會。

  中國需要多一些這樣的熱愛分享的白帽子,一方面是推動安全測試水位,另一方面是帶來更多的思路給他人。看這篇文章,給了我一些啟發。在相當內卷的今天,選擇適合自己的漏洞挖掘賽道很重要。就像不是人人都適合挖rce,一個道理。

    第一篇文章的細節點:

  存取: 

https://example.com/xsspath'%22?xssparam%27%22=xssvalue%27%22#xsshash'%22

  

 

 

 

結論:

location.search 會對'"編碼
location.hash 不會對'編碼
location.pathnme 不會對'編碼
location.href hash和pathname中的'不會被編碼 包含search,hash和pathname

{ 這三個可以跳出單引號
location.href
location.hash
location.pathname 
}

 

 

  因為作者文章中提到有自動化挖掘。這裡就調研了下市面上的工具,記錄下:

  通過檢視作者寫的文章,以及自己對dom xss的理解,簡單寫下半動化的粗略思路

  dom xss半自動化簡單思路:

{
n個source
n個sink
如果有某個source和某個sink同時存在

疑似dom xss,命中
}

只檢索applocation/javascript和text/html

  關於dom xss的探測,多疑似,那麼誤報率就會很高。

 缺陷很明顯,需要儘可能的收集javascript和javscipt庫的source和sink,吃經驗,吃規律,需要熟悉一定的規律。

 工具1:Dom Invader 可以用於檢測dom xss和postMessage xss

  

 

 

 

   檢測postmessage+dom xss設定如下:

   

 

 

  和寫dom xss的作者聊過一些,這款工具,檢測dom xss很不錯

  關於這個外掛的學習教學:

  

https://www.youtube.com/watch?v=Wd2R47czzO0&t=156s
https://portswigger.net/blog/introducing-dom-

  這裡簡單提一嘴,burpsuite很多外掛,挖洞使用很方便,有空的話,我講下burpsuite上一些很好的輔助挖洞神器。

  這個工具我就一筆帶過,他不是本文的重點,本文的重點是另一個工具:

  重點檢測工具:semgrep

  semgrep? what? 

A fast, open-source, static analysis tool for profoundly improving software security and reliability.
一種快速、開源、靜態分析工具,可顯著提高軟體的安全性和可靠性。
我認為它就是grep命令的升級版,更加的強大。

  

  優勢:

1.支援本地,命令列執行,很方便
2.支援線上網站上建立和匯入/新增規則
3.支援批次檢測,無需對程式碼進行編譯

 

  什麼場景下使用他們?

 

1.大量的程式碼,進行安全缺陷審查
2.漏洞挖掘,web程式碼審計
3.支援純文字程式碼識別和汙點跟蹤
4.src/眾測 部分程式碼需要
5.發現某個漏洞特徵,使用semgrep事半功倍

 

 安裝:

 

三種安裝方式
# Using Homebrew
$ brew upgrade semgrep

# Using pip
$ python3 -m pip install --upgrade semgrep

# Using Docker
$ docker pull returntocorp/semgrep:latest

 

 

 

 這裡我使用的是第二種,pip安裝。

 referer: https://github.com/returntocorp/semgrep

 

 semgrep基礎使用:

 1.命令列cl使用 

semgrep --pattern '127.$A.$B.$C' --lang generic /etc/hosts

#lang 是指定某種型別
參考:https://semgrep.dev/docs/supported-languages/ 很詳細

 

 

 

  

參考:https://semgrep.dev/docs/getting-started/

—pattern是一種匹配模式。但是更推薦的是匯入yaml,對某段程式碼/某個專案進行執行漏洞規則檔案:

 

 

 漏洞yaml規則庫大全 用於學習編寫規則:

 

https://github.com/returntocorp/semgrep-rules
https://semgrep.dev/playground/new?editorMode=advanced

 涉及到的語言眾多

  

 

 

  汙點跟蹤 這個適合漏洞挖掘,半自動化:

  汙點跟蹤演示教學:https://semgrep.dev/docs/writing-rules/data-flow/taint-mode/

  使用汙點跟蹤半動化檢測dom xss:

  

rules:
  - id: domxss-insertAdjacentHTML
    languages:
      - javascript
      - typescript
    message: Found dangerous HTML output
    mode: taint
    pattern-sources:
      - pattern: document.location.href
      - pattern: document.location
      - pattern: window.location
      - pattern: window.location.href
    pattern-sinks:
      - pattern: $X.insertAdjacentHTML(...)
      - pattern: $X.innerHTML(...)
      - pattern: $X.innerHTML = ...
    severity: WARNING

 

 不想聊規則細節,我說下這段yaml哪裡來的。

 參考:https://netsec.expert/posts/automating-dom-xss/

 一定要看,這篇文章作者是谷歌的一位安全工程師,這是他寫的規則。

 他還寫了一個輔助工具,用於爬蟲網站上的js:https://github.com/the-xentropy/dump-scripts/blob/main/dump-scripts.py

 

 

 

 

  

 

 

  然後呼叫semgrep批次檢測script目錄裡的js。

  這個規則,會漏掉很多dom xss,這裡簡單調研了下,source和sink非常多,這裡只總結了一些常見的,整合了前面的幾位作者的思路和官方規則:

  總結了下用於檢測js open redirect_url和其他型別的dom xss規則:

rules:
  - id: dom_xss
    message: dom_xss
    metadata:
      cwe:
        - "dom_xss"
      owasp:
        - A03:2021 - Injection
      asvs:
        section: V5 Validation, Sanitization and Encoding
        control_id: 5.2.4 Dynamic Code Execution Features
        control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v52-sanitization-and-sandboxing
        version: "4"
      category: security
      technology:
        - browser
      subcategory:
        - audit
      likelihood: LOW
      impact: MEDIUM
      confidence: LOW
      references:
        - https://owasp.org/Top10/A03_2021-Injection
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
    languages:
      - javascript
      - typescript
    severity: WARNING
    mode: taint
    pattern-sources:
      - patterns:
          - pattern-inside: |
              url.split('...')
      - patterns:
          - pattern-inside: |
              getURLParameter('...')
      - patterns:
          - pattern-inside: |
              $PROPS.get('...')
      - patterns:
          - pattern-inside: |
              getUrlParameter('...')
      - patterns:
          - pattern-inside: |
              GetQueryString('...')
      - patterns:
          - pattern-inside: |
              $PROPS.get('...')
      - patterns:
          - pattern-inside: |
              $PROPS.split("...")
      - patterns:
          - pattern-either:
              - pattern-inside: >
                  $PROP = new URLSearchParams($WINDOW. ...
                  .location.search).get('...')

                  ...
              - pattern-inside: |
                  $PROP = new URLSearchParams(location.search).get('...')
                  ...
              - pattern-inside: >
                  $PROP = new URLSearchParams($WINDOW. ...
                  .location.hash.substring(1)).get('...')

                  ...
              - pattern-inside: >
                  $PROP = new
                  URLSearchParams(location.hash.substring(1)).get('...')

                  ...     
              - pattern-inside: | 
                  $PROP = window.location.search.substr(1).match(...)  

                  ...
          - pattern: $PROP
      - patterns:
          - pattern-either:
              - pattern-inside: |
                  $PROPS = new URLSearchParams($WINDOW. ... .location.search)
                  ...
              - pattern-inside: |
                  $PROPS = new URLSearchParams(location.search)
                  ...
              - pattern-inside: >
                  $PROPS = new URLSearchParams($WINDOW. ...
                  .location.hash.substring(1))

                  ...
              - pattern-inside: |
                  $PROPS = new URLSearchParams(location.hash.substring(1))
                  ...
          - pattern: $PROPS.get('...')
      - patterns:
          - pattern-either:
              - pattern-inside: |
                  $PROPS = new URL($WINDOW. ... .location.href)
                  ...
              - pattern-inside: |
                  $PROPS = new URL(location.href)
                  ...
          - pattern: $PROPS.searchParams.get('...')
      - patterns:
          - pattern-either:
              - pattern-inside: >
                  $PROPS = new URL($WINDOW. ...
                  .location.href).searchParams.get('...')

                  ...
              - pattern-inside: |
                  $PROPS = new URL(location.href).searchParams.get('...')
                  ...
          - pattern: $PROPS

    pattern-sinks:
      - patterns:
          - pattern-either:
              - pattern: $WINDOW. ... .location.href = $SINK
              - pattern: $WINDOW. ... .location = $SINK
              - pattern: location.href = $SINK
              - pattern: $THIS. ... .location.href = $SINK
              - pattern: $THIS. ... .location.replace($SINK)
              - pattern: $WINDOW. ... .replace($SINK)
              - pattern: $PROPS.replace($SINK)
              - pattern: $X.insertAdjacentHTML($SINK)
              - pattern: $X.innerHTML($SINK)
              - pattern: $X.innerHTML = $SINK
              - pattern: $X.innerHTML += $SINK
              - pattern: $X.prepend($SINK)
              - pattern: $X.prepend("..."+$SINK)
              - pattern: $X.append($SINK)
              - pattern: $X.append("..."+$SINK)
              - pattern: $X.before($SINK)
              - pattern: $X.before("..."+$SINK)
              - pattern: $X.after($SINK)
              - pattern: $X.after("..."+$SINK)
              - pattern: $X.html($SINK)
              - pattern: $X.html("..."+$SINK)
              
          - metavariable-pattern:
              patterns:
                - pattern-not: |
                    "..." + $VALUE
                - pattern-not: |
                    `...${$VALUE}`
              metavariable: $SINK

   如何實戰利用?

  使用一個漏洞規則批次檢測多個專案:

 

 

   使用多個規則檢測多個專案:

semgrep -c rules/  jstest/*

 

  

 

 

  對於semgrep,我並不陌生。早在今年log4j2漏洞剛爆發的時候,我們團隊內部就使用了semgrep編寫log4j2規則去批次檢測,效果很好。 

  工具很強大,寫好匹配規則即可。語言都是次要的,主要是要多收集source和sink。剩下的就是套娃~~