アプリなどのエンジニアです

iOS、Android、PHP、Rubyを使ったことがあります

iOSアプリのセキュアコーディング - バッファオーバーフロー(Stack Overflows, Heap Overflows)

どんなアプリ開発にも言えることですが、セキュリティを考慮したコードを書く必要があります。
iOSアプリ開発におけるセキュアコーディングの一つに、バッファオーバーフローを回避することが挙げられます。

詳しくは、Appleの公式のセキュアコーディングガイドを。

ここでは、簡単な説明を記しておこうかと思います。

バッファオーバーフロー

まず、バッファって何?

例えば、文字列をメモリ上に格納するためには、文字の数だけ連続したメモリ領域を確保する必要があります。
このようにメモリ上に確保する領域をバッファ領域といいます。
バッファ領域には、スタックとヒープの2種類があります。

バッファオーバーフローとは?

一言で説明すると、入力データが、バッファ領域を超えていた場合に、他のデータ領域を上書いたりしてしまうこと です。
例えば、Intの最大値を超えた数値のInt型を生成するときにエラーが発生します。

バッファオーバーフローの流れ

  1. ユーザーが不正な文字列を入力する
  2. 有限なバッファ領域の大きさがどれくらいなのかをCPUは知らないため、不正な文字列を格納しようとする
  3. 確保した領域以外に、他の実行コードが格納された領域などの、メモリ上の不正な場所にデータを上書きしてしまう

バッファオーバーフローの種類

上記のようなバッファオーバーフローは、2種類のバッファ領域それぞれで発生し得ます。
スタックオーバーフロー(Stack Overflows)とヒープオーバーフロー(Heap Overflows)です。

スタックとは?

一時的に利用するデータを確保するための領域のこと。

関数内のローカル変数、関数の引数、関数の戻り先アドレスなどのデータがスタックに格納されています。
関数を呼び出すごとに、スタックが一番上に追加されていき、アプリは常に一番上のスタックにアクセスする。
関数の呼び出し元に戻すときは、スタックの一番上が削除されます。

f:id:piikaachuu:20170930071025g:plain

スタックオーバーフロー(Stack Overflows)の流れ

スタックにおけるバッファオーバーフローとは、以下の流れになります。

  1. ユーザーがバッファ領域を超えるデータを入力する
  2. 確保したバッファ領域以外に、スタック上の他のデータを上書きしてしまう

例えば、上書きしてしまうことを利用して、関数の戻り先を変えてしまうなんてこともできちゃいます。

f:id:piikaachuu:20170930072033j:plain

ヒープとは?

mallocなどの関数で動的に確保できたり、使い終わったら解放できたりするメモリ領域のことです。
オブジェクトのインスタンスを生成すると、ヒープ上の領域を指すポインタが返されます。

ヒープオーバーフロー

f:id:piikaachuu:20170930103946g:plain

他のプログラムなどから渡されたデータの長さなどの検証を行わないと、確保されたヒープ領域の大きさを超えるデータが入力されてしまうことがあります。
そうなると、書き込み不可のメモリ領域へ書き込まれたり、プログラムを以上終了させられたりしてしまいます。

ヒープオーバーフローの影響

ヒープ上に確保するオブジェクトには、関数やデータポインタの表が付随しています。
攻撃により、ポインタを上書きされると、データを書き換えられたり、インスタンスメソッドが置き換えられたりします。

以下は、Appleが例としてあげている攻撃の例。
> 1. ビットマップ画像をデコードするコードのヒープオーバーフローを利用して、リモート操作により任意のコードを実行する。
> 2. ネットワークサーバのヒープオーバーフロー脆弱性を利用して、「Content-Length」ヘッダに負の値を指定したTTP POST要求を送りつけ、任意のコードを実行する。

対策

これらのバッファオーバーフローを防ぐためには、ユーザー入力や外部からのデータ受け取る際に、必ずデータの受け取り可能な長さやサイズの上限を設けて、受け取ったデータをチェックするようにしましょう。