セキュア・プログラミング

C言語は Unix とともに普及し,その汎用性・移植性の高さからオープンソースソフトウェアや多くのソフトウェア製品の記述に用いられている.古くからフリーのコンパイラも数多く提供されており,実行可能ファイルがコンパクトで効率が良いことなどから,多くの場面で採用されている.

C 言語は,次のような特徴を持っている.

その一方で,C言語は軽量であり自由度が高いゆえに安全機構が欠けており.コンピュータを乗っ取るに至るようなセキュリティ脆弱性を生み易いという特性がある.また,セキュリティ脆弱性や潜んだバグによる想定外の動作を起こし易い.

例えば,データ複写の際の領域あふれ,ポインタによる誤った領域へのアクセス,データへのポインタと関数へのポインタの混同などを言語処理系が事前に検出しない.

これらの問題により発生する代表的な脆弱性として,バッファオーバーフロー脆弱性,フォーマット文字列脆弱性,整数オーバーフロー脆弱性等が挙げられる. これらの問題を防ぐための安全なロジックを組み込むことは,本来プログラマの役目であるが,これを忘れるとセキュリティ問題を引き起こすことになる.

C++言語は,クラスの概念に基づくオブジェクト指向プログラミングを C言語ベースで行えるように C言語を拡張したものである.C言語の要素を引継ぐとともに新しい構文や機能を追加している.そのため,オブジェクト指向プログラミングが可能である一方で,純粋な C言語スタイルのプログラミングも行える.したがって,C++言語でも C言語と同様,脆弱性を持つプログラムが書かれ易い状況にある.

以下では,C/C++言語で発生する代表的な脆弱性の問題の概要を示す. セキュア・プログラミングに関する問題とその対策の詳細は,IPA がまとめている セキュア・プログラミング講座 C/C++言語編 を参照されたい.

バッファ・オーバーフロー攻撃

バッファ・オーバフローとは,プログラムの実行においてスタックに確保されたデータ領域を超えてデータを書き換えてしまうことである.通常は,メモリー違反を起こしプログラムが停止してしまう. しかし,バッファ・オーバフローを利用してスタック上のプログラムのリターンアドレスを書き換えることで,プログラマが意図しない処理 (悪意あるプログラム) を実行できてしまう.バッファ・オーバフローは,セキュリティホール (脆弱性) の一種である. バッファオーバーフロー攻撃は,この脆弱性を利用してコンピュータのメモリ内に機械語プログラムを送り込んで実行し,コンピュータの制御を奪うなどの攻撃方法である.

バッファオーバーフロー攻撃には,対象とするメモリ領域に応じて次の種類がある.

対策は,コード記述時に領域長とデータ長を常に意識すること (strcpy や strcat といったバッファのサイズをチェックしない関数は使用しない),動的に領域を確保すること,領域あふれを検出できるデバッガの利用,バッファオーバーフロー対策されたランタイムライブラリを利用すること等である.

整数オーバーフロー攻撃

C/C++ 言語においては整数型に多くのバリエーションが存在するが,整数演算のオーバーフロー,代入時の上位ビット消失,符号あり型符号なし型間で値が保存されない等の問題が実行時に誤りとして検出されないことが多い.このことが問題を生み,整数オーバーフロー攻撃の余地を作っている.攻撃は,データ配置のオフセットや転記データ長として想定外の符号の値あるいは範囲を超えた値を生じさせるよう整数演算を誘導し,それを利用してメモリ上に攻撃コードを送り込む.

C/C++ 言語における整数の取り扱いには,次のような注意が必要である.

整数オーバーフロー攻撃への対策には,取り扱う整数の型をなるべく統一し大きなビット幅かつ符号無しにする,演算結果を検証する (事前検査,事後検査),アサーションによる検査,整数演算の C++クラスを導入する,コンパイラのオプションを利用する等がある.

フォーマット文字列攻撃

フォーマット文字列攻撃は,printf や syslog 等のライブラリ関数がもつ書式編集機能を悪用し,実行中のプログラムのメモリに悪意の機械語コードを送り込んで実行させる攻撃手法である. この攻撃は,ライブラリ関数の書式引数に外部からの入力データがそのまま渡るようになっている場合に起こり得る.

フォーマット文字列攻撃は,printf 等が解釈実行する %n 書式を悪用する.%n 書式は,これまでの書式編集出力で何バイトのデータが書き出されたかの値を整数変数に書き戻すことを指示する書式である. %n 書式によって関数のリターンアドレスを書換えて関数からのリターン時,攻撃コードへのジャンプが起こるようにする.

フォーマット文字列攻撃への対策は,書式引数には外部から入力したデータを用いないことである.外部から書式文字列を受け入れる必要のある場合は,許容される文字列を十分に確認してから使用し,%n 書式を用いない.

コマンド注入攻撃

C 言語にはプログラム内部がらシェルを呼び出してコマンドを実行できる system,popen 等のライブラリ関数がある. シェルは,ユーザが指定したプログラムを単に起動するのみならず,ファイル入出力のリダイレクト,複数コマンドの組み合わせ実行,パイプ,変数,条件分岐,ループ等プログラミング機能をも含む強力なツールである.

コマンド注入攻撃は,プログラムが外部からの入力を組み入れてシェルコマンド文字列を組み立てて実行する処理を狙って悪意ある入力データを送り込み,攻撃者に都合の良いコマンドを実行させる攻撃である.

コマンド注入攻撃への対策は,シェルの使用を極力避けることである.プログラムの中から別のプログラムを起動する際は,execve 等の exec 系の API を使用する.シェルを使用する場合は,シェルコマンド文字列の値を事前に検査することである.

inserted by FC2 system