デバッガを利用してWebアプリの脆弱性を分析してみた

11/15に開催されたこちらの勉強会に参加いたしました!

デバッガでWordPress本体やプラグインの脆弱性を追いかけてみよう - connpass

こちらの勉強会は、「WordPress本体とプラグイン脆弱性をデバッガで追跡することにより、脆弱性の中身について詳しく追跡し、理解を深める」という内容のものであり、なんとあの徳丸浩さんが講師をされています!
私個人としては、仕事というか半分趣味でゆるゆる脆弱性の検証をしており、今回の勉強会はまさに自分の興味分野にドンピシャな内容だったので、非常に楽しんで参加させていただきましたw
私はこちらの勉強会にブログ枠として参加いたしましたので、勉強会の内容について本ブログにてレポートいたします。

分析対象の脆弱性について

今回分析する題材となった脆弱性は以下の二つです。 なお、二つの脆弱性とも徳丸さんが詳細な解説記事をブログにて公開されております。

脆弱性分析のやり方

勉強会の冒頭にて徳丸さんより以下のような脆弱性分析のhow-toに関するお話しがありました。

脆弱性情報はどこにあるのか?

WordPressCMS脆弱性であれば米セキュリティ会社Sucuri社のブログがおススメ!
https://blog.sucuri.net/

正し、Sucuri社のブログは、書いてある内容はすごいけど、説明がちょっと不親切である(意図的にぼかしている?)。
そのため、読んだだけでの完全理解は難しいので、自分で検証する必要があるとのことです。

脆弱性分析の手法

脆弱性を分析する方法には以下の3種類がある(複数組み合わせてやっても勿論OK!) 。

  1. 脆弱性の解説記事を読む
  2. ソースコードの差分をとり中身を見る(静的解析)
  3. PoC(Proof of Concept)を試して動作を分析する(動的解析)

2番の手法については、差分に脆弱性だけではなくて他の修正内容も含まれていることもあり、複雑なアプリケーションの場合などでは差分のコードを読んでもよく分からない場合が多いとのこと。
3番の方法は比較的楽な方法である。

今回の勉強会では、上記3番の方法をデバッガを利用して分析してみるという感じです。
勉強会の冒頭にて、徳丸さんが脆弱性の内容を調べるモチベーションやブログとして公開する楽しさについてもお話しされていましたが、自分も非常に共感する部分がありました。
やっぱ脆弱性を検証するのって楽しいですよねw

脆弱性分析をするための環境について

WordPressプラグインPHPを利用して作成されているので、動作を分析するために、PHPアプリをリモートデバッグできる環境を用意します。
リモートデバッグ可能なIDEは複数ありますが、勉強会ではNetBeans 8.2+ Xdebugを使用していました。

なお、今回の勉強会の参加者には分析対象のVMデータを配布いただきました。
今回の僕の記事もいただいた環境を利用して書かせていただいております。
いただいた環境はUbuntuで構築されており、脆弱なWordPressと脆弱なプラグインデータなどがセットアップされていました。
また、Xdebugもインストールされており、こちらの環境を利用すれば、すぐにリモートデバッグして検証ができるようになっているので非常にありがたかったです。
余談ですが、実は勉強会に参加する前の予習として自分でもリモートデバッグできる環境をCENTOSで作成してみたのですが、ちょっと面倒くさかったです。
Ubuntu等で作成するとapt-get一発でインスコできるみたいなので、後ほど自分でももう一回環境を作ってみようと思います。
なお、Xdebugを利用する際には、php.ini(あるいはconf.d/xdebug.ini 等)に設定情報を記載する必要があり、NetBeansを起動してリモートデバッグを行うホスト側の情報に合わせる必要があります。

リモートデバッグをする準備

NetBeansの初期設定

まずはNetBeansを起動して、VMサーバ側にSSH経由にて、リモートデバッグをできるように設定する必要があります。

1.NetBeansを起動して、メニューから[ファイル][新規プロジェクト]を選択

f:id:tigerszk:20171116210733j:plain

2.プロジェクトを選択において「リモートサーバーからのPHPアプリケーション」を選択して「次>」を押す

f:id:tigerszk:20171116212212j:plain

3.「プロジェクト名」・「ソースフォルダのパス」・「PHPのバージョン」を適当に設定して「次>」を押す

f:id:tigerszk:20171116212336j:plain

4.リモート接続が定義されていないので、「管理」のボタンを押す

f:id:tigerszk:20171116211052j:plain

5.新規接続を作成します。接続名は適当に入力して、接続型は「SFTP」に設定して「OK」を押す

f:id:tigerszk:20171116211242j:plain

6.リモート接続の部分については接続したい先のホストに合わせた情報を入力して「OK」を押す
※画像ではいただいたVMデータの情報を設定しています。事前にNetBeansを動作させているホスト側のhostsファイルを編集していたりもしています。

f:id:tigerszk:20171116211424j:plain

7.プロジェクトURL・アップロードディレクトリを適切に設定して「次>」を押す
※プロジェクトURLはブラウザでアクセス可能なURLを入力、アップロードディレクトリは、検証するコンテンツが配置してある公開ディレクトリのパスとなるように指定する。

f:id:tigerszk:20171116212932j:plain

