ポタージュを垂れ流す。

マイペースこうしん(主に旅行)

ASLR

例のリレーブログ*1の時間です。前の僕の記事はこれ、前回の方のブログはこちらになります。

今回僕に与えられたテーマはASLR。聞いたことないワードだったので毎度のごとく少し調べて、今回は試してみたことを書いていこうと思う。

ASLRとは

ASLR(Address Space Layout Randomization、アドレス空間配置のランダム化)とは、重要なデータ領域の位置(スタックやヒープの位置など)を無作為に配置するOSのセキュリティ技術のこと。現在よく使われているOSにはこの機能が標準搭載されている。

なんでそんなことするんだ、と思うかもしれないが、この技術は例えばスタックバッファオーバーフロー攻撃に有効な防御手段となる。入力サイズの上限の指定ができなかったり、その指定を怠った時に、大量の入力をすると、スタック領域を超えた場所にあるデータが上書きされてしまうことがある。これを悪用して呼び出し元のプログラムへの戻りアドレスであるリターンアドレスを書き換え、別のプログラムを実行させるといったことができてしまう。これに対してアドレスのランダム化を行えば、攻撃の成功率を下げることができる。

ASLRを確認する

ASLRあり

実際にASLRがどう動いているのか確かめてみる。今回は床に転がっていたraspberry piを使う。

pi@raspberrypi:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.11 (stretch)
Release:    9.11
Codename:   stretch

適当なコードを実行させてメモリマップを見てみる。

pi@raspberrypi:~$ sleep 100 &
[1] 996
pi@raspberrypi:~$ sleep 100 &
[2] 997

100秒スリープするプロセスを2つ走らせてみた。これら2つのメモリマップを確認してみる。

pi@raspberrypi:~$ cat /proc/996/maps
00010000-00016000 r-xp 00000000 b3:07 391782     /bin/sleep
00025000-00026000 r--p 00005000 b3:07 391782     /bin/sleep
00026000-00027000 rw-p 00006000 b3:07 391782     /bin/sleep
002d0000-002f1000 rw-p 00000000 00:00 0          [heap]
76d3c000-76e55000 r--p 00000000 b3:07 14166      /usr/lib/locale/locale-archive
76e55000-76f7f000 r-xp 00000000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f7f000-76f8e000 ---p 0012a000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f8e000-76f90000 r--p 00129000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f90000-76f91000 rw-p 0012b000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f91000-76f94000 rw-p 00000000 00:00 0 
76faa000-76faf000 r-xp 00000000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76faf000-76fbe000 ---p 00005000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76fbe000-76fbf000 r--p 00004000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76fbf000-76fc0000 rw-p 00005000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76fc0000-76fe1000 r-xp 00000000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
76fee000-76ff0000 rw-p 00000000 00:00 0 
76ff0000-76ff1000 r--p 00020000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
76ff1000-76ff2000 rw-p 00021000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
7ec25000-7ec46000 rw-p 00000000 00:00 0          [stack]
7eff0000-7eff1000 r-xp 00000000 00:00 0          [sigpage]
7eff1000-7eff2000 r--p 00000000 00:00 0          [vvar]
7eff2000-7eff3000 r-xp 00000000 00:00 0          [vdso]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]
pi@raspberrypi:~$ cat /proc/997/maps
00010000-00016000 r-xp 00000000 b3:07 391782     /bin/sleep
00025000-00026000 r--p 00005000 b3:07 391782     /bin/sleep
00026000-00027000 rw-p 00006000 b3:07 391782     /bin/sleep
01562000-01583000 rw-p 00000000 00:00 0          [heap]
76cc3000-76ddc000 r--p 00000000 b3:07 14166      /usr/lib/locale/locale-archive
76ddc000-76f06000 r-xp 00000000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f06000-76f15000 ---p 0012a000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f15000-76f17000 r--p 00129000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f17000-76f18000 rw-p 0012b000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f18000-76f1b000 rw-p 00000000 00:00 0 
76f31000-76f36000 r-xp 00000000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76f36000-76f45000 ---p 00005000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76f45000-76f46000 r--p 00004000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76f46000-76f47000 rw-p 00005000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76f47000-76f68000 r-xp 00000000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
76f75000-76f77000 rw-p 00000000 00:00 0 
76f77000-76f78000 r--p 00020000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
76f78000-76f79000 rw-p 00021000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
7e91a000-7e93b000 rw-p 00000000 00:00 0          [stack]
7e98f000-7e990000 r-xp 00000000 00:00 0          [sigpage]
7e990000-7e991000 r--p 00000000 00:00 0          [vvar]
7e991000-7e992000 r-xp 00000000 00:00 0          [vdso]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

