【解説】任意コード実行とは何か?バッファオーバーフローはどう危険なのか?


任意コード実行の脆弱性がどうとか言われてもピンとこない。
バッファオーバーフローもただアプリ落ちるだけじゃんと思っている。

そんな人向けに何故騒がれるのか説明してみようという記事です。

任意コード実行ってなに?

簡単に言うと「PCやスマホであなたが出来ること大体全部を他人がやれてしまう穴」が見つかったという意味です。

SNSにあなたのふりして投稿したり、アカウント自体消したり、保存してある画像を全部消したり、あなた名義で好き放題課金したり、あなたの名義でウイルスをばらまいたりできます。

こういう何でもできる所が"任意"なわけですね。

何でもできるということは、ウイルス.exeを複製してそこら中に仕込むこともできます。
任意コード実行で攻撃されたら再インストールか捨てるしかないのも恐ろしいところです。
業務中に穴を突かれて会社のサーバーにも広がって大変な目に合う人もいます。

なにすると任意コード実行になるの?

色々ありますが代表的な原因にバッファオーバーフローがあります。

セキュリティの世界では、バッファオーバーフローが見つかる=任意コード実行を警戒して使用を控える、って空気感です。
バッファオーバーフローが危険と言われるのはそのせいだったんですね。

バッファオーバーフローがどうなって任意コード実行に?

「メモリに次に実行するアドレスがメモしてありますが、バッファオーバーフローで好きに上書きできてしまうから」です。

って言われてもピンとこないと思うので順に説明します。

まずは説明用C言語のコードをドン!

#include <stdio.h>
#include <limits.h>
#include <string.h>

void hoge() {
   printf("Hoge!");
}

int main() {
   char b = 'A';
   char a[4];
   fgets(a, INT_MAX, stdin);
   printf("%c\n", b);
   return 0;
}

※本来ならfgetsした内容を使ってなんか処理するんですが省略。
※hoge()が呼ばれていないのも同上。

このままだと単に入力受け付けてから「A」と出力して終わるだけです。

しかしfgetsがaのサイズではなくINT_MAX(※巨大な数)で受けているためバッファオーバーフローが発生しています。

なので適当にガチャガチャ入力してやると。

こうなります。

さて、ではここから任意コード実行を試みます。

レッツ任意コード実行!

まずメモリーをexcelに例えます!

「そうはならんやろ」って言われそうですがExcelに例えるんです!

とりあえず今回のアプリを当てはめるとこんな感じ。

fgets呼び出しは「この図の上から順に入力で埋めていく処理」と言えるでしょう。

並び順は、変数aが居て、よくわからないものが3byteいて、変数bがいて、また何かが~って感じですね。

1文字1byteで、途中のprintfは変数bを表示しているのだから。
fgetsに8文字入力したら表示変わりそうじゃないですか?やってみましょう。

無事出力が8文字目に変化しました!
※よく見ると以前の例外している画像でも8文字目が出力されてたりします。

メモリー図に反映させるとこんな感じ。

こうしてみると"mainの次に実行するアドレス"を上書きしてみたくなりませんか?なりますよね?
ところでhoge()関数のアドレスは0x2044D420で、これは文字であらわすと「 ヤD 」なんですよ。

えいっ

おぉ、hoge()関数が実行されたではないですか!

この時のメモリー。

解説

あんな感じで"○○したら実行するアドレス"は実はメモリー上にたくさんあります。

  • 関数呼び出しが終わったら戻る先のアドレス
    • 今回のはこれ
  • 例外したら実行するアドレス
  • そのインスタンスのメソッドのアドレス
  • 関数ポインターの中身

などなど。

それらを1つでも上書きされると好きな関数を呼ばれてしまい、ファイル作られたり外部と通信されて好き放題されます。

つまりメモリーを好きに書き換えられると、それだけで攻撃には十分ということなんです。

もちろんこれらへの対策もいくつもあって、対策を回避するための攻撃もいっぱいあるのですが、そういう話はまた今度ということで。