ブレークポイントを張って、デバッグを開始して、攻撃コードを打ちます。いうことで、簡単にXdebugとNetBeansを使った脆弱性検証の環境が立ちました。Drupalの脆弱性の攻撃コードが出る前に用意しとけよ、という話ですね。もって、その通りです。これ自体はもう少し応用が利きそうなので、PHP系のCMSやJAVAのミドルウェアを使ったアプリケーションは同じことができそうだなーと思っています。そのへんは今後、頑張っていきたいです。Chromeを使ったWebクローラを作る最近Webサイトのクローリング(スクレイピング?)に興味を持ちまして、Webサイトのクローラ的なものを作りたいと思い、いろいろ試行錯誤していました。Webサイトのコンテンツを取得するなら、一番簡単なものだとwgetやcurl、ちょっと手を加えるならスクリプトを書く、Pythonならrequestsやmechanizeなどのライブラリを使うと、比較的単純なことなら簡単にできます。高度なことをやろうとすると、やはり実際のブラウザを利用するのが一番でしょう。ChromeをHeadlessモードで動かし、Seleniumで制御してスクレイピングしようという記事です。面白そうだったのですが、自分の欲しい機能にあと一歩というところでした。これにmitmproxyを組み合わせれば、幸せになれそうだったので、試してみました。Middle)を行うプロキシです。暗号化された通信に割り込んで、盗聴、改ざんを行う攻撃手法ですが、このテクニック自体は攻撃に限らず色々な場面で利用されています。mitmproxyを利用すると、HTTPS(HTTP)の通信の中身を覗き見たり、書き換えたりが可能になります。コンテンツを取得するだけであればそんなことをする必要はないのですが、これができると色々と便利なので、何とか組み込みたいと思いました。上の記事にある内容をトレースしつつ、mitmproxyを挟んでみたのですが、結論を言うとダメでした。mitmproxyを利用するとき、「ブラウザ⇔mitmproxy⇔Webサイト」という形で通信が流れますが、ブラウザとmitmproxyの間はmitmproxyが発行する自己証明書が利用されます。こちらはブラウザから見ると不正な証明書になります。そこで、Chromeに「--ignore-certificate-errors」というオプションを付けてやることで、不正な証明書のエラーを無視して通常通りアクセスできるようになるはずです。Headlessでmitmproxyを動かすのは現状難しそうという結論に至りました。Headlessでも正常に動くようになるかもしれないので、そこは気長に待つことにします(あるいは僕の知らない別のオプションがあるのかもしれませんが、どなたか知っていたら教えていただきたい......)。追記(2018/5/15)個人のプロファイルにルート証明書をちゃんと読み込ませてやると、証明書のエラーがでなくなり、うまくいきました。ChromeをDockerから動かすことを考えました。unskilled.siteこういう方法を使ってDocker内のGUIアプリケーションを起動させることができるようです。Systemを許可してUNIXソケット経由でディスプレイを共有する方法です。ChromeをインストールしたコンテナでChromeを起動させると見事にChromeが立ち上がり、普通のGUIアプリケーションとして利用可能となりました。Headlessモードを使わなくとも、GUIアプリケーションとしてDocker内で起動させることもできるということです。Chromeのコンテナイメージを作ってみました。ChromeChromeDriverSeleniummitmproxy日本語のフォントなど一応日本語環境で利用することを想定して日本語関係のフォントやパッケージも入れました。本当はイメージを分けて作った方が後々やりやすいのかもしれませんが、mitmproxyの起動時に作成される自己証明書をChromeが入っているコンテナにインストールする必要があり、いろいろと面倒だったので、ひとまず全部一つのコンテナイメージにぶち込みました(イメージサイズが1.5Gくらいになってます......)。出来上がったDockerfileがこちらになります。github.com起動時に色々やることがあるので、docker-entrypoint.shが色々面倒なことになっています。Chromeが起動するはずです。mitmproxyのログはそのまま標準出力に流れていきます。今はHeadlessでGoogleにアクセスするようになっています。Systemの認証を許可するために、ホスト側で以下のコマンドを実行しておく必要があります。local:認証を許可してそのままにしておくのはセキュリティ的によろしくないので、終わったら戻しておきましょう。-local:Chromeを自動で動かしたい場合はscriptsフォルダ内に「crawling-script.sh」を作成すると、そこに記載されているコマンドを実行します。例として、特定のサイトにアクセスするスクリプトを実行します。up」すると、サイトにアクセスしてスクリーンショットを撮って終了します。「--headless」のオプションを付けると、Headlessモードで動きますが、先に述べた通りの理由でHTTPSのサイトではmitmproxyのエラーのために正常にアクセスできません。アクセス先がHTTPのみのサイトであれば、問題はないですが。次にscriptsフォルダに「mitmproxy-script.py」を作成します。例として、アクセス先のレスポンスからhtmlファイルをすべて保存するスクリプトです。f.write(flow.response.text)これで起動すると、outputフォルダに保存されたダウンロードしたhtmlファイルが保存されているのを確認できます。mitmproxyのサンプルはこちらにあります。こんな感じでmitmproxyとseleniumのスクリプトを書いて、うまくやれば好きなWebサイトに好きなようにアクセスした際の通信を解析できるようになる、と思います。スクリプトについては今後作っていこうかと思います。seleniumもmitmproxyも割とサンプルはあるので書きやすいのではないかなー、と。Webサイトの解析用のクローラを作ることはできたので、満足はしました。Headlessで動かせなかったのは残念でした。なにかしら方法はありそうなので、もうしばらく調べてみたいです。あと、FirefoxにもHeadlessモードが搭載されているそうなので、いずれはそっちも試してみたいです。最後に、Webサイトのクローリング、スクレイピングはマナーを守って行うようお願いします。追記(2018/5/15)headlessモードでうまく動作したので、追記です。ルート証明書をちゃんとインストールすると、エラーがなくなりました。docker-entrypoint.shの中でコンテナの起動時にやるようにしています(ので、コンテナ起動に若干余計な時間がかかります)。OSに証明書を認識させます(ここまでは前回やっていた)。update-ca-certificateschromeを一度起動させると、デフォルトのプロファイルが作成されます。すると、ホームディレクトリの「.pki」ディレクトリ配下に証明書を関連のデータベースができるので、ここにcertutilコマンドを使ってmitmproxyの証明書をインストールします。sql:${prefdir}doneこれで、headlessモードでchromeが動いてくれるようになりました。ちなみに、Firefox版も作りました。こちらも同じように動いてくれるかと思います。(Firefox版を作っていて証明書に気づいた)これで幸せになれそうです。久しぶりにブログ書きます。最近あまりネタがなかったのでちょっとさぼり気味でした。Frameworkの脆弱性(CVE-2018-1270)についてです。Struts同様JAVAのアプリケーションフレームワークです。いうメッセージプロトコルをWebSocketで利用している場合に、攻撃者から細工されたメッセージを受け取ることで、任意のコード実行が行われる脆弱性。同様に細工されたURLにアクセスすることでディレクトリトラバーサルが行われる脆弱性も報告されています(CVE-2018-1271)。4.3.15また、すでにサポートが終了している過去のバージョンにおいても本脆弱性の影響を受けるとのことです。検証PoCがすでに公開されており、検証用のアプリケーションもあったので、検証してみました。検証用のアプリケーションを動かしました。8080ポートを開けてコンテナを動かします。Bootの脆弱性のあるバージョンを持ってきます(このへんから)。Bootのソースの中に検証用のアプリケーションのソースとpom.xmlを入れて、Mavenでビルドし、アプリケーションを動かします。Bootが色々と必要なものを落としてきて、アプリケーションを動かしてくれます。終わったら、localhostの8080番にアクセスします。検証用のサンプルなので、すでにPoCが入力されており、あとはSendするだけという親切設計になっています。中身がコピーされていました。ついでに修正されたバージョンでもやってみました。中身のバージョンを書き換えます。気を利かせて、脆弱なバージョンを持ってきてビルドするみたいですね。同じようにやってみましたが、コード実行は失敗、それ以外には変化はありませんでした。攻撃時のパケットパケットキャプチャをとってみました。WebSocketでやり取り(STOMP)という感じですかね。攻撃コードがバイナリになってどこが何をやっているのかがちょっとわからないです......。WebSocketがデータ圧縮を行っているため、攻撃コードが可読でなくなってるみたいです。permessage-deflate」というヘッダのせいみたいですね。試しにBurpを間に挟んで攻撃コードを実行してみました。例のヘッダがなくなり、一部平文で見えるようになりました。それでも攻撃コードはマスクされています。(BurpってWebSocketも対応してるんですね)ただ、WireSharkで見ると、マスクを解除してくれるので、攻撃コードがちゃんと見えています。普通のHTTP通信ならレスポンスが圧縮されることはあってもリクエストは平文だったのですが、WebSocketはリクエストが圧縮されたりマスクされたりするので、攻撃のポイントが見えにくくなり、検知がしにくくなります。WebSocket経由の攻撃はこれまで見たことなかったのですが、割と面倒くさいなというのが今回の印象です。追記(2018/04/17)WebSocketのマスクついて調べてみました。マスクされたペイロードということらしいです。攻撃者が任意のトラフィックを通信路に流せると、キャッシュ汚染の恐れがあるといった理由でこうなっているみたいです。これをIDSなどで検知しようとすると、攻撃コードがWebSocketのマスクされた値の中にあるので、それを解除したうえで、検知を行う必要があり、かなり難しいと思われます。WebSocket経由での攻撃というのは初めて聞いたのですが、このようなWebSocketのリクエストに対応した検知システムとかって、何かあるんでしょうかね......。乗り換えようという人もいるかもしれませんが、こまめにアップデートする必要はいずれにせよありそうですね。Frameworkは初めて触ったのですが、割と開発の使い勝手は良さそうな印象でした。今回の攻撃は影響は大きそうですが、まだ攻撃が行われたという話は聞かないです。先に述べたように一般的なWebの攻撃に比べて検知が難しいので、気づかないうちに攻撃が行われている、なんてこともあるかもしれません。自分の管理するサーバに異変がないか、確認してみるのがいいかと思います。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。