差分を見てみる。

pi@raspberrypi:~$ diff <(cat /proc/996/maps)  <(cat /proc/997/maps)
4,22c4,22
< 002d0000-002f1000 rw-p 00000000 00:00 0          [heap]
< 76d3c000-76e55000 r--p 00000000 b3:07 14166      /usr/lib/locale/locale-archive
< 76e55000-76f7f000 r-xp 00000000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
< 76f7f000-76f8e000 ---p 0012a000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
< 76f8e000-76f90000 r--p 00129000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
< 76f90000-76f91000 rw-p 0012b000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
< 76f91000-76f94000 rw-p 00000000 00:00 0 
< 76faa000-76faf000 r-xp 00000000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
< 76faf000-76fbe000 ---p 00005000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
< 76fbe000-76fbf000 r--p 00004000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
< 76fbf000-76fc0000 rw-p 00005000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
< 76fc0000-76fe1000 r-xp 00000000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
< 76fee000-76ff0000 rw-p 00000000 00:00 0 
< 76ff0000-76ff1000 r--p 00020000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
< 76ff1000-76ff2000 rw-p 00021000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
< 7ec25000-7ec46000 rw-p 00000000 00:00 0          [stack]
< 7eff0000-7eff1000 r-xp 00000000 00:00 0          [sigpage]
< 7eff1000-7eff2000 r--p 00000000 00:00 0          [vvar]
< 7eff2000-7eff3000 r-xp 00000000 00:00 0          [vdso]
---
> 01562000-01583000 rw-p 00000000 00:00 0          [heap]
> 76cc3000-76ddc000 r--p 00000000 b3:07 14166      /usr/lib/locale/locale-archive
> 76ddc000-76f06000 r-xp 00000000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
> 76f06000-76f15000 ---p 0012a000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
> 76f15000-76f17000 r--p 00129000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
> 76f17000-76f18000 rw-p 0012b000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
> 76f18000-76f1b000 rw-p 00000000 00:00 0 
> 76f31000-76f36000 r-xp 00000000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
> 76f36000-76f45000 ---p 00005000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
> 76f45000-76f46000 r--p 00004000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
> 76f46000-76f47000 rw-p 00005000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
> 76f47000-76f68000 r-xp 00000000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
> 76f75000-76f77000 rw-p 00000000 00:00 0 
> 76f77000-76f78000 r--p 00020000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
> 76f78000-76f79000 rw-p 00021000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
> 7e91a000-7e93b000 rw-p 00000000 00:00 0          [stack]
> 7e98f000-7e990000 r-xp 00000000 00:00 0          [sigpage]
> 7e990000-7e991000 r--p 00000000 00:00 0          [vvar]
> 7e991000-7e992000 r-xp 00000000 00:00 0          [vdso]

これから、[heap]から[vdso]まで、ヒープやスタックなどは違うアドレスになっていることがわかる。

もうちょっと直接的に(?)見てみる。C言語のmain関数の中で定義した変数(ローカル変数)はスタックメモリに配置されるので、試しに以下のような適当なローカル変数のアドレスを表示するだけのプログラム

#include <stdio.h>

int main() {
    int x;
    printf("%p\n",&x);
    return 0;
}

を書いて、10回実行してみると

pi@raspberrypi:~$ gcc test.c -o test
pi@raspberrypi:~$ for x in {0..9}; do ./test; done
0x7e9496e4
0x7ee156e4
0x7ea486e4
0x7ed7e6e4
0x7efc56e4
0x7eb376e4
0x7eea06e4
0x7ea146e4
0x7e8196e4
0x7e8a96e4

このように全て異なるアドレスになっていることがわかる。

ASLRなし

Linuxの場合、sudo sysctl -w kernel.randomize_va_space=0とすれば、ASLRを切ることができる。逆にsudo sysctl -w kernel.randomize_va_space=2とすればASLRありの状態に戻る。

