race condition
TRANSCRIPT
RACE CONDITIONの話
Fukui Tech 7.5
2017/02/25 (Sat)
@hama7230
WHOAMI
• @hama7230
•東京の大学生•元福井の高専生• CTF歴 1年6ヶ月
• CTFチーム「TokyoWesterns」のpwn要員
何を話すか
• Race Conditionの解説
• CODEGATE 2017 Quals「Hunting」の解説
RACE CONDITION
•日本語にすると競合状態•マルチタスク(もしくはマルチスレッド)な環境において、同一のリソースへほぼ同時にアクセスしたときに、予定外の処理結果が生じる問題
https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/c304.html
DIRTY COW
• CVE-2016-5195
• https://dirtycow.ninja/
• Race Conditionを使った脆弱性
• Linuxカーネルにおける権限昇格の脆弱性
• Read Onlyな権限である、本来なら編集できないファイルを編集できてしまう脆弱性
• Androidなどで攻撃が確認された
CTFにおけるRACE CONDITION
• CTFでもRace Conditionを取り扱った問題は存在する
• pwnジャンルとして出題される傾向にある
•処理全体を追いかけて、どの部分でRace Conditionが起こせるか見極める必要があり、難易度が高い
PWN問題のパターン
•サーバ上で動作するバイナリを攻略し、フラグを読むことが目的
•バイナリには脆弱性があり、必ず攻略可能となっている
• ncで接続するリモートシェル奪取型と、sshで接続するローカル権限昇格型の2種類に分かれる
•ローカル権限昇格型では、ログイン時の権限でフラグを読むことができず、suidビットがついた脆弱なバイナリを攻略していく
HUNTIG
• CODEGATE 2017 Qualsで出題
• sshでログインするローカル権限昇格型
• Race Conditionを起こし、本来なら起こりえない処理を発生させてフラグを得る問題
• Tokyo Westernsも解けたが、かなり時間をかけてしまった
初期調査 (1/2)
% file ./hunting
./hunting: setgid ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=c32e1cc2bfd1447bd571a21303dd40e79324e2bb, stripped
-r-xr-sr-x 1 hama hama 15056 2月 10 16:04 hunting*
• 64bitのダイナミッックリンク
• setgidされている => 所有者の権限で実行される
初期調査 (2/2)
% checksec ./hunting
[*] '/home/hama/ctf/CodeGate2017/Hunting/hunting'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE
•セキュリティ機構の確認•よくある標準的なバイナリ
RELRO
• RELRO: Partial RELRO
• RELocation Read-OnlyからRELRO
•ライブラリ関数の解決をいつ行い、解決されたアドレスを管理するテーブルが書き換え可能かどうか
• Partialでは、書き換えが可能でありGOTの書き換えで処理の制御を奪うことができる
CANARY
•スタック上に置かれるランダムな値• stack-smashing protectionによって追加されるデータ
•関数の処理が始まる前にスタック上に設置され、関数の処理が終わるときに書き換わってないかどうか確認する
•書き換わっていた場合は、バッファオーバーフローが発生したとしてプログラム自体を終了する
• huntingもcanaryが存在する
• canaryの値がリークできれば突破可能
動作確認
% ./hunting
1. How to play
2. Use skill
3. Change skill
4. Remove skill
5. Recieve suggestion
6. Exit
choice:
• 1~6まで選択できる。それ以外を入力するバイナリは終了する
HOW TO PLAY
•メッセージを出すだけの処理•そのまま終了する
USE SKILL
========================================Boss' Attack
Boss is Attacking you!
select shield
1. iceshield
2. fireshield
3. windshield
choice:
========================================Skill Activation
You use attack
Boss‘s hp is 50 (初期値は100)
=======================================
2 (自分の入力)
Your HP is 250 (初期値は500)
•防衛に失敗したパターン
USE SKILL
========================================Boss' Attack
Boss is Attacking you!
select shield
1. iceshield
2. fireshield
3. windshield
choice:
========================================Skill Activation
You use attack
Boss's hp is 50
=======================================
1 (自分の入力)
You succeed in defense
Your HP is 500
========================================
•防衛に成功したパターン
CHANGE SKILL
select skill1. attack2. fireball3. iceball4. magicball5. lightning6. hellfire7. icesword8. magicsword9. hollylightchoice:
• スキルが選択可能• 5以上はレベルを上げないと選択できない
REMOVE SKILL
•スキルを初期状態のattackに戻す
RECIEVE SUGGESTION
•メッセージを受け取る処理•バッファオーバーフローが発生する• canaryがあるため検知されて処理が終了してしまう
EXIT
•バイナリが終了する
動作解析
• Bossとバトルしているみたい
• Use Skillでスキルを使ってBossのHPを減らしている
• Skillによって与えられるダメージは違う
• Bossからも攻撃される
• shieldの選択しだいではBossからの攻撃も防げる
•何をすればいいのか?
動作解析
•フラグを出力する処理はバイナリ中に存在している
•この処理が呼ばれる条件は?
動作解析
• Bossに4回勝てばフラグを表示する処理へと分岐する
動作解析
•ボスの攻撃を防ぐshieldの選択は必ず当てることができる
• time(NULL)を元にしたsrandを使用している
•同様に、同じ時間にtime(NULL)すれば同じ乱数が得られる
•乱数を得るプログラムを書き、同時に実行させて乱数を予測する
•この部分はRace Conditionとはあまり関係ないので割愛します
動作解析
• skillは250回しか使用できない
• 250回目の使用後に強制終了
• (BossのHPがとんでもないことに…)
動作解析
•レベル4のBossのHP初期値は0x7fffffff_fffffffe (9223372036854775806)
•初期のattackでは50しかHPが減らない
•他のskillでも多くて50万程度
•まっとうにやっていてはフラグは得られない•なんとかしてHPを0以下にしたい
動作解析
• ここでRace Conditionを考える
• UseSkillの処理は、スレッドを新しく生成して実行される
• start_routineにはUseSkillの処理を行う関数のアドレスがある
• 初の6択とshieldの3択は同一のスレッドで実行される
• UseSkillだけが独立している
動作解析
•選んだskillによっては、sleepするタイミングと秒数が違う
• fireballでは、ダメージ計算後にsleep(1)
• iceballでは、ダメージ計算前にsleep(0)
• magicballでは、ダメージ計算前にsleep(0)
動作解析
• sleep(1)が呼ばれるとどうなるか?
• usedSkillの扱いに誤りがある
• sleep中のUseSkillの処理が終わる前に、再度UseSkillを選択したりChangeSkillすることができる
• これはRace Conditionを起こせそう
動作解析
•スキルによってダメージ処理が違う• 4以下と5以上
• 4以下では、32bitを拡張して64bitにして計算する
• 5以上では、64bitのまま計算する
動作解析
• 4以下は右側
• 5以上は左側の処理がされる
• 4以下では、cdqe命令を使い、raxレジスタの中身を32bitから64bitへ拡張している
動作解析
• iceswordの攻撃値は0xffffffff
• 32bitでは-1
• 64bitでは4294967295
• cdqe命令で拡張されると0xffffffff_ffffffff (-1:64bit)
• iceswordを4以下のSkillの攻撃値にできればよさそう
方針
• 4以下でsleep(1)をするSkillで、UseSkillする
• sleepしている間に、ChangeSkillでiceswordにすり替えてUseSkillする
• 4以下のUseSkillで攻撃値がiceswordの0xffffffffになり、64bit拡張されて-1になって実行される
•攻撃値がマイナス値になって、BossのHPを増やすことができる
EXPLOIT解説
• まずは、3回勝利しBossのレベル4まで上げる
• attackの攻撃値50だと82回攻撃すれば、レベル4になる
• 以下の工程を行うことでBossのHPを1上げることができる
• ChangeSkillでSkillをfireballへ変更
• fireballでUseSkill
• ChangeSkillでSkillをiceswordへ変更
• iceswordでUseSkill
• 整数値オーバーフローで、9223372036854775806 (0x7fffffff_fffffffe)から-9223372036854775808(0x80000000_00000000)
EXPLOIT
• BossのHPをマイナスにすることができ、フラグを得ることができた
• 成功率は低い(bufferingの影響だと思われる)
まとめ
• Race Conditionを起こし、本来なら起こりえない処理を起こした
•マルチスレッド・マルチタスクな開発で、資源のアクセス管理が杜撰だと有り得ない処理が起こりうる