blog of morioka12

morioka12のブログ (Security Blog)

バグバウンティにおける JavaScript の静的解析と動的解析まとめ

1. 始めに

こんにちは、morioka12 です。

本稿では、バグバウンティなどの脆弱性調査で行う、JavaScript の静的解析と動的解析についてまとめて紹介します。


免責事項

本稿の内容は、セキュリティに関する知見を広く共有する目的で執筆されており、悪用行為を推奨するものではありません。

想定読者

  • セキュリティ初学者・学生
    • 特に Web Security の学習をしている方
  • バグバウンティに興味がある方
  • (脆弱性調査をしている方)
  • ( Web アプリケーションの開発者)

検証環境

今回は、ツールの検証環境として、「OWASP Juice Shop」を活用します。

OWASP Juice Shop は、「OWASP Top 10」に含まれる脆弱性を取り入れた「やられアプリ」で、Node.js・Express・Angular などの JavaScriptフレームワークで書かれています。

  • http://localhost/#/
    • ( Docker でローカル環境に構築)


静的解析と動的解析

  • 静的解析 (Static Analysis)
  • 動的解析 (Dynamic Analysis)
    • 実際にソースコードが実行されて、その挙動をベースに解析する方法


2. 静的解析 (Static Analysis)

Web アプリケーション上にある JavaScript ファイルを静的解析する場合は、主に以下のような点を確認します。


また、JavaScript ファイルの静的解析は、主に以下のような流れで行います。

  1. 対象の Web アプリケーションのドメインから JavaScript ファイルの URL を収集する
  2. 収集した JavaScript ファイルからコードを解析してエンドポイントを列挙する
    • まだ未発見だったエンドポイントや API 、パラメーターを知れる可能性がある
  3. 収集した JavaScript ファイルからコードを解析してシークレットな情報を検出する
    • ハードコードされている API の認証情報など得れる可能性がある
  4. 収集した JavaScript ファイルで使われているライブラリやフレームワークなどを特定して潜在的脆弱性を特定する
    • 実際の Web アプリケーションで有効に活用できるセキュリティ問題を得れる可能性がある


2.1 JavaScript File の URL を収集する

getJS

getJS は、指定したドメインから JavaScript のファイルの URL を収集することができます。

$ getJS --url https://<Domain> --complete

検証環境に対する実行結果 (クリックで表示)

$ getJS --url http://localhost --complete
http://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js
http://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js
http://localhost//runtime.js
http://localhost//polyfills.js
http://localhost//vendor.js
http://localhost//main.js

github.com


hakrawler

hakrawler は、クローリングツールで、URL と JavaScript のファイルを収集することができます。

$ echo "https://<Domain>" | hakrawler

検証環境に対する実行結果 (クリックで表示)

$ echo "http://localhost" | hakrawler
http://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js
http://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js
http://localhost/runtime.js
http://localhost/polyfills.js
http://localhost/vendor.js
http://localhost/main.js

github.com


getallurls (gau)

getallurls (gau) は、 Wayback Machine などから既知の URL を列挙するツールで、その出力結果から JavaScript のファイルのみを抽出して収集することもできます。

$ gau <Domain> | grep ".js$" | sort -u

github.com


2.2 エンドポイントを列挙する

LinkFinder

LinkFinder は、ドメインから JavaScript ファイル内にあるエンドポイントを列挙することができます。

$ python3 linkfinder.py -i https://<Domain> -d -o cli
$ python3 linkfinder.py -i https://<Domain>/<Path>/<JS-file> -o cli

検証環境に対する実行結果 (クリックで表示)

$ python3 linkfinder.py -i http://localhost -d -o cli
 ...
Running against: http://localhost/runtime.js

Running against: http://localhost/polyfills.js

https://github.com/zloirock/core-js/blob/v3.33.2/LICENSE
https://github.com/zloirock/core-js
Running against: http://localhost/vendor.js