ASLRなしの状態で上のsleepコマンドとCのプログラムを走らせてみる。

pi@raspberrypi:~$ cat /proc/1019/maps
00010000-00016000 r-xp 00000000 b3:07 391782     /bin/sleep
00025000-00026000 r--p 00005000 b3:07 391782     /bin/sleep
00026000-00027000 rw-p 00006000 b3:07 391782     /bin/sleep
00027000-00048000 rw-p 00000000 00:00 0          [heap]
76d4a000-76e63000 r--p 00000000 b3:07 14166      /usr/lib/locale/locale-archive
76e63000-76f8d000 r-xp 00000000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f8d000-76f9c000 ---p 0012a000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f9c000-76f9e000 r--p 00129000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f9e000-76f9f000 rw-p 0012b000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f9f000-76fa2000 rw-p 00000000 00:00 0 
76fb8000-76fbd000 r-xp 00000000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76fbd000-76fcc000 ---p 00005000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76fcc000-76fcd000 r--p 00004000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76fcd000-76fce000 rw-p 00005000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76fce000-76fef000 r-xp 00000000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
76ff9000-76ffb000 rw-p 00000000 00:00 0 
76ffb000-76ffc000 r-xp 00000000 00:00 0          [sigpage]
76ffc000-76ffd000 r--p 00000000 00:00 0          [vvar]
76ffd000-76ffe000 r-xp 00000000 00:00 0          [vdso]
76ffe000-76fff000 r--p 00020000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
76fff000-77000000 rw-p 00021000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
7efdf000-7f000000 rw-p 00000000 00:00 0          [stack]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]
pi@raspberrypi:~$ cat /proc/1020/maps
00010000-00016000 r-xp 00000000 b3:07 391782     /bin/sleep
00025000-00026000 r--p 00005000 b3:07 391782     /bin/sleep
00026000-00027000 rw-p 00006000 b3:07 391782     /bin/sleep
00027000-00048000 rw-p 00000000 00:00 0          [heap]
76d4a000-76e63000 r--p 00000000 b3:07 14166      /usr/lib/locale/locale-archive
76e63000-76f8d000 r-xp 00000000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f8d000-76f9c000 ---p 0012a000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f9c000-76f9e000 r--p 00129000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f9e000-76f9f000 rw-p 0012b000 b3:07 526355     /lib/arm-linux-gnueabihf/libc-2.24.so
76f9f000-76fa2000 rw-p 00000000 00:00 0 
76fb8000-76fbd000 r-xp 00000000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76fbd000-76fcc000 ---p 00005000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76fcc000-76fcd000 r--p 00004000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76fcd000-76fce000 rw-p 00005000 b3:07 11311      /usr/lib/arm-linux-gnueabihf/libarmmem.so
76fce000-76fef000 r-xp 00000000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
76ff9000-76ffb000 rw-p 00000000 00:00 0 
76ffb000-76ffc000 r-xp 00000000 00:00 0          [sigpage]
76ffc000-76ffd000 r--p 00000000 00:00 0          [vvar]
76ffd000-76ffe000 r-xp 00000000 00:00 0          [vdso]
76ffe000-76fff000 r--p 00020000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
76fff000-77000000 rw-p 00021000 b3:07 526228     /lib/arm-linux-gnueabihf/ld-2.24.so
7efdf000-7f000000 rw-p 00000000 00:00 0          [stack]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

差分をとってみると

pi@raspberrypi:~$ diff <(cat /proc/1019/maps)  <(cat /proc/1020/maps)
pi@raspberrypi:~$ 

ということでキレイに何も出力されなかったので、全く同じアドレスになっている。

Cのプログラムも先ほど同様10回走らせてみると

pi@raspberrypi:~$ for x in {0..9}; do ./test; done
0x7efff6e4
0x7efff6e4
0x7efff6e4
0x7efff6e4
0x7efff6e4
0x7efff6e4
0x7efff6e4
0x7efff6e4
0x7efff6e4
0x7efff6e4

ということで全く同じアドレスになった。

*1:seccampのグループワークから生まれた企画。リレーブログのルール:前の人がが次の人のテーマを決める