memologue RSSフィード

書いている人

日記というよりは備忘録、ソフトウェア技術者の不定期メモ。あるいはバッドノウハウ集。プライベートで調査した細々した諸々のスナップショット。嘘が散りばめられています。ISO/IEC 14882(C++)とPOSIX, GCC, glibc, ELFの話ばかりで、WindowsやMacの話はありません。特に記載がなければLinux/x86とILP32が前提です。時間の経過と共に古い記事は埋もれてしまいます。検索エンジンから飛んできた場合は、ページ内検索をご利用いただくかgoogleキャッシュを閲覧してみてください。技術的な記事を書きためる場所として使っています。言及してもらえると喜びます。主要な記事の一覧を書いておきます:

にんきコンテンツ: [GCC] mainを一度も呼ばないばかりか蹂躙する / Binary2.0 Conference 2006 発表資料 / C++ で SICP / ついカッとなって実行バイナリにパッチ / hogetrace - 関数コールトレーサ

昔のPOSIX関係の記事: シグナルの送受に依存しない設計にしよう / シグナルハンドラで行ってよい処理を知ろう / マルチスレッドのプログラムでのforkはやめよう / スレッドの「非同期キャンセル」を行わない設計にしよう / スレッドの「遅延キャンセル」も出来る限り避けて通ろう / マルチスレッドプログラミングの「常識」を守ろう / C++でsynchronized methodを書くのは難しい / シグナルハンドラからのforkするのは安全か? / g++ の -fthreadsafe-statics ってオプション知ってます? / 非同期シグナルとanti-pattern / localtimeやstrtokは本当にスレッドセーフにできないのか / UNIXの規格について / マルチスレッドと共有変数 - volatile?なにそれ。 / type punning と strict aliasing / アセンブラで遊ぶ時に便利なgdb設定 / 最近の記事は一覧から

2005-12-30

[] signed intでの配列アクセスはマジヤバイ(こともある)

次のC/C++なコードには問題があります。

#define A_SIZE 6
static int a[A_SIZE];

void vuln(int n, int val)
{
 assert(n < A_SIZE);
 a[n] = val;
}

配列アクセスの添字となる変数aの方が signed int なのが問題です。nとして負数を渡すと面白い(というか恐ろしい?)動作をします。


ええと・・(int)(0x80000000U + n) を vulnの第一引数として渡すと*1、vuln内の配列xのx[n]に書き込むことができてしまうのです。もちろん、配列の境界チェックは行われません。だから、

int main(void)
{
 // test1: a[4] = 123; と同じ。
 //        これはまぁ配列の範囲内だからいいけど・・
 vuln(0x80000004U, 123);

 // test2: overwrite return address (or saved-ebp) 
 //        without invalidating the canary word !!
 vuln(0x8000000AU, 123);
}

test2のような引数を渡すと、攻撃者に任意のコードを実行されてしまう恐れがあります。たとえ配列がスタック上に確保されている場合であっても、ProPoliceなどのcanary系プロテクションでは検出できないメモリの改ざんとなるので、厄介です。


細かい解説

(昨日の記事からのコピペ)


C99規格の§6.5.2.1(配列の添字演算子)や§6.5.6(加減演算子)の脚注88を見ると、int型の配列aに対して、a[n] は

 *((int*)((char*)(a)) + ((n) * sizeof(int)))

と等価ですので、負数を与えると、配列tableの終わりよりもっと後ろの方にもアクセスできてしまいます*2。つまり、メモリ上のほぼお好きな4バイトをお好きな値に書き換えることができてしまいます。


まとめ


  • 配列の添字が負数かどうかも必ずチェックしよう
  • そのまえに、そもそもsigned int型の添字で配列にアクセスするのはやめよう。添字については、プログラムの全域でstd::size_tを使うようにしよう。

ということで。


結論は当然っぽいんだけど、被害の程度があまり知られていないような気がしたので書いてみました。

*1:負の数を渡すことになります

*2:えーと、(n) * sizeof(int)の結果はsize_t型であることに注意してください

ball crystal espnball crystal espn 2007/01/31 07:03 Deerslayer obeyed her, the hunter, as usual, abbreviated manner of doubt with men, its clock would have stood in readiness to get the ascendancy. http://www.xvyn.com/131/ball-crystal-espn.html <a href=”http://www.xvyn.com/131/ball-crystal-espn.html”>ball crystal espn</a> [url]http://www.xvyn.com/131/ball-crystal-espn.html[/url]

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/yupo5656/20051230/p1
Connection: close