KEEP LEARNING

情報処理の学習

【仕組みを理解しよう】バッファオーバーフロー

f:id:food_blog:20200518000251p:plain

本記事ではセキスペ 過去問(H.30/秋 午後I 問1)を例題として解説する中でバッファオーバフローの理解を深めます。

※IPA公式サイトから実際の問題を使用しております。 

 

 

1.前提知識

  • バッファオーバフロー
  • スタック領域

 

2.知識のインプット

スタックバッファオーバーフロー 

f:id:food_blog:20200515102822p:plain

 

図のように、本来の空き領域に収まらず、他のバッファ領域が上書きされてしまい、リターンアドレスと呼ばれる次に実行すべき処理の指示も書き換えられ、想定しない命令が実行されてしまうことをバッファオーバーフローと言います。

 

 

ASLR (Address Space Layout Randomization)

 

ASLRは配置予測を困難にするために生まれた技術であり、アドレスの配置場所をランダムに変える技術です。

 

スタックオーバーフローを悪用する場合、攻撃者はアドレスの配置位置を正確に判断する必要がります。

 

ASLRを利用していない場合は基本的にスタック領域には順番に配置されることから配置位置が予測されやすいという危険性があります。

 

DEP(デップ) 

f:id:food_blog:20200515215429p:plain

通常、バッファオーバーフローはデータ領域に書き込んだウイルスを実行させることを目的としています。

 

DEPはデータ領域にプログラムが置かれた場合はその処理を実行せず強制的に処理を中止させることで、不正なプログラムの実行を防ぐ仕組みです。 

 

Return-to-libc 

f:id:food_blog:20200515223356p:plain

Return-to-libcとは意図的にDEPを無効にできる標準APIを実行させることでデータ領域ないにある不正プログラムを実行させることです。

 

標準APIなので例えばsystem('cmd')を実行させることでコマンドプロンプトを起動させる等のことが可能になります。

 

つまりDEPではブッファオーバーフローによる攻撃を防ぎきることはできません

 

 SSP(Stack Smashing Protector)

 

スタック領域に処理実行前に、canaryと呼ばれる値を挿入し、その値が変わっているかどうかでバッファオーバフロー発生の有無をチェックする仕組みです。

 

ただし、処理前にcannary自体を書き換えられてまうとこのチェックが機能せずバッファオーバフローの発生を検知できなくなります。

 

PIE(Position Independent Executable)

 

ASLRはテキスト領域に対してはランダム配置されないのに対してPIEはテキスト領域に対してもランダム配置できるようになります。

 

Automatic Fortification

 

こちらは、コンパイル時にバッファオーバフローを引き起こす可能性のあるプログラムを自動で安全性の高いプログラムへ変換する機能です。

 

例えば、C言語ではstrcpy()という値のコピー関数がありますが、これをそのまま利用するとコピー先がコピー元より用意されたバイト数が少ない場合はバッファオーバフロー発生の起因要因になってしまいます。

 

それを防ぐためにstrcpy()の場合は空きブッファを超えないような制御を付加したプログラムに置換されます。

 

このように、プログラマが、明示的に宣言しなくても安全性の高いプログラムに置換してくれる機能をAutomatic Fortificationと呼びます。 

 

3.背景

 

昨今、多くのアプリケーションで様々な脆弱性情報が報告されるが、開発者のみならず、企業のセキュリティ担当者もそのリスクの程度を正確に推定できることが求められる

 

バッファオーバフロー脆弱性についてセキュリティ担当者が仕組み、対策について知っておくべきである。

 

4.過去問の要約

f:id:food_blog:20200516171057p:plain

 

図1に示すプログラムVulnはスタックバッファオーバフローの脆弱性用に作成されたプログラムである。図2は関数fooが呼び出された後のメモリマップである。

 

プログラム実行時に、変数bが指し示すデータが不正な場合、そのデータによって、リターンアドレスXbffff29dに書き換えられると、関数fooの終了時にshellコードへ処理が遷移する。

 

しかし、このような遷移があってもDEPが機能していれば、攻撃は成功しない。

 

攻撃者がDEPを回避するために、図2中のshellコードへ処理を遷移させる代わりにライブラリ中の実行可能コードやテキスト領域にマップされているVulnのコードを利用する攻撃もある。

 

例えば、攻撃の際にリターンアドレスXライブラリ関数の先頭アドレスに置き換えて

攻撃者の意図したライブラリ関数を呼び出すReturn-to-libc攻撃も存在する。

 

f:id:food_blog:20200516173606p:plain

[M対策技術の動作概要]

 

プログラムコンパイル時にSSPが適用されていると、関数fooを呼び出す際、図2のベースポインタレジスタ保存値より下位にcanaryが挿入される。

 

canaryが上書きされた場合は、攻撃と判断しVulnの実行を停止する。攻撃者がcanaryの位置を正確に推測して上書きされるとリターンアドレスXの値が書き換え可能となりReturn-to-libc攻撃が避けられなくなる。

 

対策としてはアドレス推測を困難にさせるASLRが有効である。

 

しかし、ASLRテキスト領域に関しては効果がない。

 

そうした攻撃はPIEによって緩和される。

 

さらには、Automatic Fortificationによって、ライブラリ関数strcpyを安全な関数に

 置き換えることでバッファオーバーフローの原因を排除できる。

 

表1 の備考欄の指摘以外にもAutomatic Fortificationではブッファオーバフローの原因を排除できないケースがある。

 

SSPを適用してコンパイルしていると、メモリ破壊攻撃は成立しないが、そのソースコードを別の開発環境でコンパイルすると問題となる場合があことが分かった。 

 

5.解説

 

しかし、このような遷移があってもDEPが機能していれば、

攻撃は成功しない。

 

理由としては以下です。

 

DEPはしてデータ領域(スタック領域)に万が一実行コードが埋め込まれたとしてもデータ領域内であればその実行を中断するという機能だからです。

 

表1 の備考欄の指摘以外にもAutomatic Fortificationでは

ブッファオーバフローの原因を排除できないケースがある。

 

こちらは図1のプログラム16行目のコードがそれに当たります。

排除できない理由はポインタを用いて直接メモリを操作しているからです。

 

ソースコードを別の開発環境でコンパイルすると問題となる場合がある

 

こちらは、SSPを適用できないコンパイラを用いた開発環境を利用すると、SSPが適用されずメモリ破壊攻撃を防ぐことができなくなります。