hacktricks/binary-exploitation/integer-overflow.md

6 KiB
Raw Blame History

整数オーバーフロー

{% hint style="success" %} AWSハッキングの学習と練習HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングの学習と練習HackTricks Training GCP Red Team Expert (GRTE)

HackTricksをサポートする
{% endhint %}

基本情報

整数オーバーフローの中心にあるのは、コンピュータプログラミングのデータ型のサイズとデータの解釈によって課せられる制限です。

例えば、8ビット符号なし整数は、0から255までの値を表すことができます。8ビット符号なし整数に256の値を格納しようとすると、その格納容量の制限により、0にラップアラウンドします。同様に、16ビット符号なし整数は、0から65,535までの値を保持できますが、65,535に1を加えると値が0に戻ります。

さらに、8ビット符号付き整数は、-128から127までの値を表すことができます。これは、1ビットが符号正または負を表すために使用され、残りの7ビットが大きさを表すためです。最も負の数は**-128**(バイナリ 10000000)で表され、最も正の数は127(バイナリ 01111111)です。

最大値

潜在的なWeb脆弱性に関して、サポートされる最大値を知っておくことは非常に興味深いです:

{% tabs %} {% tab title="Rust" %}

fn main() {

let mut quantity = 2147483647;

let (mul_result, _) = i32::overflowing_mul(32767, quantity);
let (add_result, _) = i32::overflowing_add(1, quantity);

println!("{}", mul_result);
println!("{}", add_result);
}

{% endtab %}

{% tab title="C" %} 整数オーバーフローは、整数演算において結果が変数のデータ型の範囲を超える場合に発生します。これは、攻撃者が意図しないコードパスを実行したり、メモリの破壊を引き起こしたりする可能性がある深刻なセキュリティリスクです。整数オーバーフローは、特にC言語などの低レベル言語でプログラミングされたアプリケーションでよく見られます。適切な入力検証や境界値チェックを行うことで、整数オーバーフローによる脆弱性を防ぐことが重要です。 {% endtab %}

#include <stdio.h>
#include <limits.h>

int main() {
int a = INT_MAX;
int b = 0;
int c = 0;

b = a * 100;
c = a + 1;

printf("%d\n", INT_MAX);
printf("%d\n", b);
printf("%d\n", c);
return 0;
}

純粋なオーバーフロー

charをオーバーフローさせたため、印刷される結果は0になります

#include <stdio.h>

int main() {
unsigned char max = 255; // 8-bit unsigned integer
unsigned char result = max + 1;
printf("Result: %d\n", result); // Expected to overflow
return 0;
}

符号付きから符号なしへの変換

ユーザー入力から読み取られた符号付き整数が、適切な検証なしに符号なし整数として扱われる状況を考えてみましょう。

#include <stdio.h>

int main() {
int userInput; // Signed integer
printf("Enter a number: ");
scanf("%d", &userInput);

// Treating the signed input as unsigned without validation
unsigned int processedInput = (unsigned int)userInput;

// A condition that might not work as intended if userInput is negative
if (processedInput > 1000) {
printf("Processed Input is large: %u\n", processedInput);
} else {
printf("Processed Input is within range: %u\n", processedInput);
}

return 0;
}

その他の例

(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)

ARM64

これはARM64でも変わりません。このブログポストで確認できます。