実行ファイルのセキュリティ機構についてまとめてみる

CTFのpwnについて調べているとよくセキュリティ機構の用語が出てきます。しかし、それぞれのセキュリティ機構がどんな役割を果たすのかをよく忘れてしまいます。なので、一度まとめてみました。

実行ファイルのセキュリティ機構について、こちらの書籍を参考にしました。

セキュリティ機構の調べ方

https://github.com/slimm609/checksec.sh

checksecというものがあります。checksecはセキュリティ機構をわかりやすい形式で表示してくれるシェルスクリプトです。

使い方

以下のコマンドを実行すると、ダウンロードすることができます

git clone https://github.com/slimm609/checksec.sh

ダウンロードが完了すると、コマンドを実行した階層にchecksec.shというディレクトリができます。 その中に移動すると、checksecというファイルがあります。これをセキュリティ機構を調べたいファイルがある場所にコピーして、

./checksec --file=<file name>

を実行すると、セキュリティ機構が表示されます。

RELRO

RELRO(RELocation Read Only)はメモリ上のデータのどの部分に対してReadOnly属性を付けるか決定する役割を果たします。

RELROには以下の3種類が存在します。

  • No RELRO
  • Partial RELRO
  • Full RELRO

No RELROの時とPartial RELROのときは、GOT領域が書き込み可能なためGOT overwrite攻撃が成功します。一方、Full RERLOのときはGOT領域を読み込み専用にしてしまうためGOT overwrite攻撃が成功しません。

RELROはコンパイル時に-Wl,-z,norelroを指定すると無効にすることができます。以下に例を示します。

RELRO有効(デフォルト)

$ gcc -o target example.c
$ checksec target
[*] '/home/vagrant/hoge/target'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

RELRO無効

$ gcc -Wl,-z,norelro -o target example.c
$ checksec target
[*] '/home/vagrant/hoge/target'
    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

SSP

SSP(Stack Smashing Protection)はバッファオーバーフローを防ぐための役割を果たします。

SSPでは、関数呼び出し時にリターンアドレスとローカル変数の間にCanary(カナリア)と呼ばれる値をスタックに挿入し、関数の終了時に値が書き換えられているかどうか判定することで、スタックオーバーフローを検出します。

SSPが有効になっている時と無効になっている時の関数呼び出しを例に見てみましょう。

下の図は、SSPが無効になっている時のスタックの様子です。

 +--------------------+      ↑
 | ...                | Low Address
 +--------------------+
 | buffer             |
 +--------------------+
 | ...                |
 +--------------------+
 | saved rbp          |
 +--------------------+
 | ret addr           |
 +--------------------+
 | arg 1              |
 +--------------------+
 | ...                | High Address
 +--------------------+       ↓

このスタックでは、bufferがバッファオーバーフローを起こしても検出することができません。

一方、下の図はSSPが有効になっている時のスタックの様子です。

 +--------------------+      ↑
 | ...                | Low Address
 +--------------------+
 | buffer             |
 +--------------------+
 | ...                |
 +--------------------+
 | canary             |
 +--------------------+
 | saved rbp          |
 +--------------------+
 | ret addr           |
 +--------------------+
 | arg 1              |
 +--------------------+
 | ...                | High Address
 +--------------------+       ↓

SSPが有効になっているときは、Canaryがsaved rbpbufferの間にあることがわかります。この状態でbufferという変数がバッファオーバーフローを起こし、Canaryの値を変えてしまうと、プログラムが強制終了します。

gccではSSPはデフォルトで有効になっています。-fno-stack-protectorオプションをコンパイル時に指定すると、SSPを無効にすることができます。

NX bit

NX bit(No eXecute bit)はメモリ領域に置かれたデータをプログラムとして実行できなくする役割を果たします。WindowsではDEP(Data Execution Prevention)と呼ばれます。

NX bitが有効になっているとシェルコードを使って攻撃するのが困難になります。

gccではデフォルトでNX bitが有効になっています。無効にするときは、gccでは-z execstackというオプションを付けてコンパイルすると、NX bitを無効にすることができます。

ASLR

ASLR(Address Space Layout Randomize)は日本語に訳すと「アドレス空間のランダム配置」という意味になります。

ASLRが有効になっていると、実行ファイルのスタックやヒープ、ライブラリをメモリに配置するときに、アドレスの一部をランダムに配置するようになります。これによって、攻撃者がアドレスを推測するのを困難にする役割を果たします。

スタック領域やヒープ領域、共有ライブラリのアドレスは、

cat /proc/<process ID>/maps

で確認することができます。なので、起動したら入力を受け付けて、それを表示するだけのプログラムを作成し、実際に起動するたびにアドレスが変わっているか確認してみました。

以下はASLRが無効になっているときのスタック領域とヒープ領域のアドレスです。ASLRが無効になっているときは常に以下のアドレスを出力しました。

555555559000-55555557a000 [heap]
7ffffffde000-7ffffffff000 [stack]

cat /proc/<process ID>/mapsを実行すると、本来はアドレスだけではなくパーミッションなども一緒に出力されるのですが、今回注目するのはアドレスだけなのでアドレスの部分だけ抜き出しています。

ASLRを有効にすると次のようになりました。

1回目
562ef2635000-562ef2656000 [heap]
7ffdd3881000-7ffdd38a2000 [stack]

2回目
55d1f63f6000-55d1f6417000 [heap]
7fff6e4e2000-7fff6e503000 [stack]

1回目と2回目で異なるアドレスが表示されていることが分かります。

Ubuntuでは以下のコマンドを入力するとASLRを無効にすることができます。

sudo sysctl kernel.randomize_va_space=0

ALSRを有効に戻すときは以下のコマンドを実行します。

sudo sysctl kernel.randomize_va_space=2

PIE

PIE(Position Independent Executable)は実行コード内のアドレス参照をすべて相対アドレスで行うことで、実行ファイルがメモリ上のどの位置に置かれても、正常に動作実行できるように コンパイルされた実行ファイルのことを指します。

PIEが有効になっていると、特定のアドレスを突く攻撃を成功させることが困難になります。

参考リンク

間違った情報があれば修正します。