未初期化変数
Reading time: 8 minutes
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
基本情報
ここでの核心的なアイデアは、未初期化変数が、割り当てられたメモリに既にあった値を持つことが何を意味するかを理解することです。 例:
- 関数 1:
initializeVariable
: 変数x
を宣言し、値を割り当てます。例えば0x1234
とします。このアクションは、メモリ内にスポットを予約し、特定の値をそこに置くことに似ています。 - 関数 2:
useUninitializedVariable
: ここでは、別の変数y
を宣言しますが、値は割り当てません。C言語では、未初期化変数は自動的にゼロに設定されることはありません。代わりに、最後にそのメモリ位置に保存されていた値を保持します。
これらの二つの関数を順次実行すると:
initializeVariable
では、x
に値 (0x1234
) が割り当てられ、特定のメモリアドレスを占有します。useUninitializedVariable
では、y
が宣言されますが、値は割り当てられないため、x
の直後のメモリスポットを取ります。y
を初期化しなかったため、x
が使用していた同じメモリ位置から値を「継承」することになります。なぜなら、それがそこにあった最後の値だからです。
この動作は、低レベルプログラミングにおける重要な概念を示しています: メモリ管理は重要であり、未初期化変数は予測不可能な動作やセキュリティの脆弱性を引き起こす可能性があります。なぜなら、意図せずにメモリに残された機密データを保持することがあるからです。
未初期化のスタック変数は、以下のような複数のセキュリティリスクを引き起こす可能性があります:
- データ漏洩: パスワード、暗号鍵、または個人情報などの機密情報が未初期化変数に保存されると、攻撃者がこのデータを読み取る可能性があります。
- 情報漏洩: 未初期化変数の内容は、プログラムのメモリレイアウトや内部操作に関する詳細を明らかにし、攻撃者がターゲットを絞ったエクスプロイトを開発するのを助ける可能性があります。
- クラッシュと不安定性: 未初期化変数を含む操作は未定義の動作を引き起こし、プログラムのクラッシュや予測不可能な結果をもたらすことがあります。
- 任意のコード実行: 特定のシナリオでは、攻撃者がこれらの脆弱性を利用してプログラムの実行フローを変更し、任意のコードを実行できるようになる可能性があります。これにはリモートコード実行の脅威が含まれるかもしれません。
例
c
#include <stdio.h>
// Function to initialize and print a variable
void initializeAndPrint() {
int initializedVar = 100; // Initialize the variable
printf("Initialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
}
// Function to demonstrate the behavior of an uninitialized variable
void demonstrateUninitializedVar() {
int uninitializedVar; // Declare but do not initialize
printf("Uninitialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
}
int main() {
printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
// First, call the function that initializes its variable
initializeAndPrint();
// Then, call the function that has an uninitialized variable
demonstrateUninitializedVar();
return 0;
}
これがどのように機能するか:
initializeAndPrint
関数: この関数は整数変数initializedVar
を宣言し、値100
を割り当て、その後、変数のメモリアドレスと値の両方を印刷します。このステップは簡単で、初期化された変数がどのように動作するかを示しています。demonstrateUninitializedVar
関数: この関数では、初期化せずに整数変数uninitializedVar
を宣言します。その値を印刷しようとすると、出力にはランダムな数が表示されることがあります。この数は、そのメモリ位置に以前存在していたデータを表します。環境やコンパイラによって、実際の出力は異なる場合があり、安全のために、一部のコンパイラは変数を自動的にゼロに初期化することがありますが、これは信頼すべきではありません。main
関数:main
関数は、上記の2つの関数を順番に呼び出し、初期化された変数と初期化されていない変数の対比を示します。
ARM64の例
ARM64では、ローカル変数もスタックで管理されるため、全く変わりません。ここで示されているこの例を確認できます。
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。