8.ディレクトリ・ファイルを選んで終了を押すとダウンロードが始まります。
※ここではWordPressのコンテンツを丸ごと選択しています。

f:id:tigerszk:20171116212958j:plain

9.ダウンロードが完了すれば、リモートデバッグできる状態となります。

f:id:tigerszk:20171116213213j:plain

リモートデバッグのやり方

NetBeansの上部の「プロジェクトをデバッグ」のボタンを押すと、デバッグ・セッションが実行され、以下のようなボタンが表示されます。

f:id:tigerszk:20171116221725p:plain

後はお好みの場所にブレークポイント(実行中のプログラムを意図的に一時停止させる箇所)を設定して、こちらのボタンを操作すれば、デバッグをすることができます。
NetBeansでは、エディタにて設定したい行の左マージンをクリックすれば、簡単にブレークポイントを設定できます。
なお、NetBeansでのデバッグについて、ちょっと調べてみたら以下などに細かく解説がありました。

PHP向けのNetBeans IDEのエディタでのPHPソース・コードのデバッグ

脆弱性の分析について

脆弱性の分析については以下の手順で行います。

  1. まず、ブログなどの一次情報などを元に、脆弱性に関係がありそうな関数などにブレークポイントを設定する
  2. デバッガを動かしている状態で、WebアプリケーションにPoCを打ちこんでみる
  3. ブレークポイントを設定した箇所やその周辺にて、関連するような変数の値が内部でどのように処理されているのかをひたすら追って挙動をみていく。

ものすごいザックリとした説明ですが、上記の手順で追跡をしていくわけです。
正常に機能を利用した場合の処理内容と、PoCを打ち込んだ場合の処理結果に、どのような差分があるのかなどを比較したりするのも有効なのかなと思いました。

WordPress REST API脆弱性の検証

こちらは分析初級編というお話しでした。

脆弱性については非常に話題になったので、ご記憶にある方も多いのではないでしょうか。
IPAやJPCERTなどからも注意喚起されていましたね。

WordPress の脆弱性対策について:IPA 独立行政法人 情報処理推進機構

再度リンクを張りますが、脆弱性に関する要因の詳細につきましては、まずこちらの徳丸さんの記事を良く読み込むのが一番良いと思います。

WordPress 4.7.1 の権限昇格脆弱性について検証した | 徳丸浩の日記

上記のブログにて脆弱性の要因について以下二点をご指摘されています。

  • 権限チェックの際に、存在しないid に対して、権限ありを返していた
  • 権限チェックの際はid キャストなし、データ更新の際はid を整数にキャストしていた

デバッガを利用してPoCを実行してやれば、上記のブログにて解説されている流れをそのまま体験できます。
update_item_permissions_checkメソッドとupdate_itemメソッドにブレークポイントを設定してステップ・オーバーなどで進めていけば、どのように値が処理されているのか良く分かります。

存在しないidなのに、返り値がtrueとなる f:id:tigerszk:20171117135927j:plain

整数にキャストされているためid=1xだったのがid=1として処理されている f:id:tigerszk:20171117140021j:plain

自分で試してみた感想としてですが、PoCのリクエストをid=1としてブン投げると正常処理の流れとなるので、そちらと比べるとより分かりやすいかもなと思いました。

WordPress NextGEN GalleryのSQLインジェクション脆弱性の検証

こちらは分析上級編という位置づけでした。

脆弱性WordPressのフォトギャラリープラグインSQLインジェクション脆弱性が存在するというものです。
WordPressフレームワークとして提供するwpdbクラスのprepareメソッドが、プレースホルダに用いている「%s」という値を外部由来文字列から内部のSQL文に受け渡してやるとそのままプレースホルダとして解釈されることを利用して、細工した値を送りこんでSQLインジェクションを発生させるという脆弱性だと認識しています。
こちらの脆弱性は上級編だけあってかなりトリッキーなものですね。

こちらについても、脆弱性に関する要因の詳細につきましても、まず徳丸さんの記事を良く読み込むのが一番良いと思います。

WordPressのプラグインNextGEN GalleryのSQLインジェクション脆弱性について検証した | 徳丸浩の日記

デバッガを利用すれば、ブログに書いてある「aaa%1$%s)) or 1=1#」という細工された値を受け渡した際に、内部にてどのように処理されるか確認することができます。

f:id:tigerszk:20171117163352j:plain

まとめ

自分は、今までWebアプリケーションの脆弱性を検証する際に、デバッガを利用したことがなかったので今回非常に勉強になりました。
脆弱性検証でもいくつかのフェーズがあり、脆弱性の再現確認は環境作るのがちょっと面倒くさいというのを除けば割と誰でもできるかなと思いますが、脆弱性が起こる原理解析などの部分がやっぱりなかなか難しいよなあと個人的に思います。
デバッガを用いた動的解析を利用すれば、原理解析の部分などが色々捗りそうだなという印象をもちました。
今回の環境を利用すれば、WordPressだけじゃなくて、Joomla!Drupalなどの検証もできそうなので次回の検証からは早速使ってみようかなと思っています。
後は、他の言語でのこういったリモートデバッグのやり方なども調べてみたいですね。