text/css
http://www.w3.org/2000/svg
/assets/i18n/
image/png
/engine.io
application/octet-stream
application/pdf
application/msword
image/photoshop
image/x-photoshop
image/psd
application/photoshop
application/psd
zz-application/zz-winassoc-psd
application/x-gtar
application/x-gcompress
application/compress
application/x-tar
application/x-rar-compressed
application/x-zip-compressed
application/zip-compressed
application/x-7z-compressed
application/gzip
application/x-bzip2
/socket.io
text/plain
application/json
https://g.co/ng/security#xss
text/html
M/d/yy
zone.js
http://www.w3.org/1999/xhtml
http://www.w3.org/1999/xlink
http://www.w3.org/XML/1998/namespace
http://www.w3.org/2000/xmlns/
http://www.w3.org/1998/MathML/
Running against: http://localhost/main.js

/rest/admin
/application-configuration
/rest/web3
/nftUnlocked
/nftMintListen
/api/Challenges/?key=nftMintChallenge
/submitKey
/walletNFTVerify
/walletExploitAddress
/rest/admin/application-configuration
privacy-security/privacy-policy
https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/771984076&amp;color=%23ff5500&amp;auto_play=true&amp;hide_related=false&amp;show_comments=true&amp;show_user=true&amp;show_reposts=false&amp;show_teaser=true
/assets/public/images/hackingInstructor.png
https://ponzico.win/ponzico.pdf
https://www.sec.gov/investor/alerts/ia_virtualcurrencies.pdf
assets/public/images/padding/56px.png
/api/Users
/rest/user/authentication-details/
/rest/user/login
/rest/user/change-password?current=
/rest/user/reset-password
/rest/user/whoami
https://www.googleapis.com/oauth2/v1/userinfo?alt=json&amp;access_token=
/rest/saveLoginIp
/rest/deluxe-membership
/login
/api/BasketItems
assets/public/images/products/
/address/select
/rest/track-order
/api/Feedbacks
/rest/captcha
/160
assets/public/images/carousel/1.jpg
assets/public/images/carousel/2.jpg
assets/public/images/carousel/3.jpg
assets/public/images/carousel/4.jpg
assets/public/images/carousel/5.png
assets/public/images/carousel/6.jpg
assets/public/images/carousel/7.jpg
ftp/legal.md
/api/SecurityAnswers
/api/SecurityQuestions
/rest/user/security-question?email=
/20
/40
/rest/products
/reviews
/api/Products
/api/Quantitys
assets/public/images/products/no-results.png
/search
/2fa/enter
/forgot-password
/register
assets/public/images/padding/19px.png
/api/Complaints
/file-upload
application/pdf
application/xml
text/xml
application/zip
application/x-zip-compressed
multipart/x-zip
/rest/chatbot
/status
/respond
assets/public/images/ChatbotAvatar.png
assets/public/images/uploads/default.svg
/api/Recycles
/api/Addresss
/address/edit/
/delivery-method
/address/create
/api/Challenges
/rest/repeat-notification
/rest/continue-code
/rest/continue-code-findIt
/rest/continue-code-fixIt
/rest/continue-code/apply/
/rest/continue-code-findIt/apply/
/rest/continue-code-fixIt/apply/
/snippets
/snippets/fixes
/snippets/verdict
https://docs.google.com/forms/d/e/1FAIpQLSdaNEuz0dzFA2sexCa0AJ4QOb2OYdEL04eQOLFD2Y4T-BW6ag/viewform?usp=pp_url&amp;entry.384948954=
https://forms.gle/2Tr5m1pqnnesApxN8
/score-board-preview
assets/public/images/padding/1px.png
http://www.w3.org/2000/svg
/rest/image-captcha/
/rest/user
/erasure-request
/data-export
https://www.freeprivacypolicy.com/
assets/public/images/padding/81px.png
/rest/wallet/balance
/api/Deliverys
/api/Cards
/16
/10
/wallet
/deluxe-membership
/order-summary
./redirect?to=https://blockchain.info/address/1AbKfgvw9psQ41NbLi8kufDQTezwG8DRZm
./redirect?to=https://explorer.dash.org/address/Xr556RzuwX6hg5EGpkybbv5RanJoZN17kW
./redirect?to=https://etherscan.io/address/0x0f933ab9fcaaa782d0279c300d73750e1311eae6
https://pwning.owasp-juice.shop/part3/donations.html
./redirect?to=http://shop.spreadshirt.com/juiceshop
./redirect?to=http://shop.spreadshirt.de/juiceshop
./redirect?to=https://www.stickeryou.com/products/owasp-juice-shop/794
./redirect?to=http://leanpub.com/juice-shop
https://opensea.io/collection/juice-shop
/rest/order-history
/orders
https://twitter.com/
/track-result/new
https://twitter.com/intent/tweet?text=
/order-completion
/payment
/#/wallet-web3
/track-result
/rest/memories
multipart/form-data
assets/public/images/JuiceShop_Logo.png
assets/public/images/deluxe/blankBoxes.png
assets/public/images/products/juicy_chatbot.jpg
https://testnets.opensea.io/0x8343d2eb2B13A2495De435a1b15e85b98115Ce05
https://testnets.opensea.io/assets/mumbai/0xf4817631372dca68a25a18eb7a0b36d54f3dbcf7/0
/score-board
address/select
address/saved
address/create
track-result/new
2fa/enter
/application-version
privacy-security/data-export
privacy-security/change-password
privacy-security/two-factor-authentication
privacy-security/last-login-ip
assets/public/images/
/profile
/dataerasure
http://www.w3.org/1999/html
/accounting
/basket
/order-history
/recycle
/address/saved
/saved-payment-methods
https://owasp.org
https://owasp-juice.shop
/rest/country-mapping
/contact
/complain
/chatbot
/about
/photo-wall
./redirect?to=https://github.com/juice-shop/juice-shop
./assets/i18n/
image/x-icon
assets/public/favicon_js.ico
text/css
//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.css
//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js
//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js
https://www.youtube.com/watch?v=9PnbKL3wuH4
runtime.js
polyfills.js
vendor.js
main.js

