1月6日(金)1、2コマ目
今日、やったこと
バッファオーバーフロー
今日のホワイトボード
バッファオーバーフローとは
バッファオーバーランとも呼ばれる。
メモリ上の確保済みエリアのサイズを超えてデータをコピーすることで、未確保部分にも上書きされること。
![]() |
| 図 バッファオーバーフロー |
バッファオーバーフローはセキュリティインシデントの要因ナンバー1(と思われる)。
そもそもC言語はメモリ保護がないため、簡単に不具合を作ってしまう。
また、バッファーオーバーフローが特定の場合のみ発生するため、テストで露見しにくい。
メモリは
コンピュータのメモリはプログラム実行時に以下のように3つのエリアで使い分けられる。
![]() |
| 図 メモリ |
サンプルプログラムでバッファオーバーフロー発生
サンプルプログラム「bof_sample1.c」はstrcpy()でバッファオーバーフローを引き起こし、変数auth_flagの値を書き換えます。
変数auth_flag、password_bufferのアドレス
デバッガでプログラム実行中のメモリの状態(auth_flag、password_buffer)を確認します。
![]() |
| 図 auth_flag、password_bufferのアドレス |
auth_flag、password_bufferのアドレスから、メモリ上では以下のように配置されていることがわかります。
![]() |
| 図 メモリ上でのauth_flag、password_buffer |
実際にバッファオーバーフローを引き起こしてみます。
バッファオーバーフロー発生時のメモリ[strcpy()前]
メモリは以下のとおり。
![]() |
| 図 auth_flag、password_bufferのアドレス |
![]() |
| 図 strcpy()前のメモリ |
auth_flagは0で初期化しているため、0です。(当然)
バッファオーバーフローでのメモリ[strcpy()後]
strcpy()で引数passwordの値を配列password_bufferにコピーすると、バッファーオーバーフローが発生します。
![]() |
| 図 auth_flag、password_bufferのアドレス |
![]() |
| 図 strcpy()後のauth_flag、password_buffer |
まとめ
なにも考えずにstrcpy()を使っていることが原因ですが、それ以外にも不具合の要因はあります。
![]() |
| 図 このプログラムの問題点 |
strcpy()の問題とif()の問題はC言語が持つ問題。
if()の使い方はプログラマの問題。
バッファオーバーフローでリターンアドレス書き換え
バッファオーバーフローを使えば、もっといろいろなことができます。
たとえば、プログラムの実行順を変えることも可能です。
サンプルプログラム「bof_sample2.c」はbof_sample1.cの問題点を修正したものの、根本原因のstrcpy()を使っているため、バッファオーバーフローが発生します。このサンプルプログラムで異なるバッファオーバーフローを引き起こしてみます。
リターンアドレスとは
プログラムを実行すると、実行ファイルがコードエリアにロードされ、順に実行します。
関数を呼び出すと関数実行後は関数呼び出し元に戻ります。
関数呼び出し元に戻る際、コードエリアの戻るべきアドレスをリターンアドレスと呼びます。関数実行時にスタック上にリターンアドレスを記録して、関数を実行します。
![]() |
| 図 リターンアドレス |
リターンアドレスもローカル変数と同じスタックエリアに書き込まれます。
バッファオーバーフローでリターンアドレスも書き換えができそうです。
![]() |
| 図 check()関数でのスタックエリア |
次回は
バッファオーバーフローでリターンアドレスを書き換えてプログラムの処理順序を変更します。










