脆弱なWAF達で遊んでみた

最近、二つの脆弱なWAFが公開されました!

Vurp - Vulnerable Reverse Proxy: https://github.com/hasegawayosuke/vurp
ViddlerProxy: https://int21h.jp/tools/ViddlerProxy/

今回は巷(ごく一部かな?w)で話題のこの脆弱なWAF達で遊んでみたら非常に面白かったので、このブログでちょっとご紹介したいと思います。

脆弱なWAFとは?

そもそも、「脆弱なWAF」とは一体なんなのでしょうか?一般的なWAF(Web Application Firewall)は、Webサイトの脆弱性を悪用した攻撃から、Webサイトを保護するためのセキュリティ対策の一つです。 通常は守りたいWebサイトの通信経路上の前面に配置するような構成をとります。例えWebサイトに脆弱性が存在したとしても、前面のWAFにて攻撃をブロックできれば、Webサイトは攻撃を受けないため、導入することでセキュリティレベルの向上が期待できるわけです。

しかしながら、はせがわようすけさんが考案した脆弱なWAFについては上記とは全く真逆のコンセプトのもので、このWAFを経由してアクセスすることで、安全な作りのWebサイトであっても、脆弱なWebサイトに早変わりしてしまうというものになります。この時点で個人的には超面白い発想だなあと思いましたw ではこの脆弱なWAFを使うと、実際どんなことになるのか見てみましょう。

対象のWebサイトとして分かりやすいように適当なWordPressのサイトを用意してみました。

f:id:tigerszk:20170408150331j:plain:w700

適当なWordPressサイト

このWordpressの検索フォームに「"><script>alert("XSS")</script>」のようなスクリプトタグを入力した場合には、遷移後の画面ではXSSの対策のため入力値がHTMLエスケープされた状態にて出力されます。そのため当然スクリプトは動作しません。

f:id:tigerszk:20170408150721j:plain:w700

スクリプトタグを挿入した結果(そのままアクセスした場合)

f:id:tigerszk:20170408150727j:plain:w700

結果のソース(そのままアクセスした場合)

では、脆弱なWAFを経由した状態で、このサイトに同様の入力値を送信した場合にはどうなるでしょうか。

f:id:tigerszk:20170408151109j:plain:w700

スクリプトタグを挿入した結果(脆弱なWAFを経由した場合)

f:id:tigerszk:20170408151512j:plain:w700

結果のソース(脆弱なWAFを経由した場合)

なんと、先ほどは何も起こらなかったWebサイトにて、XSS脆弱性が発現し、alertが上がっています。 ソースを見ると先ほどはHTMLエスケープされていたはずの値が、入力されたスクリプトタグの値をそのまま出力されている状態になっていることが確認できます。

もうお分かりですよね?途中に挟まっている脆弱なWAFが、HTMLエスケープした値をわざわざHTMLエスケープ前の状態に変換してユーザ側に返しているのです。 これによって本来はちゃんとXSS対策されているサイトにもかかわらず、このWAFを経由することで、バンバンXSSが発現してしまう状態になってしまうわけです。

このように入力した値に応じて、いかにも脆弱性が存在するような挙動を返すことで、本来は安全なWebサイトなのにもかかわらず、ユーザからは脆弱性が存在するサイトに見えさせてしまうものが脆弱なWAFなわけです。 面白いですよね!

Vurpをためしてみた

ということで、はせがわようすけさんが公開されたVurpを早速試してみました。

VurpはNode.jsにて作成されているプログラムで、リバースプロキシとして動作をします。 実行にはNode.jsの実行環境といくつかモジュールのインストールが必要なようです。

CentOS 7では以下の手順で実行できました。

sudo yum install epel-release
sudo yum install nodejs npm
sudo npm install connect
sudo npm install http-proxy
sudo npm install set-cookie-parser
sudo npm install cookie
sudo npm install replacestream
sudo npm install commander
git clone https://github.com/hasegawayosuke/vurp
cd vurp/src/
sudo node main.js

readmeに詳しく記載されていますが、基本的には「config.js」というコンフィグファイルを編集して、Vurpを起動しているホストのURL、対象とするWebサイトのURL、脆弱性を発現する箇所の情報(URLやパラメータなど)を指定してあげる必要があります。
https://github.com/hasegawayosuke/vurp/blob/master/readme.md

