All blogs
4 min readEN

Lab Solved — Exploiting Vulnerabilities in LLM APIs

  • LLM Security
  • Pentesting
  • AI Security
  • OS Command Injection
On this page

LLM Pentesting Series — Part 3

This walkthrough is intended only for PortSwigger’s authorized Web Security Academy environment. Do not test these techniques against systems without permission.

Introduction

In Part 3 of the LLM Pentesting series, we will solve PortSwigger’s “Exploiting vulnerabilities in LLM APIs” lab.

The lab demonstrates how an attacker can abuse an LLM’s API integrations to attack the underlying system. This time, we will perform OS command injection through a vulnerable LLM API.

The objective is to delete the morale.txt file from Carlos’s home directory.

Lab Architecture

The high-level architecture is shown in Figure 1.

Architecture of the lab
Architecture of the lab

The diagram uses colors and numbered steps along the red path. Here is what they mean:

  • Red path: The path the attacker takes.
  • Yellow path: Controls that would stop the attack if they were implemented, or implemented correctly.
  • Numbers on the red path: The steps the attacker follows to exploit the endpoint. We will use these numbers while explaining the exploit.

How to Exploit

Step 1: Find the LLM Interaction Page

First, locate any page on the site that integrates the LLM.

The live chat feature on the shop page
The live chat feature on the shop page

As shown in Figure 2, the site has a live chat feature. This is our entry point for the exploitation.

Steps 2–3: Interact with the Model and Enumerate Its Functions

First interaction with the model
First interaction with the model

In Figure 3, we start interacting with the model. Notice that it behaves strangely in response to the first question. Keep this in mind, because the same behavior appears again during the OS command injection attempts.

Steps 4–8: Focus on the Newsletter Subscription

There are several steps here, but the key point is that I interacted with the LLM extensively to identify which endpoint was exploitable, trying different approaches along the way.

Eventually, I realized that the newsletter subscription function was a good candidate for injecting commands into the server side.

Probing the newsletter subscription function
Probing the newsletter subscription function

After some trial and error, we learn that the function is called newsletter_subscription and that it takes an email address as input. Internally, it works something like this:

newsletter_subscription(String email) -> String:
    system.run("sendemail {email}")

Can you see the issue? It calls another service through the command line. That gives us an opportunity.

Steps 9–12: Exploit the System

In the architecture diagram these are separate steps, but for this walkthrough we can treat them as one.

The model rewriting the $(whoami) payload
The model rewriting the $(whoami) payload

Can you see the problem? The model takes our “$(whoami)” payload and rewrites it as ‘assistant’ or ‘customer’. Have a look at Figure 5 to see what I mean. After several attempts, I managed to execute “$(whoami)” directly inside the email command.

The whoami output reflected in the email client
The whoami output reflected in the email client

Now we can see that the server side is running as carlos. Next, we can try something like “$(ls)”.

The $(ls) command executes successfully
The $(ls) command executes successfully

It reports success. We will confirm the result in Figure 8.

morale.txt appears in the directory listing
morale.txt appears in the directory listing

As you can see, morale.txt is right in front of us. Now we can run “$(rm morale.txt)”.

The function returns an error after deleting the file
The function returns an error after deleting the file

The function returns an error. Why? Because it then tries to send an email to an invalid address. But by that point, the injected command has already executed.

morale.txt is deleted, and the lab is solved.

Conclusion

This was one of the most interesting labs I have solved so far. It is a strange combination of a classic vulnerability and a new technology integrated into a system, and together they create a dangerous attack path.

We will keep going deeper down the rabbit hole. There is much more to explore.

I hope this was helpful and gave you a different perspective on the attack surface of 2026.

See you in the next lab!

References