メモリリーク、デッドロック、リダイレクトループ、JVMクラッシュ...バグだらけのWebアプリケーションを使ってバグを理解する

More than 1 year has passed since last update.


概要

Webアプリケーションの開発や保守をしていると、いろいろなバグに遭遇します。メモリリーク、デッドロック、リダイレクトループ、JVMクラッシュ等々、バグは様々です。こういったバグは、実際にコードを書いて、実行・再現させてツールで解析してみると理解が深まります。

ということで、いろいろなバグを実装したWebアプリケーションをつくってみました。現時点では、以下を簡単に再現できます。


  • メモリリーク (Javaヒープ領域)

  • メモリリーク (Permanent領域)

  • メモリリーク (Cヒープ領域)

  • デッドロック (Java)

  • デッドロック (SQL)

  • 完了しないプロセスの待機

  • 無限ループ

  • リダイレクトループ

  • JVMクラッシュ

  • ネットワークソケットリーク

  • データベースコネクションリーク

  • ファイルディスクリプタリーク

  • XSS

  • SQLインジェクション

  • ExceptionInInitializerError

  • NoClassDefFoundError

  • OutOfMemoryError (Java heap space)

  • OutOfMemoryError (Requested array size exceeds VM limit)

  • OutOfMemoryError (unable to create new native thread)

  • OutOfMemoryError (GC overhead limit exceeded)

  • OutOfMemoryError (PermGen space)

  • OutOfMemoryError (Direct buffer memory)

  • StackOverflowError

  • UnsatisfiedLinkError

  • 整数オーバーフロー

  • 丸め誤差

  • 打ち切り誤差

  • 情報落ち

[2017/02/20 さらに以下を追加]


  • LDAPインジェクション

  • コードインジェクション

  • フォワードループ

  • スレッドリーク

  • 正規表現解析による遅延

  • 文字化け

[2017/03/08 さらに以下を追加]


  • OSコマンドインジェクション(OGNL式インジェクション)

  • 拡張子制限の無いファイルアップロード

  • オープンリダイレクト

  • ブルートフォース攻撃可能なログイン画面

[2017/03/26 さらに以下を追加]


  • CSRF (クロスサイトリクエストフォージェリ)

  • クリックジャッキング

  • サイズ制限の無いファイルアップロード

  • ディレクトリトラバーサル

  • メールヘッダーインジェクション

  • 意図しないファイル公開

  • 親切過ぎるエラーメッセージ

  • 危険なファイルインクルード

  • プラス演算子による文字列結合の遅延

  • FactoryConfigurationError

  • Nullバイトインジェクション

  • XEE

  • XXE


Webアプリケーションの起動方法

Webアプリケーションをgit clone(またはダウンロード)して、mvn install exec:execで起動します。

$ git clone https://github.com/k-tamura/easybuggy

$ cd easybuggy
$ mvn clean install exec:exec

以下のようなメッセージが表示されたら、Webアプリケーションの起動は完了しています。

5 27, 2017 3:29:58 午後 org.apache.coyote.AbstractProtocol start

情報: Starting ProtocolHandler ["http-bio-8080"]


その他の起動方法

ここからダウンロードしたeasybuggy.jarを実行(java -jar easybuggy.jar)するか、ROOT.warをTomcatなどのサーブレットコンテナにデプロイしても起動できます。このとき以下のようなJVMオプションを付けると問題が再現しやすくなります。

java -Xmx256m -XX:MaxPermSize=64m -XX:MaxDirectMemorySize=90m -XX:+UseSerialGC -Xloggc:logs/gc.log -XX:+PrintHeapAtGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M -XX:GCTimeLimit=15 -XX:GCHeapFreeLimit=50 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/ -XX:ErrorFile=logs/hs_err_pid%p.log -XX:NativeMemoryTracking=summary -agentlib:jdwp=transport=dt_socket,server=y,address=9009,suspend=n -Dderby.stream.error.file=logs/derby.log -Dderby.infolog.append=true -Dderby.language.logStatementText=true -Dderby.locks.deadlockTrace=true -Dderby.locks.monitor=true -Dderby.storage.rowLocking=true -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=7900 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -jar easybuggy.jar

※easybuggy.jarとROOT.warは、mvn packageでビルドされます。

起動したら次のURLにアクセスします。

http://localhost:8080

正常に起動していると以下のような画面が表示されます。

mainPage.png

リンクのいずれかをクリックすると、問題が発生します。が、その前にVisualVMやJConsoleなどを起動しておくと、どのような現象が起こっているか把握できます。以下は、Javaヒープ領域のメモリリークを起こして、OutOfMemoryErrorを発生させる過程を監視しているVisualVMの画面キャプチャです。

OOME.png

これらのツールを使ったバグの解析方法などについては、今後簡単に説明します。


注意事項

OutOfMemoryError関連のリンク(特にネイティブメモリを操作するもの)をクリックすると、PCの動作が不安定になる可能性があります。CPUやメモリを制限したVM上で起動するなどしてから、自己責任でリンクをクリックして下さい。


詳細

このWebアプリケーションに関するデバッグやトラブルシューティングの方法については、このページ(日本語)かこのページ(英語)を参考にして下さい。


補足

Spring Bootでつくったこのアプリケーションのクローンもあります。


デモ

以下は起動のデモです。

mov_eb_ppt1.gif


プレゼン資料

「第57回 脆弱性診断ええんやで(^^) やられWebアプリケーションの倒し方」でお話しした(正確にはお話していただいた)「Easybuggy」についてのプレゼン資料です。

thumbnail

([2018/01/22 デモとプレゼン資料を追加])