github.com


xnLinkFinder

xnLinkFinder は、ドメインから JavaScript ファイル内にあるエンドポイントやパラメーターを列挙することができます。

$ python3 xnLinkFinder.py -i <Domain> -sp https://<Domain> -sf <Domain> -v

github.com


katana

katana は、クローリングツールで、オプションで JavaScript ファイルの解析と JavaScript ファイル内からエンドポイントをクロールする「-js-crawl」があり、これを使うことでエンドポイントを列挙することができます。

$ katana -u http://<Domain> -jc

検証環境に対する実行結果 (クリックで表示)

$ katana -u http://localhost -jc          

   __        __                
  / /_____ _/ /____ ____  ___ _
 /  '_/ _  / __/ _  / _ \/ _  /
/_/\_\\_,_/\__/\_,_/_//_/\_,_/                             

      projectdiscovery.io

[INF] Current katana version v1.0.4 (latest)
[INF] Started standard crawling for => http://localhost/
http://localhost/
http://localhost/runtime.js
http://localhost/polyfills.js
http://localhost/main.js
http://localhost/styles.css
http://localhost/rest/country-mapping
http://localhost/redirect?to=https
http://localhost/rest/admin
http://localhost/rest/web3
http://localhost/vendor.js
http://localhost/redirect?to=http
http://localhost/assets/public/images/
http://localhost/rest/admin/application-configuration
http://localhost/api/Cards
http://localhost/address/saved
http://localhost/assets/i18n/
http://localhost/rest/order-history
http://localhost/rest/wallet/balance
http://localhost/snippets/verdict
http://localhost/snippets/fixes
http://localhost/track-result/new
http://localhost/rest/user
http://localhost/rest/image-captcha/
http://localhost/rest/continue-code-findIt/apply/
http://localhost/rest/continue-code-fixIt/apply/
http://localhost/rest/continue-code
http://localhost/rest/repeat-notification
http://localhost/rest/continue-code/apply/
http://localhost/api/Addresss
http://localhost/api/Recycles
http://localhost/address/create
http://localhost/address/edit/
http://localhost/api/Complaints
http://localhost/rest/chatbot
http://localhost/2fa/enter
http://localhost/rest/products
http://localhost/rest/memories
http://localhost/api/SecurityAnswers
http://localhost/rest/user/security-question?email=
http://localhost/rest/track-order
http://localhost/%5C/index.html
http://localhost/application/vnd.ms-word.do
http://localhost/application/vnd.openxmlformats-officedocument.wordprocessingml.do
http://localhost/angular.json
http://localhost/Highlight.js
http://localhost/like/
http://localhost/address/select
http://localhost/assets/public/images/products/
http://localhost/api/BasketItems
http://localhost/rest/deluxe-membership
http://localhost/rest/saveLoginIp
http://localhost/rest/user/whoami
http://localhost/rest/user/reset-password
http://localhost/rest/user/change-password?current=
http://localhost/rest/captcha
http://localhost/api/Deliverys
http://localhost/rest/user/authentication-details/
http://localhost/rest/continue-code-fixIt
http://localhost/rest/continue-code-findIt
http://localhost/api/Users
http://localhost/rest/user/login
http://localhost/Edge/
http://localhost/Trident/
http://localhost/zone.js
http://localhost/Zone.js
http://localhost/api/Quantitys
http://localhost/api/Products
http://localhost/api/SecurityQuestions
http://localhost/api/Challenges
http://localhost/api/Feedbacks