また、こちらの勉強会は同じ内容で追加開催されるとのことですので、ご興味がある方は参加されてみてはいかがでしょうか?
※好評につき追加開催※ デバッガでWordPress本体やプラグインの脆弱性を追いかけてみよう - connpass

AWSの侵入テスト申請フォームが変更された件

過去このブログでも取り上げてますが、AWSにおいて脆弱性診断を実施する際に、侵入テスト申請というものが必要となります。

ペネトレーションテスト(侵入テスト)- AWS セキュリティ|AWS

この侵入テスト申請について、実は2017年9月頃にアップデートがあり、申請フォームの内容が従来と変更されておりますので、こちらに変更点などをちょっとまとめておきます。 今後、侵入テストを申請される方の少しでもご参考になれば幸いです。

また、アカウントが無い方は申請フォームの中身を見ることができないので、キャプチャした現時点(2017年10月20日)の申請フォームの画像データもアップしておきます。

従来との変更点は?

従来との大きな変更点として、今まではEC2やRDSしか診断の対象とすることができなかったのですが、以下のマネージドサービスを正式に診断の対象とすることができるようになりました!

こちらにつきましては、診断を実施する側としても非常に大きな変更点だと思います。

CloudFront、APIゲートウェイ、Lambdaなどを利用して構築されているシステムなどには、個人的にも最近割と遭遇しており、今までは、公式にて診断対象とできないといわれていたので、どうやって診断などをしたものかなとちょっと悩んでいました。 また、原則としてはEC2やRDSしか診断できないはずだったのですが、知り合いの方などから「Lambdaを使っているんだけど申請したらなぜか通った」などのお話を聞いたことがあり、一体何がOKで、一体何がOUTなのか非常にグレーな感じだったので、ここら辺を明確化していただいたのは個人的には非常にありがたいです。

申請フォーム中のTarget Data、DNS Zone Walkingの項目がこの変更に対応してできた項目のようで、診断したいマネージドサービスごとに必要な内容を記載して申請できるようになっています。 ちなみに従来も診断可能だったELBも公式の診断対象として明記されており、ちゃんと専用の入力項目ができてますね。

その他、気になる変更点としてはTesting Detailsの所で、従来から入力が必要だったテスト時の帯域幅に追加して、秒間リクエスト数(RPS)の記入が必須となっております。 DNSを検査する場合には秒間問い合わせ数(QPS)なども申請しなくてはならないようです。

上記以外は、従来の申請とそこまで変わらない内容であると思います。

PS

ちなみにSource Dataの項目に 「Does the testing company have a NDS with AWS?」 と記載があり、初めはこの「NDS」について調べても良くわからなかったので謎だったのですが、知り合いの方よりどうやら「NDA」の記載ミスらしいというお話しを聞きましたw 一応私からもAWSに問い合わせておりますが、まだ正式なご回答いただいておりません。 ご回答があり次第こちらに追記しようかと思います。

(2017年10月21日追記)

AWSから以下のように丁寧なご回答をいただきました。

Thank you for contacting us. I sincerely apologize for the confusion, but this is an internal error on our side. We are aware of this error and will address it soon as possible. The request form should originally ask for an NDA (Non-Disclosure Agreement) rather than an NDS. This is, of course, not a requirement for the approval process.

誤記載ということが確定ですので、その内修正いただけるのだと思います。 このブログを公開してから、何人かの知り合いの方に「やっぱりみんなそれ問い合わせますよねーw」とかってご連絡をいただいたのがちょっと面白かったですw

申請フォームのキャプチャ

f:id:tigerszk:20171020124411p:plain

f:id:tigerszk:20171020124423p:plain

f:id:tigerszk:20171020124433p:plain

f:id:tigerszk:20171020124441p:plain

※2017年10月20日時点のものとなります。

僕が調べたApacheバージョン判定の小ネタ

皆さんこちらのブログをご覧になられましたでしょうか?

Apache HTTP Serverのバージョンを当てる方法 | MBSD Blog

Apache HTTP Serverのバージョンが秘匿されていたとしても、脆弱性の修正や、仕様変更による応答差分を確認することによって、バージョンを特定することができるよというMBSDさんの記事です。
この記事には私も知らなかったテクニックも載っていて非常に勉強になりました!

実際の脆弱性診断の現場でもこのようなテクニックは結構使われていまして、Apache HTTP Serverであればかなり古いですが他にも以下の二つの脆弱性なども脆弱性が修正されているかどうかによる応答差分で、バージョンの判定が可能だったかなーと記憶しています。

CVE-2006-3918
JVNDB-2006-000441 - JVN iPedia - 脆弱性対策情報データベース

CVE-2007-6203
JVNDB-2007-001017 - JVN iPedia - 脆弱性対策情報データベース

さて、MBSDさんのブログを読んでいて、そういえば私も以前たまたま見つけて、あんまり出回ってなかった(当時調べたんですがあんまり情報とかなかったと記憶しています)Apache HTTP Serverバージョン判定の小ネタがあったのを思い出したので、折角なので今回ブログに書こうかと思います。
最初に書いておきますが、かなり古いバージョンの判定ができるってだけなので、今となっては正直実用性0だと思います。
まあちょっとした小ネタとして読んでいただければ幸いですw

TRACEメソッドとは?

