サイト内の現在位置

トレーニングコンテンツ:脆弱なウェブアプリケーション「VulnerableAPP」のご紹介

NECセキュリティブログ

2022年5月20日

NECサイバーセキュリティ戦略統括部セキュリティ技術センターの中島健児です。本記事では、ウェブアプリケーションの脆弱性によるセキュリティ上の問題を体験可能な学習コンテンツ「VulnerableAPP」をご紹介します。

VulnerableAPPとは

VulnerableAPP new window[1]は、OWASPのIncubator Project new window[2]で開発段階に位置づけられるツールです。本ツールは、Java、Spring Boot等を使用して作成された脆弱なウェブアプリケーションで、 Apache 2.0ライセンスで公開されています。本ツールは、セキュリティ診断ツールのパフォーマンスをテストする際の実行対象として使用できるウェブアプリケーションを目指して開発されています。この目的のためにあらかじめ10種類の脆弱性が盛り込んで作られており、ツールの評価だけではなくウェブアプリケーションを作成する開発者やセキュリティ技術者が、セキュリティについて学ぶことができる学習用コンテンツとなっています。

VulnerableAPPには、以下の10種類の脆弱性が含まれています。

  • JWT Vulnerability
  • Command Injection
  • File Upload Vulnerability
  • Path Traversal Vulnerability
  • SQL Injection
  • XSS
  • XXE
  • Open Redirect
  • Remote File Inclusion
  • SSRF

VulnerableAPPのセットアップ

GitHubのREADMEページでは、2通りのセットアップ方法が記載されています。今回は、容易に準備が可能なDocker-composeで立ち上げる方法 new window[3]を紹介します。詳しくはREADMEをご確認ください。

  1. 以下のページのdocker-compose.ymlを作業ディレクトリにダウンロードします。
    new windowhttps://github.com/SasanLabs/VulnerableApp-facade/blob/main/docker-compose.yml
  2. docker-compose.ymlファイルが存在するディレクトリにてdocker-compose upを実行します。
  3. ブラウザでhttp://<ipaddress>にアクセスし、トップページを表示可能で正常に動作していることを確認します。

VulnerableAPPに挑戦

VulnerableAPPでは10種類の脆弱性が用意されています。本記事では、その内の2種類 Command InjectionとSSRFに挑戦してみます。なお本記事ではVulnerableAPPの脆弱性調査にBurpSuite Professional v2022.3.6 new window[4]を使用しています。

1. Command Injection

Command Injectionの課題は以下の画像のように、Level 1から6までの6問が用意されています。Level1から5までは開錠された状態の鍵アイコン、Level6では施錠された状態の鍵アイコンとなっています。これら鍵アイコンの意味の説明は明記されていませんが、鍵が開いている課題は脆弱性が含まれており、鍵が締まっている課題は脆弱性の対策が部分的に施されているという意味であると考えられます。VulnerableAPPでは、このように複数のLevelが用意されている脆弱性があり、最初は容易に悪用可能ですが段階的に悪用が難しくなります。

それでは、各Levelの課題に挑戦します。

Level 1に挑戦

まずは、通常の動作を確認します。pingを実行できる機能ということですので、試しにlocalhostと入力して実行します。サーバー上でPingコマンドが実行されていることがわかります。

続いて、Command Injectionという題名の通り、コマンドインジェクションを試します。
セミコロンとidコマンド”;id”をlocalhostの後に入力して実行します。Pingコマンドに続いてidコマンドが実行されていることを確認できます。

Level 2に挑戦

Level2では、1で実行できたセミコロンを使用する手法は対策され結果が返ってきません。別の手法を使う必要があります。&や;をURLエンコードした”%26”や”%3B”を使用して対策を回避します。

Level 3に挑戦

Level2で使用した”%3B”は対策されていました。そこで小文字に変えた”%3b”を使用して再度対策を回避します。

Level 4に挑戦

Level3までの文字列が使用できないため、新たに別の文字列で挑戦します。バーティカルバー”|”をURLエンコードした”%7C”もしくは”%7c”を使用すると対策を回避できました。

Level 5に挑戦

Level5でも同様に前段までの文字列は対策されているため別の文字列を使用します。改行コードである、”%0A”もしくは”%0a”を使用して対策を回避できました。

Level 6に挑戦

Level6は、施錠された鍵アイコンとなっており、前述の通り対策が施されている課題ですのでスキップします。Level1~5で使用した手法が使用できないことを確認できます。

2. SSRF

SSRFとは、Server-Side Request Forgeryの略で、ウェブアプリケーションがリソース(別サイトやファイル)を取得する際に、ユーザーから提供された値を検証せずに使用することで発生する脆弱性です。 new window[5] VulnerableAPPは、セキュリティ診断ツールのテスト用途を主眼においているということで、後半はSSRF攻撃のファジングツールであるSSRFmap new window[6]を使用してSSRFの課題を攻略します。

まずは、通常の動作を確認します。”Here you can give us a link and we will put your image down below!”とあることから、画像のリンクを与えることでページ内に画像を表示する機能があるようです。
この機能を試すために準備します。VulnerableAPPと別のVM(192.168.93.128)上に画像を配置し簡易ウェブサーバーを建てて画像をホストします。
入力欄に「http://192.168.93.128/ssrf_test_1.png」と入れて”Show Image”をクリックします。以下のように、画像をページ内に表示できることを確認できます。

