Skip to content

Commit 73250bb

Browse files
authored
Merge pull request #2113 from HackTricks-wiki/research_update_src_pentesting-web_xss-cross-site-scripting_integer-overflow_20260410_032101
Research Update Enhanced src/pentesting-web/xss-cross-site-s...
2 parents a89223e + ffcf4d1 commit 73250bb

1 file changed

Lines changed: 72 additions & 6 deletions

File tree

src/pentesting-web/xss-cross-site-scripting/integer-overflow.md

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ Typical attack surface:
2929

3030
| Year | Component | Root cause | Impact |
3131
|------|-----------|-----------|--------|
32-
| 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. |
33-
| 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. |
34-
| 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). |
32+
| 2023 | **libwebp – CVE-2023-4863** | Malformed WebP lossless Huffman tables caused a heap overflow while building decoder lookup tables | A single malicious image was enough to get **heap corruption / renderer RCE** in Chromium-based browsers. |
33+
| 2024 | **Chrome Layout CVE-2024-7025** | Integer overflow in the rendering/layout pipeline reachable from a crafted HTML page | Demonstrates that integer bugs are not limited to JS engines: **HTML/CSS alone** can be enough to reach heap corruption. |
34+
| 2024 | **Chrome Skia – CVE-2024-9123** | Integer overflow in the graphics stack while processing crafted HTML content | A page visit could trigger an **out-of-bounds memory write** in the renderer. |
3535

3636
---
3737

@@ -69,6 +69,43 @@ Pad to length: 10, Enable hex prefix 0x
6969
* **Fuzzilli** – grammar-aware fuzzing of JavaScript engines to hit V8/JSC integer truncations.
7070
* **boofuzz** – network-protocol fuzzing (WebSocket, HTTP/2) focusing on length fields.
7171

72+
### 3.4 JavaScript and browser coercion cases worth forcing
73+
74+
Not every web integer bug is a native-style `size_t` wraparound. A lot of exploitable web logic starts with a **representation mismatch**:
75+
76+
* JavaScript numbers are IEEE-754 doubles, so integers above `Number.MAX_SAFE_INTEGER` (`2^53 - 1`) lose precision.
77+
* Legacy code frequently uses bitwise operators such as `|0`, `~~x`, `x<<0`, or `x>>>0`, which **coerce values to 32-bit signed/unsigned integers**.
78+
* Browser-facing code often parses a value once in JS and a second time in the backend, producing different range checks and different final values.
79+
80+
Useful probes:
81+
82+
```javascript
83+
// Precision loss above 2^53-1
84+
JSON.parse('{"n":9007199254740993}').n
85+
86+
// Signed wrap to negative
87+
(2147483648 | 0) // -2147483648
88+
89+
// Unsigned wrap to a huge positive
90+
(-1 >>> 0) // 4294967295
91+
92+
// Common "fast truncation" gadget in legacy code
93+
(4294967297 | 0) // 1
94+
```
95+
96+
When a target mixes client-side validation with API-side validation, replay the same field as:
97+
98+
* JSON number vs JSON string
99+
* decimal vs hex-like string (`4294967295` vs `0xffffffff`)
100+
* plain integer vs scientific notation (`10000000000` vs `1e10`)
101+
* positive vs negative boundary (`2147483647`, `2147483648`, `-1`, `4294967295`)
102+
103+
Interesting symptoms:
104+
105+
* Pagination or `limit` checks pass, but the query executes with `0`, `-1`, or a huge unsigned value.
106+
* Frontend blocks a value while the backend accepts it after a second parse.
107+
* A value displayed in the UI is not the value finally used by the API / renderer / WASM module.
108+
72109
---
73110

74111
## 4. Exploitation patterns
@@ -84,13 +121,42 @@ if($total > 1000000){
84121
```
85122

86123
### 4.2 Heap overflow via image decoder (libwebp 0-day)
87-
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.
124+
The WebP lossless decoder bug behind `CVE-2023-4863` was a good reminder that browser bugs still start with simple arithmetic mistakes around attacker-controlled metadata. In practice, a crafted image can make the decoder build invalid Huffman lookup tables and write past the heap before consistency checks finish. For web testing this means that **image dimensions, chunk sizes, color-table counts and compression metadata** are still first-class attack surface when the browser or the backend parses user-supplied files.
88125

89126
### 4.3 Browser-based XSS/RCE chain
90127
1. **Integer overflow** in V8 gives arbitrary read/write.
91128
2. Escape the sandbox with a second bug or call native APIs to drop a payload.
92129
3. The payload then injects a malicious script into the origin context → stored XSS.
93130

131+
### 4.4 Web logic bug → DOM XSS via integer truncation
132+
133+
This pattern is much more common in pentests than full renderer RCE:
134+
135+
```javascript
136+
const raw = JSON.parse(location.hash.slice(1)).len;
137+
const len = raw | 0; // "fast" int cast to signed 32-bit
138+
139+
if (len <= 64) {
140+
preview.innerHTML = userInput.slice(0, len);
141+
}
142+
```
143+
144+
If `raw=4294967295`, then `len` becomes `-1`. Depending on the surrounding code, this may:
145+
146+
* bypass a max-length check,
147+
* make `slice(0, -1)` drop the last character and preserve the rest of the payload,
148+
* or desynchronize validation and the eventual sink (`innerHTML`, template renderer, markdown preview, etc.).
149+
150+
The offensive lesson is simple: whenever you see **bitwise truncation in client-side code**, test whether the sanitized/validated length is the same value that later reaches the DOM sink.
151+
152+
### 4.5 WASM note
153+
154+
If the target uses Emscripten/WASM, a single integer bug in linear-memory management can often be upgraded into DOM XSS by corrupting writable HTML templates instead of the sanitized source string:
155+
156+
{{#ref}}
157+
wasm-linear-memory-template-overwrite-xss.md
158+
{{#endref}}
159+
94160
---
95161

96162
## 5. Defensive guidelines
@@ -107,6 +173,6 @@ The WebP lossless decoder multiplied image width × height × 4 (RGBA) inside a
107173

108174
## References
109175

110-
* [NVD CVE-2023-4863 – libwebp Heap Buffer Overflow](https://nvd.nist.gov/vuln/detail/CVE-2023-4863)
111-
* [Google Project Zero – "Understanding V8 CVE-2024-0519"](https://googleprojectzero.github.io/)
176+
* [Cloudflare: Uncovering the Hidden WebP vulnerability (CVE-2023-4863)](https://blog.cloudflare.com/uncovering-the-hidden-webp-vulnerability-cve-2023-4863/)
177+
* [NVD: CVE-2024-7025](https://nvd.nist.gov/vuln/detail/CVE-2024-7025)
112178
{{#include ../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)