皆さんはTRACEメソッドというものをご存知でしょうか?
HTTP 1.1(RFC2616)にて定義されているHTTPメソッドの一つであり、デバッグなどの目的で利用されるもので、HTTPリクエストの内容をHTTPレスポンスとしてクライアントにそのまま返すというものです。
Cross-Site Tracingという本メソッドを利用する攻撃手法が存在するため、セキュリティスキャナなどでは、Webサーバー側で本メソッドが有効になっていると良く指摘項目として検出します。
しかしながら、現行のブラウザでは上記の攻撃手法は対策されており、現在ではこのメソッドが有効であっても大した実害はないといえます。
こちらについては徳丸さんが以下の記事にて詳しく解説されています。

実はそんなに怖くないTRACEメソッド | 徳丸浩の日記

ちなみに本メソッドはApacheの設定変更で簡単に無効化することができます。
さて、このTRACEメソッドですが、Apache HTTP Serverではサーバ側にて本メソッドを無効にしている場合の応答結果が、実はあるバージョンを境に変化しています。
これを利用することでApache HTTP Serverのバージョンを判定することが可能です。

試してみよう!

論より証拠ということで、応答内容の変化を確認してみましょう。

以下のコマンド(以前検証した際、togakushiさんにご指導いただいたシェル芸を記載しています)を実行してApache HTTP Serverの2.2系を全部ソースインストールして、バージョンごとに別々のポートで起動させてみます。

for i in {0..34}; do wget http://archive.apache.org/dist/httpd/httpd-2.2.${i}.tar.gz;tar xf httpd-2.2.${i}.tar.gz; pushd httpd-2.2.${i}; ./configure --prefix=/opt/httpd/2.2.${i};make;make install;sed -i "s/Listen 80/Listen $((2000+${i}))/" /opt/httpd/2.2.${i}/conf/httpd.conf; echo "TraceEnable Off" >> /opt/httpd/2.2.${i}/conf/httpd.conf; /opt/httpd/2.2.${i}/bin/apachectl start; popd; done

※実行するのであれば、事前にwgetgccなどはインスコしてください。
ちなみにconfファイルに「TraceEnable Off」を書き込んで全部TRACEメソッドは無効な状態としてApache HTTP Serverを起動しています。

nmap -sS -sV -n -p 2000-2034 ServerIP

とかやってnmapを実行してやるともりもりバージョンが表示されるので結構壮観です。

f:id:tigerszk:20170904194524p:plain

こちらを使えばMBSDさんのブログに記載したあった内容の検証もはかどりそうですw

さて次にpythonで簡単ですが以下のような各ポートにTRACEメソッドを打ち込んで、HTTPレスポンスのステータスコードを表示させるようなスクリプトを作ってみました。

import requests
for i in range(0, 35):
    url="http://ServerIP:"+str(2000+i)
    try:
        r = requests.request('TRACE', url)
        print("2.2."+str(i)+":"+str(r.status_code))
    except requests.exceptions.RequestException:
        print("no version")

このスクリプトを実行すると以下のような結果となります。

2.2.0:403
no version
2.2.2:403
2.2.3:403
2.2.4:403
no version
2.2.6:403
no version
2.2.8:405
2.2.9:405
2.2.10:405
2.2.11:405
2.2.12:405
2.2.13:405
2.2.14:405
2.2.15:405
2.2.16:405
2.2.17:405
2.2.18:405
2.2.19:405
2.2.20:405
2.2.21:405
2.2.22:405
2.2.23:405
2.2.24:405
2.2.25:405
2.2.26:405
2.2.27:405
no version
2.2.29:405
no version
2.2.31:405
2.2.32:405
no version
2.2.34:405

というわけで、2.2.6と2.2.8を境に応答結果が、403から405へと変化していることが確認できます。
さらに、2.2.6と2.2.8のソースを比較して調査してみた結果、「modules/http/http_filters.c」のコードに以下のような差分があることを確認しました。

f:id:tigerszk:20170904195515p:plain

ステータスコード 403(HTTP_FORBIDDEN)からステータスコード 405(HTTP_METHOD_NOT_ALLOWED)を返すように修正されていますね。

まとめ

というわけで、TRACEメソッドを無効化している際のサーバー側の応答結果にてApache httpdが2.2.6以下であるかということが判別できるわけです(ドヤァ)
まあ、だからどうしたって感じですよね…。
あと「僕の」とかって書きましたが、他にも脆弱性診断とかやってらっしゃる方だったら気づいていた方も多かったのではないでしょうか。
脆弱性診断を実施していると結構色々なバージョンのApacheに出会うため、以前この応答差分にたまたま気が付いて、気になってちょっと色々検証してみましたという感じでした。
正直今となっては相当古いバージョンが判別できるってだけの小ネタなので、飲み会のときのネタぐらいにしていました。
MBSDさんのブログが面白くて触発されたのと、MBSDさんのブログ中にも記載がありますが、Apache httpd 2.2.XのEOLが2017年12月と発表されているため今回このネタの供養の意味も込めて記事を書かせていただきました。

gitの脆弱性のアレを作ってみた