github.com


jsluice

jsluice は、JavaScript ファイルから URL やエンドポイントなどを列挙することができます。

$ jsluice urls https://<Domain>/<Path>/<JS-file> | jq

検証環境に対する実行結果 (クリックで表示)

(出力結果が長いため、Gist に丸ごと添付しました)

$ jsluice urls http://localhost/main.js | jq         
{
  "url": "/rest/admin",
  "queryParams": [],
  "bodyParams": [],
  "method": "",
  "type": "stringLiteral",
  "filename": "http://localhost/main.js"
}
{
  "url": "/application-configuration",
  "queryParams": [],
  "bodyParams": [],
  "method": "",
  "type": "stringLiteral",
  "filename": "http://localhost/main.js"
}
{
  "url": "/rest/web3",
  "queryParams": [],
  "bodyParams": [],
  "method": "",
  "type": "stringLiteral",
  "filename": "http://localhost/main.js"
}
{
  "url": "/nftUnlocked",
  "queryParams": [],
  "bodyParams": [],
  "method": "",
  "type": "stringLiteral",
  "filename": "http://localhost/main.js"
}
{
  "url": "/nftMintListen",
  "queryParams": [],
  "bodyParams": [],
  "method": "",
  "type": "stringLiteral",
  "filename": "http://localhost/main.js"
}
{
  "url": "/api/Challenges/?key=nftMintChallenge",
  "queryParams": [
    "key"
  ],
  "bodyParams": [],
  "method": "",
  "type": "stringLiteral",
  "filename": "http://localhost/main.js"
}
{
  "url": "/submitKey",
  "queryParams": [],
  "bodyParams": [],
  "method": "",
  "type": "stringLiteral",
  "filename": "http://localhost/main.js"
}
{
  "url": "/walletNFTVerify",
  "queryParams": [],
  "bodyParams": [],
  "method": "",
  "type": "stringLiteral",
  "filename": "http://localhost/main.js"
}
{
  "url": "/walletExploitAddress",
  "queryParams": [],
  "bodyParams": [],
  "method": "",
  "type": "stringLiteral",
  "filename": "http://localhost/main.js"
}
{
  "url": "/rest/admin/application-configuration",
  "queryParams": [],
  "bodyParams": [],
  "method": "GET",
  "type": "fetch",
  "filename": "http://localhost/main.js"
}
 ...

github.com


endext

endext は、JavaScript ファイルからエンドポイントなどを列挙することができます。

$ go run main.go -l urls-js.txt

検証環境に対する実行結果 (クリックで表示)

urls-js.txt は、以下のように JavaScript ファイルの URL 一覧が記載されているとします。

(このファイルの生成方法は、「4. その他 > JS Analyze に使える Burp の機能 > Copy URLs」で紹介しています)