コンフィグ設定後に指定したVurpを起動しているホストのURLにアクセスすれば利用できます。

現時点では以下の脆弱性に対応しているようです。

  • セキュリティのためのヘッダの削除
  • 任意ページへのクロスサイトスクリプティングの埋め込み
  • 推測可能なセッションIDへの振り替え
  • OSコマンドインジェクション

先ほどのようにパラメータを指定することで様々な箇所でXSSを実行できるのが面白いです。 XSS以外にも、OSコマンドインジェクションに対応されていたのに興味を持って、色々試していたのですが、入力したOSコマンドがVurpが動作しているホスト上で実行されるというものでした。 試している中で、「|sleep 10」とかを入力した場合でも速攻でレスポンスが返ってきたため、一瞬「アレ?」となったのですが、現時点ですと、挿入したOSコマンドの処理結果を含まずに、そのまますぐに対象サイトのレスポンスを返す仕様のようです。WAF側のプロセスを確認したらちゃんと挿入したOSコマンドは実行されていました。連続アクセスしたので沢山sleepコマンドが実行されていますw

f:id:tigerszk:20170408152446j:plain

Vurpが動作するホスト側でsleepコマンドが実行されている

ViddlerProxyをためしてみた

つづいてVurpにインスパイアされて、山崎圭吾さんが公開した「ViddlerProxy」も試してみました。 こちらについてはWindowsバイナリを配布されており、実行には.NET Framework 4.5が必要とのことです。 Vurpと同様にリバースプロキシとして動作をするようです。

現時点で、対応している脆弱性項目は以下のようです。

  • Cross Site Scripting (parameters, 501 error page, 404 error page)
  • SQL Injection (string, numeric)
  • OS Command Injection (with cmd.exe, with busybox-w32)
  • Path Traversal / Directory Traversal
  • Cross-Site Request Forgery (CSRF)
  • Use of Insufficiently Random Values (Simplify SessionId Cookie Values)
  • Cookie without HttpOnly Attribute
  • Cookie in HTTPS Session without Secure Attribute
  • HTTP TRACE/TRACK Method Enabled
  • HTTP PUT/DELETE Method Enabled
  • Clickjacking (X-Frame-Options Header Missing)
  • X-Content-Type-Options Header Missing
  • Strict-Transport-Security Header Missing
  • Information Exposure Through Directory Listing

こちらはVurpの脆弱性項目に追加して、さらにいくつか脆弱性項目に対応されているようですね。 そしてこのProxyはHTTPS通信にも対応しています。

ダウンロードしてきたzipファイルを解凍後にViddlerProxy.exeを実行すると以下のようなGUIが立ち上がります。

f:id:tigerszk:20170408175935j:plain

起動したViddlerProxy

後は、Parent Serverに対象とするWebサイトのURLとポート番号を入力してListensボタンを押すだけです。 hostsも自動的に書き換えてくれるらしく「http://viddler-vulnerable.example.jp」に自動的に遷移します。 非常にお手軽ですね!

脆弱性のパラメータなどに関する設定は「settings」タブで指定するようです。

このViddlerProxyはSQLインジェクションに対応しており、入力するSQL構文の内容による応答差分なども再現してくれています。 例えば以下のようなパラメータ値を送信すると以下のような応答結果になりました。

name=test' ⇒ 500 error
name=test' and ‘a’=‘a(構文が真となる場合) ⇒ 正常応答
name=test’ and ‘a’=‘b(構文が偽となる場合)⇒ ボディが空の200応答

パラメータ値の型(文字列型、数値型)も指定できるようです。

ディレクトリトラバーサルではフォルダの中に配置されている、「root」のディレクトリ以下のファイルを表示させる仕組みになっているみたいですね。Windows環境においても適切なファイルパスを渡せば「/etc/passwd」を表示させることも可能となっています。

OSコマンドインジェクションはViddlerProxyを実行しているWindowsホスト側でコマンドが実行され、コマンド実行結果もレスポンスに反映されるようですね。また、busyboxを利用することでWindows環境にて、Linuxコマンドも実行できるようにされているようです。以下のような感じでコマンドを実行できました。

cmd.exe経由の場合: oscmd=“;netstat -n;”
busybox経由の場合: oscmd=‘;uname -a;’