先日私が運営メンバーとして参加してるIT勉強会「ssmjp」の100回記念のイベントがありました!
人生で初めてLTをしたのがこの勉強会で、私は途中から参加という形でかれこれ3年ほど運営をやっていますが、たった3年だけど色々な出来事や出会いがあったなあーと振り返っていました。
今後ともご参加いただける皆様が楽しいと思っていただけるイベントを開催していきたいと思っていますのでよろしくお願いいたします。  

さて、そのイベントの小ネタとして、今回「gitの脆弱性のアレ」を作ってみたので、折角なのでちょっとこのブログでご紹介いたします。
(もうネタとしては正直かなり遅い感じはありますが…w)  

Gitの脆弱性(CVE-2017-1000117)とは

GitでのsshURLハンドリングにshellコマンドインジェクションの欠陥が存在し、細工されたレポジトリに対してGitクライアントでcloneアクションを実行した場合に、Gitクライアントを実行したユーザの権限でshellコマンドが実行されてしまうという脆弱性です。

なお、対策としてはGitのアップグレードで、Version 2.14.1以上では対策されています。

参考
CVE-2017-1000117 - Red Hat Customer Portal
Compromise On Checkout - Vulnerabilities in SCM Tools · The Recurity Lablog

例のアレ

さて、皆さんご存知かと思いますが、上記の脆弱性をチェックするためのユニークなリポジトリが公開されて話題になりましたねw

GitHub - greymd/CVE-2017-1000117: Check Git's vulnerability CVE-2017-1000117

こちらのリポジトリの中身を見てみるとsubmoduleに以下のように細工がしてあり、脆弱なgitクライアントにてrecursiveオプション付きでgit cloneすると、fileに記載された内容がshellコマンドとして実行されるようになっているのがわかります。
shellコマンドが実行されると例のアレがターミナルに表示されるわけですw

[submodule "morimori"]
    path = morimori
    url = ssh://-oProxyCommand=sh<file /morimori

このリポジトリは非常に面白くて、他にも色々な方がインスパイアした作品を公開されていました。 GitHub - sasairc/CVE-2017-1000117_wasawasa
GitHub - takehaya/CVE-2017-1000117
GitHub - shogo82148/Fix-CVE-2017-1000117

またノリと勢いで作ってみた

面白くて私もこれらのリポジトリで色々遊んでいたのですが、とある知り合いのエンジニアの方から「tigerszkさんもあのやる夫のAA(※)使って作ってみればいいじゃないですかw」と言われたので、あー面白そうだなあと思い、勉強がてら丁度いいから100回記念イベントの小ネタに作ってしまおうと、今回もノリとその場の勢いで作ってみました。
※昨年末のとあるLTにてノリとその場の勢いでやる夫のAAを制作しました。
ノリとその場の勢いでPocを作った話

そんな経緯にて、先日のssmjpで公開した100回のお祝いメッセージとして作ってみたのがこちらですw

GitHub - tigerszk/ssmjp-100th-message

f:id:tigerszk:20170829135528g:plain

togakushiさんにご助力いただき、ランダムで色が変わって徐々に表示するようなシェルコマンドを実行するようになっています。宜しければ遊んでみてくださいw

クラウドサービスを脆弱性診断する時のお作法

「とある診断員の備忘録」というタイトルのわりに、ブログを始めてから今まで脆弱性診断に関することを一切書いていなかったことに気づいたので、そろそろ脆弱性診断ネタを書こうかと思います。 今回はクラウドプラットフォームに対する脆弱性診断の小ネタです。

クラウドサービスを診断する時のお作法って?

私が脆弱性診断をやり始めた駆け出しの頃では、オンプレ環境の診断対象が多かったのですが、最近ではクラウドプラットフォームなどの利用が当たり前となったため、クラウド環境の診断対象と沢山エンカウントします。 クラウド環境に対して脆弱性診断を実施する場合には、実はいくつか抑えておくべきお作法があります。

1. クラウド事業者側に診断事前に申請が必要な場合がある

脆弱性診断の種類にもよりますが、ブラックボックステストでは疑似的な攻撃を実施して脆弱性の有無を判定するため、不正アクセスとして検知される可能性もあります。 そのためトラブル(※)を避けるためにも脆弱性診断を実施する場合には、「事前申請は必要ない」と明記でもされていない限りは、利用しているクラウドプラットフォーム環境の管理事業者(以下 クラウド事業者)側にちゃんと事前に脆弱性診断を実施して良いか確認をする必要があります。

ちなみに過去私が経験したものですと、事前の申請時には以下のような情報をクラウド事業者側から要求されるケースなどが良くありました。

※トラブルの一例
昔々、とある診断員はシステム担当者の方に、事業者側への事前連絡を再三お願いしていたのですが、何故だか連絡がされないまま診断がスタートしました。その後、診断による通信はめでたく不正アクセスとして検知され、診断途中にアクセス元IPが念願のブラックリスト入りを果たし、全ての通信がブロックされる事案となったそうです。ちなみにその時のブロックを解除してもらう手続きには結構期間が必要とのことであり、長い間診断が中断しましたとさ。めでたしめでたし。

2. 環境によっては脆弱性診断自体を実施できない場合がある