$ cat urls-js.txt 
http://localhost/103.js
http://localhost/main.js
http://localhost/polyfills.js
http://localhost/runtime.js
http://localhost/vendor.js
$ go run main.go -l urls-js.txt      

                  ______          ________     __   
                 / ____/___  ____/ / ____/  __/ /_  
                / __/ / __ \/ __  / __/ | |/_/ __/  
               / /___/ / / / /_/ / /____>  </ /_      
              /_____/_/ /_/\__,_/_____/_/|_|\__/    

            ( * ) EndpointsExtractor Tool By @SirBugs .go Version
            ( * ) For Extracting all possilbe endpoints from Js files 
            ( * ) Version: 1.0.5 (Updated 3.Vrs on 7/7/2023)
            ( * ) Contact: Twitter@SirBagoza, GitHub@SirBugs, Medium@bag0zathev2
            ( * ) Command: go run main.go -l jsurls.txt

            ( ! ) You can use only -u for single URL or -l for .JS file URLs, Not both
            ( ! ) This tool has been received the last 3 updates at once

 ( 1 )  ::  rest/admin
 ( 2 )  ::  application-configuration
 ( 3 )  ::  rest/web3
 ( 4 )  ::  nftUnlocked
 ( 5 )  ::  nftMintListen
 ( 6 )  ::  submitKey
 ( 7 )  ::  walletNFTVerify
 ( 8 )  ::  walletExploitAddress
 ( 9 )  ::  rest/admin/application-configuration
 ( 10 )  ::  api/Users
 ( 11 )  ::  rest/user/authentication-details/
 ( 12 )  ::  rest/user/login
 ( 13 )  ::  rest/user/reset-password
 ( 14 )  ::  rest/user/whoami
 ( 15 )  ::  rest/saveLoginIp
 ( 16 )  ::  rest/deluxe-membership
 ( 17 )  ::  login
 ( 18 )  ::  api/BasketItems
 ( 19 )  ::  address/select
 ( 20 )  ::  rest/track-order
 ( 21 )  ::  api/Feedbacks
 ( 22 )  ::  rest/captcha
 ( 23 )  ::  160
 ( 24 )  ::  api/SecurityAnswers
 ( 25 )  ::  api/SecurityQuestions
 ( 26 )  ::  20
 ( 27 )  ::  40
 ( 28 )  ::  rest/products
 ( 29 )  ::  reviews
 ( 30 )  ::  api/Products
 ( 31 )  ::  api/Quantitys
 ( 32 )  ::  search
 ( 33 )  ::  2fa/enter
 ( 34 )  ::  forgot-password
 ( 35 )  ::  register
 ( 36 )  ::  api/Complaints
 ( 37 )  ::  file-upload
 ( 38 )  ::  rest/chatbot
 ( 39 )  ::  status
 ( 40 )  ::  respond
 ( 41 )  ::  api/Recycles
 ( 42 )  ::  api/Addresss
 ( 43 )  ::  address/edit/
 ( 44 )  ::  delivery-method
 ( 45 )  ::  address/create
 ( 46 )  ::  api/Challenges
 ( 47 )  ::  rest/repeat-notification
 ( 48 )  ::  rest/continue-code
 ( 49 )  ::  rest/continue-code-findIt
 ( 50 )  ::  rest/continue-code-fixIt
 ( 51 )  ::  rest/continue-code/apply/
 ( 52 )  ::  rest/continue-code-findIt/apply/
 ( 53 )  ::  rest/continue-code-fixIt/apply/
 ( 54 )  ::  snippets
 ( 55 )  ::  snippets/fixes
 ( 56 )  ::  snippets/verdict
 ( 57 )  ::  score-board-preview
 ( 58 )  ::  rest/image-captcha/
 ( 59 )  ::  rest/user
 ( 60 )  ::  erasure-request
 ( 61 )  ::  data-export
 ( 62 )  ::  rest/wallet/balance
 ( 63 )  ::  api/Deliverys
 ( 64 )  ::  api/Cards
 ( 65 )  ::  16
 ( 66 )  ::  10
 ( 67 )  ::  wallet
 ( 68 )  ::  deluxe-membership
 ( 69 )  ::  order-summary
 ( 70 )  ::  rest/order-history
 ( 71 )  ::  orders
 ( 72 )  ::  track-result/new
 ( 73 )  ::  order-completion
 ( 74 )  ::  payment
 ( 75 )  ::  track-result
 ( 76 )  ::  rest/memories
 ( 77 )  ::  score-board
 ( 78 )  ::  application-version
 ( 79 )  ::  profile
 ( 80 )  ::  dataerasure
 ( 81 )  ::  accounting
 ( 82 )  ::  basket
 ( 83 )  ::  order-history
 ( 84 )  ::  recycle
 ( 85 )  ::  address/saved
 ( 86 )  ::  saved-payment-methods
 ( 87 )  ::  rest/country-mapping
 ( 88 )  ::  contact
 ( 89 )  ::  complain
 ( 90 )  ::  chatbot
 ( 91 )  ::  about
 ( 92 )  ::  photo-wall
 ( 93 )  ::  assets/i18n/
 ( 94 )  ::  engine.io
 ( 95 )  ::  socket.io

