iOSアプリのセキュアコーディング - バッファオーバーフロー(Stack Overflows, Heap Overflows)
どんなアプリ開発にも言えることですが、セキュリティを考慮したコードを書く必要があります。
iOSアプリ開発におけるセキュアコーディングの一つに、バッファオーバーフローを回避することが挙げられます。
詳しくは、Appleの公式のセキュアコーディングガイドを。
ここでは、簡単な説明を記しておこうかと思います。
バッファオーバーフロー
まず、バッファって何?
例えば、文字列をメモリ上に格納するためには、文字の数だけ連続したメモリ領域を確保する必要があります。
このようにメモリ上に確保する領域をバッファ領域といいます。
バッファ領域には、スタックとヒープの2種類があります。
バッファオーバーフローとは?
一言で説明すると、入力データが、バッファ領域を超えていた場合に、他のデータ領域を上書いたりしてしまうこと です。
例えば、Intの最大値を超えた数値のInt型を生成するときにエラーが発生します。
バッファオーバーフローの流れ
- ユーザーが不正な文字列を入力する
- 有限なバッファ領域の大きさがどれくらいなのかをCPUは知らないため、不正な文字列を格納しようとする
- 確保した領域以外に、他の実行コードが格納された領域などの、メモリ上の不正な場所にデータを上書きしてしまう
バッファオーバーフローの種類
上記のようなバッファオーバーフローは、2種類のバッファ領域それぞれで発生し得ます。
スタックオーバーフロー(Stack Overflows)とヒープオーバーフロー(Heap Overflows)です。
スタックとは?
一時的に利用するデータを確保するための領域のこと。
関数内のローカル変数、関数の引数、関数の戻り先アドレスなどのデータがスタックに格納されています。
関数を呼び出すごとに、スタックが一番上に追加されていき、アプリは常に一番上のスタックにアクセスする。
関数の呼び出し元に戻すときは、スタックの一番上が削除されます。
スタックオーバーフロー(Stack Overflows)の流れ
スタックにおけるバッファオーバーフローとは、以下の流れになります。
- ユーザーがバッファ領域を超えるデータを入力する
- 確保したバッファ領域以外に、スタック上の他のデータを上書きしてしまう
例えば、上書きしてしまうことを利用して、関数の戻り先を変えてしまうなんてこともできちゃいます。
ヒープオーバーフロー
他のプログラムなどから渡されたデータの長さなどの検証を行わないと、確保されたヒープ領域の大きさを超えるデータが入力されてしまうことがあります。
そうなると、書き込み不可のメモリ領域へ書き込まれたり、プログラムを以上終了させられたりしてしまいます。
ヒープオーバーフローの影響
ヒープ上に確保するオブジェクトには、関数やデータポインタの表が付随しています。
攻撃により、ポインタを上書きされると、データを書き換えられたり、インスタンスメソッドが置き換えられたりします。
以下は、Appleが例としてあげている攻撃の例。
> 1. ビットマップ画像をデコードするコードのヒープオーバーフローを利用して、リモート操作により任意のコードを実行する。
> 2. ネットワークサーバのヒープオーバーフロー脆弱性を利用して、「Content-Length」ヘッダに負の値を指定したTTP POST要求を送りつけ、任意のコードを実行する。
対策
これらのバッファオーバーフローを防ぐためには、ユーザー入力や外部からのデータ受け取る際に、必ずデータの受け取り可能な長さやサイズの上限を設けて、受け取ったデータをチェックするようにしましょう。