クラウド事業者側のポリシーで、環境などによってはそもそも脆弱性診断の実施を許可していないケースがあります。 私の経験ですと共有ホスティングのような、複数顧客で同じ環境を利用しているようなサービスの場合などでは、利用している他の顧客に影響がでるかもしれないため診断実施の許可をいただけなかったケースなどがありました。 また、後述しますがAWSなどでは、診断を実施可能な環境の条件が明確に指定されています。

上記二つのお作法の内容については、事業者側のポリシーによってマチマチです。 また、ポリシー自体が変更される場合もありますので、脆弱性診断を実施する際には、ご自身の利用しているプラットフォームの事業者にちゃんと確認をした方が良いと考えます。私も脆弱性診断を実施する際には、システム担当者の方に必ず上記のご確認をお願いしています。

有名どころではどうなの?

ここら辺の情報っていちいち確認するのが大変なので、メジャーなものはどこかにまとまっていてほしいなあーって正直結構前から思っていました。 折角の機会なので、脆弱性診断士の目の前に良く診断対象として登場する三大クラウドプラットフォーム(AWSMicrosoft Azure、GCP)の脆弱性診断に関するお作法についてちょっとまとめてみました。 (なお今回記載したものは2017/6/20時点の情報となります。)

AWS(Amazon Web Services)

AWSについては以下のサイトに脆弱性診断に関するポリシーが記載されています。

ペネトレーションテスト(侵入テスト)- AWS セキュリティ|AWS

上記に記載されているようにAWSでは診断事前に専用フォームからの申請が必要です。 具体的な申請の仕方についてはクラスメソッドさんの以下の記事に詳しく記載されています。

2017年版 AWSの侵入テストについて | Developers.IO

また、診断可能な対象については以下のように明確に定義されています。

なお、AWSについては手前味噌となりますが、ここら辺について過去に私がまとめたスライドがありますので宜しければご覧ください。

www.slideshare.net

(2017/10/20 追記)

AWSの侵入テスト申請にアップデートがありましたので、新しくBlogを書いてみました。 宜しければこちらの記事をご参照ください。

AWSの侵入テスト申請フォームが変更された件 - とある診断員の備忘録

Microsoft Azure

Microsoft Azureについては以下のサイトに脆弱性診断に関するポリシーが記載されています。

Microsoft Cloud Unified Penetration Testing Rules of Engagement

以前は診断事前の申請が必要だったのですが、割と最近にポリシー変更があったようです。

MICROSOFT AZURE PENETRATION TESTING NOTIFICATION
As of June 15, 2017, Microsoft no longer requires pre-approval to conduct a penetration test against Azure resources.

と記載があり、現時点では脆弱性診断の申請は不要となったようです。

(2017/10/20 追記) 日本語の記事も公開されていたので、追記しておきます。

Microsoft Azure での侵入テスト (ペネトレーションテスト) について – Microsoft Azure サポート チーム サイト

GCP(Google Cloud Platform)

GCPについては以下の「ペネトレーション テスト」の項目にさらっとですが脆弱性診断に関するポリシーが記載されています。

Security and Compliance on the Google Cloud Platform  |  Google Cloud Platform

Google Cloud Platform のセキュリティを評価するためにペネトレーション テストを行う際に、Google へ連絡する必要はありません。ただし、Google Cloud Platform の利用規定ポリシーと利用規約を遵守し、テストの影響が他のお客様のアプリケーションに及ぶことなく、お客様のプロジェクトに限定されるようにする必要があります。脆弱性を発見した際は、脆弱性報奨金プログラムまでご報告ください。

上記のような記載があるため脆弱性診断の申請は不要です。

まとめ

メジャーなクラウドプラットフォームの脆弱性診断に関するお作法についてまとめてみました。 もし記載した内容などが誤っている場合にはご指摘いただければ幸いです!

(2017/6/30 追記)

この記事をトリガに、VAddyの公式ブログにて、主要クラウド事業者の脆弱性診断に関するポリシーをまとめてくださっています。 本記事内には記載していないクラウド事業者のポリシーについても記載されています。

クラウドサーバに対する脆弱性診断の事前申請について各社に問い合わせてみた結果 - VAddyブログ - 継続的セキュリティテストへの道 -

AWS使って社内CTFやってみたよ

5/22に開催された第五回Security-JAWSにて登壇させていただきました!

Security-JAWS 【第5回】2017年5月22日(月) - Security-JAWS | Doorkeeper

タイトルそのままですが、某社内でAWSを使って社内CTFを開催した際のよもやま話をネタとしてお話しいたしました。 本当は当日投影したスライドとかをそのまま公開したかったのですが、イベント当日の写真とかについてはちょっと諸事情で公開できないので、今回はセッションの中でお話ししたAWSに絡む部分だけをまとめて、私のブログで公開しようかなと思います。

当日のセッションでもお話ししましたが、まずそもそもなんで社内CTFを開催したのかについては、

  • なんか社内でエンジニアの人に楽しんでもらえるようなイベントとかをやってみたかった
  • セキュリティに興味をもってもらうきっかけ作りとかには丁度いいのかなと思った
  • ぶっちゃけちょっと運営側にも興味があった

というようなもので、最初は適当な有志で集まってやってみようかという軽いノリではじめてみた感じです。 社内でやってみたら、思ったよりもウケが良く、数回開催するうちにちょっとづつ規模が大きくなってきて、前回は70人くらいの方に参加していただけるイベントを開催できました。