github.com


2.3 シークレット情報を検出する

SecretFinder

SecretFinder は、LinkFinder を元に作られたツールで、JavaScript のファイル内にある API Key や Access Token 、認証情報などの機微な情報を検出することができます。

$ python3 SecretFinder.py -i https://<Domain> -e -o cli

github.com


jsluice

jsluice は、JavaScript ファイルからシークレットな情報も検出することができます。

$ jsluice secrets https://<Domain>/<Path>/<JS-file> | jq

github.com


Mantra

Mantra は、JavaScript ファイルや HTML ファイルから API Key を検出することができます。

$ echo "https://<Domain>/<Path>/<JS-file>" | Mantra

github.com


trufflehog

trufflehog は、様々なファイルなどから認証情報を検出することができます。

trufflehog では、事前に JavaScript ファイルをローカルにダウンロードしておく必要があります。

$ trufflehog filesystem <JS-file>

github.com

また、trufflehog はブラウザの拡張機能が存在するため、これをインストールして有効化しておくと、自動で検出してくれます。

addons.mozilla.org

chrome.google.com


2.4 潜在的脆弱性情報を検出する

Retire.js

Retire.js は、脆弱性のある JavaScript のライブラリを検出することができます。

github.com

retire.js はブラウザの拡張機能が存在するため、これをインストールして有効化しておくと、自動で検出してくれます。

addons.mozilla.org

chrome.google.com


ESLint

ESLint は、JavaScript のファイルに対して静的解析を行うツールで、最新のフレームワークにもカスタムセキュリティルールで対応して解析することができます。

$ eslint <JS-directory>

また、プラグインを活用して、様々な観点で静的解析を行うことも可能です。(以下は例)

例) セキュリティのプラグインを活用して ESLint で静的解析する場合

$ eslint --no-eslintrc -c ~/ESLint/security/.eslintrc.json -f html -o result_eslint-security.html <JS-directory>

github.com


3. 動的解析 (Dynamic Analysis)

Web アプリケーション上にある JavaScript を動的解析する場合は、主にブラウザに搭載されている開発者ツール「DevTools」を用いて行います。

今回は、Chrome の DevTools を用いて簡単に紹介します。

developer.chrome.com

DevTools

Debug

DevTools にある「デバッグ機能」は、特定の条件下で指定した関数にブレークポイントを設定することができます。

ブレークポイント(Breakpoint)とは、プログラムの実行を任意の場所で一時停止して、停止した箇所の変数の状態や関数の呼び出し経路(コールスタック)を確認したり、停止した箇所からコードの実行を一つずつ任意で進めながら、実行の流れを確認したりすることができます。

例えば、「postMessageワイルドカード(*)としてターゲットオリジンに使用されている」という条件でブレークポイントを設定します。

その場合は、「debug()」で以下のようなコードを、DevTools の Console タブから実行します。

debug(postMessage, 'arguments[1] == "*"')

実行後は、Web ページをリロードした際に条件に当てはまる関数が見つかると、自動でブレークポイントが動作して確認することができます。

また、「debug()」以外にも DOM のイベントにブレークポイントを設定する場合は、「monitorEvents()」を利用します。

monitorEvents()」は、要素とイベントを指定することで、その要素に対するイベントの発生を監視することができます。

monitorEvents(window, 'message')


これらのように、特定のメソッドやイベントなどを動的に追って解析したい場合は、デバッグ機能を有効的に活用すると良いと思います。

