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
Copy file name to clipboardExpand all lines: src/pentesting-web/xss-cross-site-scripting/js-hoisting.md
+24Lines changed: 24 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -133,6 +133,20 @@ let config;` -
133
133
trigger()
134
134
```
135
135
136
+
### Hoisting to bypass exception handling
137
+
138
+
When the sink is wrapped in a `try { x.y(...) } catch { ... }`, **ReferenceError** will stop execution before your payload runs. You can pre-declare the missing identifier so the call survives and your injected expression executes first:
139
+
140
+
```javascript
141
+
// Original sink (x and y are undefined, but you control INJECT)
142
+
x.y(1,INJECT)
143
+
144
+
// Payload (ch4n3 2023) – hoist x so the call is parsed; use the first argument position for code exec
145
+
prompt()) ; functionx(){} //
146
+
```
147
+
148
+
`function x(){}` is hoisted before evaluation, so the parser no longer throws on `x.y(...)`; `prompt()` executes before `y` is resolved, then a `TypeError` is thrown after your code has run.
149
+
136
150
### Preempt later declarations by locking a name with const
137
151
138
152
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:
@@ -153,11 +167,21 @@ Notes
153
167
- This relies on execution order and global (top-level) scope.
154
168
- 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`.
155
169
170
+
### Dynamic import() with user-controlled specifiers
171
+
172
+
Server-side rendered apps sometimes forward user input into `import()` to lazy-load components. If a loader such as `import-in-the-middle` is present, wrapper modules are generated from the specifier. Hoisted import evaluation fetches and executes the attacker-controlled module before subsequent lines run, enabling RCE in SSR contexts (see CVE-2023-38704).
173
+
174
+
### Tooling
175
+
176
+
Modern scanners started to add explicit hoisting payloads. **KNOXSS v3.6.5** lists "JS Injection with Single Quotes Fixing ReferenceError - Object Hoisting" and "Hoisting Override" test cases; running it against RXSS contexts that throw `ReferenceError`/`TypeError` quickly surfaces hoist-based gadget candidates.
0 commit comments