その他にも、強制的にPUT/DELETEメソッドを有効化させて、実際に使えてファイルを置いたり消したりすることなどができましたし、/icons/フォルダを指定するれば中身がちゃんと表示されるようになっていたり、色々な仕掛けが面白かったですw

まとめ

脆弱なWAF達と戯れて面白かったですw

脆弱性が存在するサイトを自分で実装とか構築することも色々勉強になると思いますが、とりあえずまずお手軽にWebアプリの脆弱性を体験するのであれば、非常にもってこいなツールなのではないでしょうか。あとは、脆弱性によってはHTTPヘッダインジェクションみたいにフレームワークミドルウェア側で対策されているため、脆弱性を作りこむのがちょっと面倒くさいものとかもあったりしますので、そういうのを再現する場合にはこのような形式の方が、お手軽なのかもしれないですね。また、疑似的に脆弱性を再現しているので、ハニーポットなどにも使えるのではないかなという印象を持ちました。

今後の機能追加などが楽しみです!

Apache Struts2の脆弱性(CVE-2017-5638)を検証してみた

Blogでもやろうかなと思いつつ、やるやる詐欺になっていたし、たまたま朝早く目が覚めたので思い切って始めることにしました。このBlogでは私が趣味でチョコチョコやっている脆弱性やスキャナの検証などについて書いていこうと思います。

さて、話題となっている以下Struts2脆弱性を昨日検証しました。

S2-045 - Apache Struts 2 Documentation - Apache Software Foundation

上記に記載がありますが、リモートから任意のコマンドが実行可能な脆弱性であり、影響範囲は Struts 2.3.5 - 2.3.31及び2.5 - 2.5.10だそうです。
また、既に複数サイトにてPoCが公開されているようです。

Struts脆弱性については定期的にみつかっているので、以前に試した検証用の環境などをすでにお持ちの方も多いと思われますが、dockerを利用すれば簡単に作成できます。
以下の記事にてdockerを利用したStruts2の検証環境の構築方法を解説されていますので、非常に参考になると思います。

Dockerを使って、Apache Struts2の脆弱性S2-037のやられ環境を手軽に作る - DARK MATTER

今回私もdocker環境を用いて検証してみました。

https://dist.apache.org/repos/dist/release/struts/2.3.31/

上記サイトよりstruts-2.3.31-apps.zipをダウンロードして以下のようなDokcerfileを作成しました。

FROM tomcat:7.0-jre8
ADD struts-2.3.31/apps/struts2-blank.war /usr/local/tomcat/webapps/
CMD ["catalina.sh", "run"]

docker環境でビルドして実行すればサクッと検証環境は出来上がります。

f:id:tigerszk:20170308062627j:plain

後はPoCを検証するだけの簡単なお仕事です。

以下では分かりやすくBurp Suiteを利用して攻撃のHTTPリクエストを送信しています。
PoCの中身を見ればすぐにわかりますが、内容としてはContent-Typeヘッダに細工したOGNLを指定してブン投げてるだけの非常にシンプルなものです。
あまりにもあっさり刺さったので、検証していてビックリしました。

攻撃が成功し、リモートからOSコマンドが実行されて、/etc/passwdの内容がレスポンス中に出力されています。

f:id:tigerszk:20170308061125j:plain
ちなみに本脆弱性が修正されているStruts 2.3.32 と 2.5.10.1はもう既にリリースされているようです。
https://dist.apache.org/repos/dist/release/struts/

同じくdocker環境を利用して修正版についても検証してみましたが、最新版の環境ではPoCの攻撃が刺さらないことを確認しました。Dokcerfile書き換えるだけなのでこういう時にもお手軽ですね。

後は、Struts脆弱性で大体話題になるのは1系への影響ですが、今回の脆弱性はOGNLを利用しているので、OGNLをサポートしていないStruts 1系には影響がないんじゃないかと推測しています。

そして、案の定早速攻撃が観測されているようですので、早急にアップデートなどの対策をされた方がよいでしょう。

Strutsは相変わらず定期的にポンポン割と影響度の高い脆弱性が報告されるので、サービスで利用されている場合はWAFなどを導入したほうが費用対効果的にも良い気がしますね。運用されている方もその方が多少気が楽になるのではないかなと思いました。

またこの記事を書いている途中に気づいたのですが、すでにpiyokangoさんが本件の詳細をまとめてくださってますね。

Struts2の脆弱性 CVE-2017-5638 (S2-045)についてまとめてみた - piyolog