特に、特定の脆弱性が発生しやすいメソッドやイベント、シンクやソースなどに注目したい場合に有効的な調査することができます。

www.yeswehack.com

www.yeswehack.com

labs.detectify.com

developer.chrome.com


Memory

DevTools にある「メモリ機能」は、ブラウザに読み込まれた Web ページ全体の実行時間やメモリ使用量などの情報を収集することができます。

主に「Heap snapshot」を利用することで、スナップショットを取得して Web アプリケーションの JavaScript ファイル内のエンドポイントやシークレット情報を列挙することができます。

利用方法

  1. DevTools から Memory タブを開く
  2. Select profiling type から「Heap snapshot」を選択して、「Take snapshot」をからスナップショットを取得する
  3. スナップショットが完了したら、検索バー(ctrl+f)を開く
  4. ここで検索する条件を指定することで、条件のもとにエンドポイントや特定の文字列を列挙することができます。(例: /api)


Network

DevTools にある「ネットワーク機能」は、ブラウザに読み込まれた Web ページ全体のファイルを収集することができます。

Network タブから、主にフィルターで JavaScript ファイルのみに抽出したり、JavaScript ファイル内にある特定の関数を列挙することもできます。(例: innerHTML)


Lighthouse

DevTools にある「パフォーマンス測定機能」は、ブラウザに読み込まれた Web ページ全体のセキュリティ問題を検出することができます。

例として、主に以下のような点をベストプラクティスとして検出してくれます。

利用方法

  1. DevTools から Lighthouse タブを開く
  2. Device を「Desktop」を選択して、Categoriesを「Best practices」を選択する
  3. 「Analyze page load」で測定する
  4. 測定が完了したら、読み込まれたページに関する情報が閲覧できる

developer.chrome.com


おすすめ動画

  • Hacker101 - JavaScript for Hackers (Created by @STOKfredrik)

www.youtube.com

  • Improve Your Hacking Skills Using Devtools | Bug Bounty Tips

www.youtube.com

www.youtube.com


4. その他

JS Analyze に使える Burp の機能

Copy URLs

Burp Suite を利用して Web アプリケーションをある程度クロールした後に、デフォルトの機能である Proxy タブから JavaScript ファイルの URL を列挙することができます。

  1. Proxy タブの HTTP history タブを開く
  2. Filter setting にある「Filter by file extension」の「Show only」をチェックして、欄に「js」を指定して、Apply から設定します。

  3. HTTP history タブのリクエストが JavaScript のファイルのみになった後に、リクエストを全て選択して、右クリックして「Copy URLs」から URL をコピーします。

  4. コピーした URL リストをローカルのテキストにペーストして保存します。

    $ cat urls.txt          
    http://localhost/103.js
    http://localhost/103.js
    http://localhost/103.js
    http://localhost/main.js
    http://localhost/vendor.js
    http://localhost/runtime.js
    http://localhost/polyfills.js
    http://localhost/vendor.js
    http://localhost/vendor.js
    http://localhost/main.js
    http://localhost/main.js
    http://localhost/polyfills.js
    http://localhost/polyfills.js
    http://localhost/runtime.js
    http://localhost/runtime.js
    http://localhost/vendor.js
    http://localhost/main.js
    http://localhost/runtime.js
    http://localhost/polyfills.js
    
  5. コピーしたままでは、重複した URL がそのままあるため、sort コマンドで並び替えと重複を排除して、ツールによる静的解析ができる JavaScript ファイルの URL 一覧を作成します。(完成)

$ cat urls.txt | sort -u > urls-js.txt

$ cat urls-js.txt 
http://localhost/103.js
http://localhost/main.js
http://localhost/polyfills.js
http://localhost/runtime.js
http://localhost/vendor.js


DOM Invader

DOM Invader は、Burp の内蔵ブラウザで利用できる機能で、DOM を解析して JavaScript のソースとシンクをツリービューで表示することができます。