現在開催しているものは、スタンダードなJeopardy形式のCTFです。 CTFを全くやったことのない方でも参加しやすいように、「CTF for ビギナーズ」のスタイルを極限まで参考にさせていただき、午前中は講義(座学+ハンズオン)、午後からみんなでCTFをやるような一日コースの集合研修という感じで開催しています。現在はそういう感じですが、今後は常設CTFにしたりとか、他競技形式でのイベント開催なども、実現できるかはわかんないですが検討していきたいですね。

で、そんな中今までは、適当な機材をつかったオンプレの競技環境で開催していたのですが、段々規模が大きくなってきてめでたく予算もついたので、競技環境をクラウド化することになり、今回AWSを使って構築してみましたという感じです。という背景で、競技環境を構築する中でハマったことや、こんな感じでやりましたということなどをここで書かせていただきますw

AWSではイベント申請が必要

Security-JAWSのセッションでもお話ししましたが、弊社内CTFの一つの特徴として、競技用のクライント環境を運営側が全部用意しているという点があります。 これはまあ社内イベントならではの悩みなのかなと思うのですが、簡単に言えば社内だと諸事情によって競技用の端末を用意できない方とかもいらっしゃるので、そういう方でも気軽に参加していただくための運営側の配慮って感じですね。ちなみに「いやいや、俺は自前の環境でやりたいし」って方も勿論沢山いらっしゃるので、ご自分で用意できる方については持ち込みPCの利用もOKにしています。

で、まあイベント開催前に運営側で毎回このクライアントPCのキッティングをやっているんですけど、これがまあダルいし、結構大変なんですよね。という中、AWSにはAmazon WorkSpacesというDaaSがあります。

Amazon WorkSpaces (クラウド上の仮想デスクトップサービス) | AWS

これを見て「おお!クライント環境の用意はこれ使えば楽できるんじゃね!」ってそんな風に考えていた時期が俺にもありました。 結論から申しますと、実はその計画はとある理由によってお蔵入りとなってしまいますw

話は変わりますが、皆さんはAWSを使ってこういうイベントを開催する場合には専用の申請が必要だということをご存知でしょうか? 脆弱性診断を実施する際に申請する必要があるペネトレーションテスト申請は結構ご存知だと思うのですが、その解説ページに、「シミュレートされたその他のイベント」という項目の記載があります。

侵入テスト - AWS クラウドセキュリティ | AWS

上記には、どうやらこういったイベントをやるには、開催するイベントの内容などを事前にAWSに申請して許可をとらなければいけないルールがあることが記載されています。 私もAWSを利用して今回こういうイベントをやることになって初めてこのルールを知りました。

ペネトレーションテストの申請をされたことがある方は結構いらっしゃるのかなと思いますが、このセキュリティイベントに関する申請をされた方とかはあんまり多くいらっしゃらないのかなと思いましたので、ご参考までに今回どんな感じでやり取りをしたかについて簡単に書いてみました(まあ、そもそもこういったイベントを開催する人が、そこまで沢山いないだろというツッコミは置いておいてくださいw)。

まずはこんな感じで問い合わせをしてみたのですが…

f:id:tigerszk:20170526132431j:plain

ええー!?マジで!?WorkSpaces使えないの!?いきなり予想してなかった回答ををいただいたので、ちょっとビックリしました…。あとやり取りは英語じゃないとNGなようです。ちなみにAWS側から提出を要求された情報については以下のようなものでした。

原文そのまま 自分の理解
Account number(s): AWSのアカウント情報
Source IP(s) if applicable: イベント時にAWS環境に接続するアクセス元IP情報
Target IP(s) if applicable: イベント時に接続するAWS環境サーバのIP情報
Start Date: イベント開始日
End Date: イベント終了日
Regions involved in Event: イベントに関係するAWSリージョン
EC2 or RDS Instances involved, if applicable: イベントに関係するEC2またはRDSインスタンスの情報
Are you an Amazon Enterprise Customer?: Amazonの企業顧客かどうか
Software Used (if commercial): 使用するソフトウェア(商用の場合)
AWS products/Services to be used): 使用するAWS製品/サービス
Type of Simulated Event in detail: イベント内容の詳細
Dependent on the Simulated Event type, please confirm if target will be aware of the event?: イベント内容に応じて、対象(対象者?)がそのイベントを把握しているか確認してください。(※1)
Whom (email address) should the target party contact to verify this is indeed a Simulated Event?: これが本当にシミュレートされたイベントであるか確認するための連絡先情報
Please provide target domain name, if applicable: 対象ドメイン情報
Will your Event require AWS interaction? If so, please let us know in what capacity and why?: イベントでAWSとのやりとりが必要?もしそうならどんなことかと理由をお知らせください。

※1 こちらについてはイマイチ内容がわからなかったので内容について質問したのですが、特にAWS側からの回答はなく申請の許可がおりました。

ペネトレーションテスト申請と同じくらい結構色々情報を要求される感じでした。また、上記の内容については結構イベントの内容とか環境設計ができてる段階じゃないと、なかなか答えづらいんじゃないかなという印象を持ちました。ちょっとでもこの申請をされる方のご参考になれば幸いです。もしかしたら、イベント内容によっては設問が変わったりするのかもしれないですし、今後新しい設問が追加される可能性もあるので、これと全く同様というわけではない可能性はあります。

