C言語のサンプルコードで学ぶフォーマット文字列脆弱性とその防止策
フォーマット文字列(Format String)とは、文字列を整形(フォーマット)するために使用されるASCII文字列のことです。テキストと書式指定パラメータ(フォーマット指定子)を組み合わせて構成されます。
C言語には、プログラムの出力を整形するために、さまざまなフォーマット文字列が用意されています。
フォーマット文字列脆弱性とは
フォーマット文字列脆弱性とは、プログラマが陥りやすいプログラミング上のミスによって発生するバグです。攻撃者が入力した文字列がそのまま printf や sprintf などの出力関数に渡されると、任意のメモリアドレスへの書き込み操作が行われる可能性があります。これにより、情報漏洩やプログラムの異常動作、最悪の場合は任意コードの実行につながることもあります。
脆弱性のあるコード例
以下は、典型的なフォーマット文字列脆弱性を含むC言語のコード例です。
#include<stdio.h>
#include<string.h>
int main(){
char buffer[100];
strncpy(buffer, "Hii ", 5);
printf(buffer);
return 0;
}このコードでは、printf の第一引数に書式指定文字列を指定せず、変数 buffer を直接渡しています。もし buffer の内容がユーザー入力によって制御できる場合、攻撃者は「%x」や「%n」などのフォーマット指定子を注入することで、スタック上のデータを読み取ったり、任意のメモリ位置に値を書き込んだりできる可能性があります。
フォーマット文字列脆弱性の防止策
フォーマット文字列脆弱性を防ぐためには、以下のような対策が有効です。
ユーザー入力をフォーマット文字列として使用せず、プログラム内で固定の書式指定文字列を使うようにします。文字列を出力する場合は「%s」フォーマット指定子を利用することで、この問題は簡単に解決できます(例:printf("%s", buffer))。
フォーマット文字列は定数として作成し、可変の文字列は定数文字列に埋め込まず、関数呼び出しの引数として渡すようにします。
定数文字列と可変文字列の初期化ルールに従うことができないケースでは、フォーマットガード(書式チェック機構)を使用して防御します。
また、コンパイラの警告機能(GCCの -Wformat-security オプションなど)を活用して、危険なフォーマット文字列の使用をビルド段階で検出することも効果的な対策の一つです。
-
JavaScriptのエラー処理と例外処理の実装例をわかりやすく解説
JavaScriptにおけるエラー処理(例外処理)は、プログラムの実行中に発生する予期しない問題に対応し、アプリケーションのクラッシュを防ぐために欠かせない仕組みです。JavaScriptでは主に try...catch 構文を使ってエラーを捕捉します。 基本となる3つの要素 tryブロック: エラーが発生する可能性があるコードを記述します。 throw文: 「0での除算は不可」など、独自のカスタムエラーを意図的に発生させることができます。 catchブロック: tryブロック内でエラーが発生した際に、そのエラーを受け取って適切な処理を行います。 実装例 以下は、JavaScriptでエラ
-
C++で学ぶ式ツリー(Expression Tree)の基本と具体例
式ツリーとは何か式ツリー(Expression Tree)とは、二分木の一種であり、木の各ノードが「演算子」または「オペランド(被演算子)」のいずれかで構成される特殊なデータ構造です。数式を木構造として表現することで、コンパイラや電卓アプリなどが数式を効率的に解析・評価できるようになります。ノードの役割式ツリーにおける各ノードは、次のように役割が分かれています。葉ノード(リーフノード):オペランド(数値や変数)を表します。非葉ノード(内部ノード):演算子(+、-、*、/ など)を表します。つまり、計算の対象となる値は必ず葉に配置され、それらをどのように処理するかを示す演算子が親ノードとして上に