また、DOM Based の Reflected XSS や Prototype Pollution などの脆弱性を検証することもできます。

  1. Proxy タブの Intercept タブを開く
  2. 「Open browser」から Burp の内蔵ブラウザを開く
  3. 右上のブラウザの拡張機能にある「DOM Invader」から「DOM Invader is on」を有効にする
  4. Devtools から「DOM Invader タブ」を開いて確認することができる

portswigger.net

portswigger.net


Find scripts (Pro)

Find scripts は、Burp Suite の Professional 版でのみ利用することができる機能で、JavaScript ファイルの全てのスクリプトをエクスポートすることができます。

方法としては、 Target タブにある Site map から特定のドメインを指定して、Engagement tools にある Find scripts を利用することで、そのドメインにある全ての JavaScript のファイルを一括でダウンロード(Export)することが可能です。

portswigger.net


JS Link Finder は、Burp Suite の Professional 版でのみ利用することができる拡張機能で、クロールしたレスポンスから JavaScript ファイルを自動でスキャンして、JavaScript ファイルの URL とエンドポイントを Burp JS LinkFinde タブから表示することができます。

また、Dashboard タブにある Issue activity 欄にも随時検出したエンドポイントを表示してくれます。

portswigger.net


[Ex] JS Miner (Pro)

JS Miner は、Burp Suite の Professional 版でのみ利用することができる拡張機能で、クロールで見つかった静的ファイルから認証情報やサブドメイン、エンドポイントなどを自動で検出することができます。

主に JavaScript ファイルや JSON ファイルなどの静的ファイル内を解析して、検出したら Dashboard タブにある Issue activity 欄に随時表示してくれます。

portswigger.net


[Ex] Retire.js (Pro)

Retire.js は、Burp Suite の Professional 版でのみ利用することができる拡張機能で、クロールで見つかった JavaScript ファイルから使われているライブラリやフレームワークに存在する潜在的脆弱性を自動で検出することができます。

検出されたら、 Dashboard タブにある Issue activity 欄に随時表示してくれます。

portswigger.net


keyhacks・secrets-patterns-db

keyhacks は、漏洩して取得した API Key が有効なものがどうかを簡単にチェックする方法を示すリポジトリ(ドキュメント)です。

もし、取得した API Key があれば、ここから有効性を確認して、詳細は各 API の公式ドキュメントを確認するようにしてください。

github.com

また、secrets-patterns-db は、API Key やトークンなどの機微な情報に関する内容を、正規表現でまとめたリポジトリ(ドキュメント)です。

これを参考に、jsluice などで独自の Config を作成して、JavaScript のファイルからシークレット情報を検出できるようにすると、良いと思います。

github.com


JavaScript の難読化・軽量化

取得した JavaScript ファイルが難読化(Obfuscation)や軽量化(Minify)されている場合があります。

そのままでは、コードが読みにくい状態のため、js-beautify やオンラインの beautifier.io などを活用すると良いと思います。

github.com

github.com

また、React などで生成されるソースマップファイル(.map)で、ソースコードの最後の方に「sourceMappingURL」としてファイル名が記載されている場合があります。(以下、例)

//#sourceMappingURL=main.2b0f621f.chunk.js.map

ソースマップファイルを直接ダウンロードしたり、「unwebpack-sourcemap」などを用いることで、簡単にフロントエンドのコードをダウンロードすることができます。

github.com

github.com

github.com

ちなみに、ソースマップファイルを ffuf などを用いてファジングで探す場合もあります。(以下、例)

$ ffuf -w js_files_path.txt -u https://<Domain>/FUZZ -mr "sourceMappingURL"


バグバウンティ入門(始め方)

バグバウンティの始め方については、以下のブログで紹介しているため、よければこちらもご覧ください。

scgajge12.hatenablog.com


参考ドキュメント

kathanp19.medium.com

anithaana3.medium.com

medium.com

infosecwriteups.com

gowthams.gitbook.io

medium.com

bitthebyte.medium.com

book.hacktricks.xyz


5. 終わりに

本稿では、バグバウンティなどの脆弱性調査で行う、JavaScript の静的解析と動的解析についてまとめて紹介しました。

ぜひ、好みのツールを使って JavaScript ファイルの解析したり、対象の情報収集などをしてみてください。

ここまでお読みいただきありがとうございました。