この回答に対して「ハイ喜んで~」と返信してしまうとまた地獄のクライアントPCキッティング大作戦が確定してしまうのがちょっと嫌だったのと、もしかしたら先方が何か勘違いしているのかもしれないし、ワンチャンあるかなと思ってちょっと食い下がってみたのですが…

f:id:tigerszk:20170526151332j:plain

f:id:tigerszk:20170526151350j:plain

というわけで、結局今回はWorkSpacesを使うことができませんでしたw 申請自体については、この後、設問に該当する情報を送ったら、次の日にあっさり許可がおりました。 もっと長い時間がかかるものなのかなと思ったのですが、思ったよりも早かったです。

結局どんな環境を構築したの?

上記のような理由により、今回WorkSpacesを使えなかったので、最終的には以下のようなシンプルな構成になっちゃいました。

f:id:tigerszk:20170526161618j:plain

社内イベントだし、そこまで大量アクセスが来ないだろうと想定し、問題サーバだけをELBを利用して冗長構成にした感じですね。今回やってみたかった取り組みの一つだったのですが、サーバで動作する問題については全部dockerを利用して作成しました。切っ掛けは以下の記事だったりします。

#cmdevio2016 (レポート: B-2) Trend Microのセキュリティコンテストの裏舞台でDockerとAnsibleを使った話 | Developers.IO

以前この記事を拝見して、「おー面白そう!自分もちょっとやってみたい!」と思っていたのと、検証目的でちょこちょこ触ってはいたのですが、サービス提供するようなシステムをdockerで構築した経験が無かったので、丁度良い機会だから今回勉強がてらやってみました。 ※ちなみに元記事の発表をされたトレンドマイクロの岩田さんより、今回の発表の後に、ご挨拶いただきめっちゃ嬉しかったです!ありがとうございました。

AWSであれば、ECR(Amazon EC2 Container Registry)を利用することで、速攻でプライベートレジストリ使ってdockerイメージを管理できるので非常に楽ちんです。 今回やってみた感想としては、docker使うとやっぱり本番へのデプロイがすごい楽だなという印象を持ちました。ローカルの開発環境で開発して、イメージが出来上がったらすぐに本番で稼働させられるのは魅力ですね。

今回作成したコンテナのタイプ的には大きく分けて以下の二種類に分かれます。

今回は全部で13個の問題コンテナを作成して、本番環境で動作させました。ちなみにdockerの管理にはECS(Amazon EC2 Container Service)を使ってみたかったのですが、諸事情によりというか単純に検証の時間が足りなくて断念し、本番時はローカル環境で動かしていたdocker-composeを利用して動作するコンテナを管理しました。

監視には折角AWS使っているので、CloudWatchを利用しようかなとも検討したのですが、やっぱり時間が無くて今回は多少慣れていたZabbixを採用しました。 今回はコンテナの監視もしてみようかなと思い、試験的ですが以下のzabbix-docker-monitoringを利用してDockerコンテナの監視もしてみました。

GitHub - monitoringartist/zabbix-docker-monitoring: Docker/Kubernetes/Mesos/Marathon/Chronos/LXC/LXD/Swarm container monitoring - Docker image, Zabbix template and C module

後は、各問題サーバのポート稼働状況やWebサービスについてはステータスコードの状況を監視したりっていう感じですね。競技中はslackにアラート通知を流すようにして、なんか問題があれば、問題があるdockerコンテナをイメージから再作成するような運用にしていました。ちなみに本番時は想定よりも問題サーバは全然安定稼働していて、特に障害対応することもなかったので一安心でした。

今回構築した環境では、時間的にできなかったことや、色々改善点もあるなあと思っているので、今後またちょこちょこいじっていこうかなと思っています。

ぶっちゃけ費用はおいくら?

Security-JAWSでも発表しましたが、AWSの利用料はこのぐらいでした。

f:id:tigerszk:20170526173139j:plain

WorkSpaces以外にも色々と検証したので、ただ開催するだけであればもっと安く上がるんじゃないかなと思います。

まとめ

というわけで、今回私がAWSを利用して社内CTFをやってみた所感をツラツラ書いてみました。もしAWSを使ってなにかこういうイベントをやろうと思っている方の参考に少しでもなれば幸いです。 開催したイベントも参加者の方には楽しんでいただけたみたいなので満足しています。まあただ、自分達でイベント運営やってみた感想としては、環境構築を通じて色々新しいことを勉強できたりするので個人的には非常に楽しかったりするのですが、楽しい以上にやはりそれなりに色々準備が大変だったので、運営側の方々の苦労を身をもって痛感しました。今後参加者としてITイベントに参加する時は、運営の方々にはより一層の敬意を払うべきだなと思った次第ですw

脆弱な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ヘッダインジェクションみたいにフレームワークミドルウェア側で対策されているため、脆弱性を作りこむのがちょっと面倒くさいものとかもあったりしますので、そういうのを再現する場合にはこのような形式の方が、お手軽なのかもしれないですね。また、疑似的に脆弱性を再現しているので、ハニーポットなどにも使えるのではないかなという印象を持ちました。

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