続いて、 OWASPのSSRF解説ページ(以下のURL)に記載されたシナリオ#2のSensitive data exposureを実施します。
new windowhttps://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_(SSRF)/

入力欄に「file:///etc/passwd」を入力後、”Show Image”をクリックします。以下のようにVulnerableAPPをホストしているサーバー上の/etc/passwdファイルを読み込める脆弱性を確認できます。

さて、 SSRF攻撃のファジングツールSSRFmapを使用して同様の攻撃を試します。SSRFmapはGitHubのREADMEを参考にあらかじめインストールします。SSRFmapは、サンプルとなるリクエストをファイルに保存してSSRFmapに引数で渡す必要があります。BurpSuiteに記録されたリクエスト内容をそのままサンプルリクエストとして使用します。SSRFVulnerablityページの通常のリクエストをBurpSuite上で記録し、そのリクエストの内容を vulapp-ssrf-req.txt という名前のテキストファイルとして保存しました。以下のような内容になります。

$ cat vulapp-ssrf-req.txt
GET /VulnerableApp/SSRFVulnerability/LEVEL_1?imageurl=aaa HTTP/1.1
Host: 192.168.93.130
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0
Accept: */*
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Connection: close
Referer: http://192.168.93.130/

それでは、SSRFmapを実行します。

python ssrfmap.py -r vulapp-ssrf-req.txt -p imageurl -m readfiles --proxy http://localhost:28080

SSRFmapのオプションを簡単に説明します。詳細はREADMEもしくは—helpオプションを実行して確認できます。

-rでリクエストのサンプルを選択
-pでFuzzの対象とするパラメータを選択
-mで実行するモジュールを選択
--proxyでプロキシを指定

モジュールは、”readfiles”を使用します。--proxyはSSRFmapの挙動をBurpSuiteで記録するために設定しましたが、通常は不要です。

私の環境では、SSRFmapが実行途中にエラーで終了しました。原因を調べたところSSRFmapは、リクエストのtimeout時間を3秒で指定しているものの、timeout時間よりレスポンスが遅くなった場合の処理が適切に行われていませんでした。SSRFの課題では、パラメータ値によってはレスポンスが返るまでの時間が長くなる場合があることをBurpSuiteのログから確認できました。そのため、暫定対処として SSRFmapのソースコードを変更しました。core/requester.pyファイルの76行目のdo_request関数のtimeoutの値を3から10へと変更しました。変更後はエラーになることなく最後までSSRFmapを実行できました。

さて、SSRFmapの結果を確認すると以下のパラメータで成功していました。

  • file%3A%2F%2F%2Fetc%2Fpasswd
  • file%3A%2F%2F%2Fetc%2Fshadow
  • file%3A%2F%2F%2Fetc%2Fhosts
  • file%3A%2F%2F%2Fproc%2Fself%2Fenviron
  • file%3A%2F%2F%2Fproc%2Fself%2Fcmdline
  • file%3A%2F%2F%2Fproc%2Fself%2Fexe

ここでは、成功したリクエストの内1件目の結果を紹介します。以下の画像はBurpSuite上でSSRFmapのリクエストをキャプチャした様子です。SSRFmapがimageurlに「file:///etc/passwd」をURLエンコードした値である「file%3A%2F%2F%2Fetc%2Fpasswd」をセットしてリクエストしています(画像左側部分)。VulnerableAPPから”content”にBase64でエンコードされた文字列が返されたレスポンスを確認できます(画像中央部分)。”content”の内容をデコードすると、VulnerableAPPが動作するサーバー上の/etc/passwの内容であることを確認できます(画像右側部分)。

おわりに

本記事では、Javaベースのウェブアプリケーションにあらかじめ脆弱性を盛り込んで作られた学習用コンテンツVulnerableAPPを紹介しました。本コンテンツでは、学習の難易度に応じて脆弱性が用意されています。前段では成功していた攻撃が次の課題では通用しないため、難易度が上がるに連れて段階的に攻撃を工夫していく必要があるという体験ができます。注意点を挙げると、本コンテンツは公式のWalkthroughがないことや、あまり知名度がないためかユーザーによる回答例が見つからないため、どのように攻略すればよいのかわからないということが起こりえます。GitHubページや手元にgit cloneすることでソースコードを閲覧可能ですので、コードから攻略方法を見つけ出すというのも面白いかもしれません。また、課題ごとにどのような対策をとっているのか確認することができますし、不適切なコーディングパターンを学習するための参考になると思います。本コンテンツは、セキュリティ診断ツールのパフォーマンスをテストする際の実行対象となることを目標に開発されています。この切り口で開発が進められている脆弱なウェブアプリケーションは珍しいと思います。また、後から課題を追加しやすいように拡張可能なように作成しているということで、今後の脆弱性の種類追加やバグ修正等コンテンツの完成度の向上が期待されます。Javaベースのウェブアプリケーションの学習コンテンツを探している方、他の学習コンテンツを既に実施済みの方、セキュリティ診断ツールのテストをしたい方はぜひ本ツールに取り組んでみてください。

参考情報

執筆者プロフィール

中島 健児(なかしま けんじ)
セキュリティ技術センター リスクハンティング・アナリシスグループ

NECがお客様へ納品するシステム・製品へのリスクアセスメント/脆弱性検査/ペネトレーションテストを通じて、安全・安心なシステム構築を支援する業務に従事
CISSP Associate、情報処理安全確保支援士(RISS)、GCPN保持

執筆者の他の記事を読む

アクセスランキング