More Related Content Similar to MS Officeファイル暗号化のマスター鍵を利用したバックドアとその対策 Similar to MS Officeファイル暗号化のマスター鍵を利用したバックドアとその対策(20) More from MITSUNARI Shigeo More from MITSUNARI Shigeo(20) MS Officeファイル暗号化のマスター鍵を利用したバックドアとその対策3. • サイボウズ・ラボで
クラウドセキュリティ関連のR&D
• 『クラウドを支えるこれからの暗号技術』(2015)
• 内容 : 前方秘匿性, 楕円曲線暗号,
IDベース暗号, 属性ベース暗号, 関数型暗号,
準同型暗号, ゼロ知識証明など
• http://herumi.github.io/ango/
• @ITで「クラウド時代の暗号化技術論」連載
• ペアリング暗号の世界最速実装(2013)
• https://github.com/herumi/ate-pairing
• Software implementation of an Attribute-Based
Encryption Scheme, IEEE trans on computers, 2014
Mitsunari Shigeo(@herumi)
3/54
4. • リクルートマーケティングパートナーズ技術フェロー
• 高知工業高等専門学校 客員准教授
• CODE BLUE review board
• OWASP Japan advisory board
• SECCON 実行委員長
• Shibuya Perl Mongers リーダー
• Microsoft MVP Developer Security in 2008
• 山内奨励賞「x86 JITコンパイラ上で任意のコードを実行する方法」
• 完全日本語訳+解説「ECMA-262 Edition 5.1を読む」(2013)
• コンピュータセキュリティシンポジウム2013 CSS×2.0一等星
Takesako Yoshinori (@takesako)
4/54
7. • 一番単純なもの
• 入力 : 𝑝𝑎𝑠𝑠 : パスワード, 𝑚 : 平文
1. 𝑆 𝐾 = 𝐻𝑎𝑠ℎ 𝑝𝑎𝑠𝑠
2. 𝑐 = 𝐸𝑛𝑐 𝑆 𝐾, 𝑚
3. 出力 : 𝑐
• 問題点
• パスワードが同じなら𝑆 𝐾はいつも同じ
パスワード暗号化
𝑚
𝑝𝑎𝑠𝑠
𝑆 𝐾
𝐻𝑎𝑠ℎ
𝐸𝑛𝑐
𝑚𝑝𝑎𝑠𝑠にのみ依存
7/54
9. • 1秒あたりの試行回数
• SHA1 : 4.2 × 1010回/秒 on 8x NVidia Titan X
• SHA512 : 5.2 × 109回/秒
• 𝐻𝑎𝑠ℎ値から元のパスワードを特定するのにかかる時間
• 𝑝𝑎𝑠𝑠 ∶ 一つの文字を[a-zA-Z0-9]の62文字で8文字とする
• SHA1なら628
4.2 × 1010
= 1時間27分で総当たり可能
hashcatの性能
9/54
10. • saltを追加する
1. 𝑠𝑎𝑙𝑡をランダムに生成する
2. 𝑆 𝐾 = 𝐻𝑎𝑠ℎ 𝑠𝑎𝑙𝑡, 𝑝𝑎𝑠𝑠
3. 𝑖𝑣 : 初期化ベクトル
4. c = 𝐸𝑛𝑐(𝑖𝑣, 𝑆 𝐾, 𝑚)
• 同じパスワードでも𝑆 𝐾は異なる
• 𝐻𝑎𝑠ℎ 𝑠𝑎𝑙𝑡1 + ′abc′ ≠ 𝐻𝑎𝑠ℎ(𝑠𝑎𝑙𝑡2 + ′abc′)
• レインボーテーブル攻撃に対して耐性が増える
より安全なフォーマット
𝑝𝑎𝑠𝑠
𝐻𝑎𝑠ℎ
𝑠𝑎𝑙𝑡
𝑆 𝐾 𝑚
𝐸𝑛𝑐
𝑚
𝑖𝑣
10/54
11. • ハッシュをたくさん繰り返す
• 𝑑1 = 𝐻𝑀𝐴𝐶(𝑝𝑎𝑠𝑠, 𝑠𝑎𝑙𝑡)
• 𝑛 is iteration count
• for 𝑖 = 1 to 𝑛 − 1:
• 𝑑𝑖+1 = 𝐻𝑀𝐴𝐶(𝑑𝑖, 𝑠𝑎𝑙𝑡)
• 攻撃能力が1/𝑛になる
• PKCS#5(RFC 2898)
• パスワードベースの暗号仕様
• PBKDF2(password based key
derivation functions)
• ZIPなどで使われている
鍵ストレッチング
𝑝𝑎𝑠𝑠
𝐻𝑀𝐴𝐶
𝑑𝑖
𝑆 𝐾 = 𝑑1 ⊕ 𝑑2 ⊕ ⋯
𝑛
𝑠𝑎𝑙𝑡
𝑝𝑎𝑠𝑠
𝐻𝑀𝐴𝐶
𝑑𝑖+1
11/54
13. • Passcoveryによる8バイトパスワードの全数探索
• on GeForce GTX860M(640SP/ALU)@1019MHz
• Office 2013 docxは強い
• 最近の動向はメモリを酷使するタイプのフォーマット
• Argon2が2015/7/20にパスワードハッシュコンペで優勝
攻撃にかかる時間の比較
File format # of tries/sec hash stretching days
ZIP(96-bit) 230000000 none 10 days
Office2003 doc 11000000 ? 220 days
ZIP(256-bit AES) 370000 1000 x HMAC SHA1 18 years
Office2007 docx 16000 50000 x SHA1 430 years
Office2010 docx 8100 100000 x SHA1 854 years
Office2013 docx 337 100000 x SHA512 20000 years
13/54
14. • パスワード暗号化フォーマットの強度比較
• デモ
• MS Office暗号化ファイルの概要
• 暗号鍵生成
• 自作ツールの紹介
• デモ
• 問題となる状況
• MS Officeファイルフォーマット
• バグを見つけたきっかけ
• バックドア対策の信頼できるフォーマットの提案
目次
14/54
16. • ハッシュアルゴリズム𝐻(𝑝𝑎𝑠𝑠, 𝑠𝑎𝑙𝑡)
• ℎ0 = 𝐻𝑎𝑠ℎ(𝑠𝑎𝑙𝑡, 𝑝𝑎𝑠𝑠)
• 𝑛 : 繰り返し回数
• for 𝑖 = 1 to 𝑛:
ℎ𝑖 = 𝐻𝑎𝑠ℎ < 𝑖 > +ℎ𝑖−1
• < 𝑖 > : 4バイトリトルエンディアン
MS Officeの暗号鍵生成
𝑝𝑎𝑠𝑠
ℎ 𝑜
𝐻𝑎𝑠ℎ
𝑠𝑎𝑙𝑡
ℎ𝑖−1𝑖
𝐻𝑎𝑠ℎ
ℎ𝑖
𝑛
𝑆 𝐾 ≔ ℎ 𝑛
16/54
17. • 二段階の秘密鍵を使う
• 𝐻 : 前述のハッシュ関数
1. 𝑝𝑎𝑠𝑠と𝑠𝑎𝑙𝑡から秘密鍵𝑠を生成
2. 秘密鍵𝑆 𝐾を生成し𝑠で暗号化
3. 𝑆 𝐾で本体𝑚を暗号化
• 詳細は後述
• 二段階なのは鍵供託のため
• パスワードを忘れたとき
管理者が復号できる
• 𝑆 𝐾を管理者の公開鍵で暗号化
• デフォルトはオフ
MS Office Agile format
𝑚
𝑝𝑎𝑠𝑠
𝑆 𝐾
Enc by 𝑆 𝐾
𝑆 𝐾
𝑚
Enc by 𝑠
𝑠
𝐻
𝑠𝑎𝑙𝑡
17/54
18. • https://github.com/herumi/msoffice/
• MS Officeファイルの暗号化・復号ツール
• Windows/Linux両対応
• Office 2007~のOpenXMLに対応
• Office 2010~のAgile formatにも対応
• LibreOfficeはまだAgile formatに対応していない
• Agile formatの秘密鍵を指定できる
• ストレッチングの回数を指定できる
msoffice-crypt
18/54
20. • パスワード"test"で暗号化
• パスワード"test"で復号
• パスワード無しで解読
使い方
"test"でeasy.xlsxを
復号して𝑆 𝐾を取得
パスワード無しで𝑆 𝐾を使ってcomplex.xlsxを解読
msoffice-crypt -d complex.xlsx -by easy.xlsx -p test
msoffice-crypt -e plain.xlsx encoded.xlsx –p test
msoffice-crypt -d encoded.xlsx decoded.xlsx –p test
20/54
24. • 所有者
• 定型ファイルを簡単なパスワードで保存
• 重要な情報を書いて強いパスワードで保存
• 攻撃者
• 簡単なパスワードを破って強いパスワードファイルを解読
シナリオ2(PCの紛失)
簡単なパスワード
への総当たり攻撃
強いパスワードで保存
社外秘を書く
こちらを解読
PC
24/54
26. • 古いフォーマットと新しいフォーマット
• MS OLE2のヘッダは"D0 CF 11 E0"
MS Office暗号化フォーマットの種類
Office file type Format
doc, ppt, xls (old Office files) MS OLE2
plain docx, pptx, xlsx ZIP file of Open XML files
encrypted docx, pptx, xlsx MS OLE2 including a header
and an encrypted ZIP file
ZIP files (Open XML)
Enc(ZIP files)
AESで暗号化
header
通常のファイル
暗号化
26/54
28. • standard暗号化 ~Office 2007
• バイナリフォーマット
• SHA-1のみ, spinCount(=# of iteration)は50000固定
• Agile暗号化 Office 2010~
• XmlEncryptionDescriptorを含む
• SHA-1, SHA256, ...をサポート
• spinCount可変
EncryptionInfoの種類
28/54
29. XmlEncryptionDescriptor
<encryption>
<keyData saltSize="16" blockSize="16" keyBits="256" hashSize="64"
cipherAlgorithm="AES" cipherChaining="ChainingModeCBC"
hashAlgorithm="SHA512" saltValue="..."/>
<dataIntegrity encryptedHmacKey="..." encryptedHmacValue="..."/>
<keyEncryptors><keyEncryptor
uri="http://schemas.microsoft.com/office/2006/keyEncryptor/password">
<p:encryptedKey spinCount="100000"
saltSize="16" blockSize="16" keyBits="256" hashSize="64" cipherAlgorithm="AES"
cipherChaining="ChainingModeCBC" hashAlgorithm="SHA512" saltValue="..."
encryptedVerifierHashInput="..."
encryptedVerifierHashValue="..."
encryptedKeyValue="..."/>
</keyEncryptor></keyEncryptors>
</encryption>
29/54
34. • パスワード暗号化フォーマットの強度比較
• デモ
• 問題となる状況
• MS Officeファイルフォーマット
• バグを見つけたきっかけ
• 動機
• 暗号学的安全な擬似乱数の紹介
• 既存のバックドアの例
• MS Officeの鍵生成部をフックする
• バックドア対策の信頼できるフォーマットの提案
目次
34/54
35. • 正規のエンコーダ
• 𝑚の暗号化部
• 𝑆 𝐾がないと誰も(𝑠𝑎𝑙𝑡, 𝑐)を復号できない
• 𝑆 𝐾の生成を制御できればバックドアを作れる?
𝑠𝑎𝑙𝑡をランダム生成
𝑆 𝐾をランダム生成
𝑐 = 𝐸𝑛𝑐 𝑆 𝐾, 𝑠𝑎𝑙𝑡, 𝑚
動機
𝑚 (𝑠𝑎𝑙𝑡, 𝑐)
35/54
38. • PRG(Pseudo Random Generator)
• ゲームやシミュレーションでよく使われる
• MT(Mersenne Twister)が有名
• CSPRG(Cryptographically Secure PRG)
• 過去のビット列から次のビットを予測できない
• 秘密鍵の生成にはこれを使わなければならない
• MTはCSPRGではない
• 624x4バイトの出力を見ると内部状態が確定する
暗号論的擬似乱数生成器(CSPRG)
0 1 0 0 1 1 1 0 1 ?
known previous bits
CSPRG
next bit
38/54
40. • IntelのハードウェアによるCSPRG命令
• NIST SP 800-90A標準に適合
• チップ上の非決定的なエントロピーソースを利用
• 使いやすい
• 安全に使うのは難しい
• ビジーループの可能性があるのでリトライ上限を設けるべき
(極めてまれ)
rdrand
// uint64_t getRand();
getRand:
.lp:
rdrand rax // raxに乱数がセットされる
jnc .lp // 失敗すればやりなおし(まれ)
ret
40/54
42. • Microsoft CryptoAPIのCSPRG
• saltや秘密鍵の生成に使われる
• この関数をフックしてみよう
• MS Officeも秘密鍵を作るのにこの関数を使ってるだろう
• CryptGenRandomをいつも同じ値を返すようにすれば、
秘密鍵も固定化されるのでは?
• 自作の (とても古い) DLL injectionライブラリで試す
• ASLRのせいでうまく動かなかった
CryptGenRandom()
42/54
43. • MS Reserachが提供するWin32 APIフックライブラリ
• http://research.microsoft.com/en-us/projects/detours/
• 64-bit版は1,234,286円 (32-bit版は無料)
• 使い方
• フックしたいdllのソース
Detoursライブラリ (1/2)
BOOL HookCryptGenRandom(HCRYPTPROV, DWORD len, BYTE *p) {
memset(p, 'a', len);
return TRUE;
}
BOOL DllMain(HINSTANCE, DWORD reason, LPVOID) {
if (reason == DLL_PROCESS_ATTACH) {
orgFunc = DetourFindFunction("adapi32.dll", "CryptGenRandom");
DetourAttach(&orgFunc, HookCryptGenRandom);
...
43/54
44. • test.exe
• Detours付属のwithdll.exeで起動する
• CryptGenRandomをフックできた
• しかしMS Officeはこの関数を呼んでいなかった...
Detoursライブラリ (2/2)
int main() {
RandomGenerator rg; // wrapper of CryptGenRandom()
for (int i = 0; i < 3; i++) printf("%08x¥n", rg.get32());
}
>test.exe
812e1af0 // random
ad990e76
865cb964
>withdll.exe /d:hook.dll test.exe
61616161 // "aaaa"
61616161
61616161
44/54
46. • rsaenh.dllのシンボルを見てみる
• dumpbin /exports rsaenh.dll
• CPGenRandomって何?
試行錯誤 (2/3)
ordinal hint RVA name
1 0 0000230C CPAcquireContext
2 1 00003A80 CPCreateHash
3 2 0001CC1C CPDecrypt
4 3 0001DBC8 CPDeriveKey
...
11 A 00009A80 CPGenKey
12 B 00001D3C CPGenRandom
46/54
47. • CPxxx関数は旧式の関数
• Cryptxxxにリネームされた
• Cryptxxxは内部でCPxxxにジャンプする
• CPxxxをフックすればCryptxxxも自動的にフックされる
• ExcelはCPGenRandomを呼んでいた
• 目論見通り同じ秘密鍵を生成したようにみえる
• しかし
試行錯誤 (3/3)
>msoffice-crypt –psk easy.xlsx –p test
...
secretKey = 8BBE31319EA4CAB9F...33013EB8853F8C6A7F5
>msoffice-crypt –psk complex.xlsx –p testtest
...
secretKey = 8BBE31319EA4CAB9F...33013EB8853F8C6A7F5
47/54
48. • フックしなくても同じ秘密鍵を生成した
• MS Office Word, PowerPointでは異なる秘密鍵だった
• Excelのみの現象
• CPGenRandomのフック
• これだけでは秘密鍵生成のコントロールには不十分だった
• タイマー関係もフックしてみたがまだ足りない
• 詳細は未調査
Excelのバグだった
48/54
49. • パスワード暗号化フォーマットの強度比較
• デモ
• 問題となる状況
• MS Officeファイルフォーマット
• バグを見つけたきっかけ
• バックドア対策の信頼できるフォーマットの提案
• 既存ファイルのチェック
• バックドアを入れられないフォーマットの提案
目次
49/54
50. • このバグは10/13のWindows Updateで修正された
• https://technet.microsoft.com/ja-jp/library/security/ms15-110.aspx
• しかし既に生成されたファイルは修正されない
• msoffice-cryptで同じ秘密鍵を持っていないか確認
• 同じ秘密鍵を見つけたら再暗号化したほうがよい
手元のExcelファイルを調べよう
50/54
51. • 信頼できるフォーマットとは?
• MS Officeフォーマットは安全だが、
バックドアがないことを証明するのは難しい
• バイナリ提供される暗号化ツール全般にいえる問題
• (再掲) 不正なエンコーダ
• バックドアがないと証明できるフォーマットが欲しい
今後の課題
𝑚 𝑠𝑎𝑙𝑡, 𝑐 , 𝑆 𝐾
blackbox
encoder
𝑠𝑎𝑙𝑡 : 乱数
𝑋 : 不正なエンコーダ内のマスター秘密鍵
𝑆 𝐾 : 𝐻(𝑠𝑎𝑙𝑡, 𝑋)
Eve gets 𝑆 𝐾 by (𝑠𝑎𝑙𝑡, 𝑋)
51/54
52. • 𝑠𝑎𝑙𝑡もKDF(Key Derivation関数)で生成する
1. 𝑟0, 𝑟1を生成する
2. 𝑠𝑎𝑙𝑡 = 𝐻 𝑝𝑎𝑠𝑠, 𝑟0 , 𝐻 : KDF
3. 𝑆 𝐾 = 𝐻(𝑝𝑎𝑠𝑠, 𝑟1)
4. 𝑐 = 𝐸𝑛𝑐 𝑟0, 𝑟1, 𝑚 by 𝑠𝑎𝑙𝑡, 𝑆 𝐾
5. 出力: 𝑐, 𝑠𝑎𝑙𝑡
• フォーマットの確認
• 上記手順に従っていることを確認する
1. 𝑟0, 𝑟1, 𝑚 ≔ 𝐷𝑒𝑐 𝑐
2. 𝑠𝑎𝑙𝑡 =
?
𝐻(𝑝𝑎𝑠𝑠, 𝑟0)
3. 𝑆 𝐾 =
?
𝐻(𝑝𝑎𝑠𝑠, 𝑟1)
バックドア対策のフォーマット
𝑆 𝐾 𝑚
𝑚
𝑟0 𝑟1𝑝𝑎𝑠𝑠
𝐻 𝐻
𝑠𝑎𝑙𝑡
𝐸𝑛𝑐
52/54
53. • (𝑐, 𝑠𝑎𝑙𝑡)しか知らない第三者にとって
• 従来と同じ困難さ
• Eveにとって
• 𝑟0が分かっているとき𝑠𝑎𝑙𝑡から𝑝𝑎𝑠𝑠を
求めるのはKDFの困難さと同程度
• 𝑟0が固定だとユーザにすぐばれてしまう
• たとえば1万回エンコードして𝑟0が
みな異なっていれば安心?
• Eveが解読する困難さは1万倍になる
提案フォーマットの困難さ
𝑆 𝐾 𝑚
𝑚
𝑟0 𝑟1𝑝𝑎𝑠𝑠
𝐻 𝐻
𝑠𝑎𝑙𝑡
𝐸𝑛𝑐
53/54