← Back to blog
|

IVON is escaping: from sandbox to backend

aipentestingred-teamcontainersssrfdocker

Part 2 of 3 in Pentesting with AI. Previously: pwning Call of Duty 1.

In the first post I used an AI agent to exploit a 20-year-old binary. This time I tested something we built ourselves. In this blog series we want to show you how super effectively AI identifies security vulnerabilities. It saves a lot of time and finds interesting attack paths.

IVON breaking out of its sandbox

IVON is our managed-detection product at Attic Security, a Zolder company. Part of the triage pipeline is an investigation agent, and that agent is Claude Code running headless. It reads incident data and analyzes it.

The main risk: that agent reads attacker-influenced data. So we run it sandboxed, inside a hardened container with limited network access. The container is the security boundary. Which of course made us want to check: how solid is that sandbox?

The setup

Same setup as always. I booted up a live copy of our own pipeline in Docker and gave it access the source code. I also let it perform the attacks against a container identical to the one we use. The AI reads the code and tries finds a vulnerabilities. When identified, it writes and tests the exploit until it works.

The interesting part: the sandboxed agent is Claude Code, the same as we are security testing with. So if you succeed in instructing the sandboxed agent to hack itselfs out, it may succeed as well..

Prompt Injection

We do have user input into the container, data from the incident, but also threat intelligence. Preventing prompt injection, using the model itself, feels unreliable. However, this seems to be the only option nowadays, as input filtering also feels unreliable.

In our tests the prompt injection mitigations were working quite well. However, its important to know that whenever a model is switched, this may also have an impact on the prompt injection prevention. 🤨 Something to be aware of.

One request out of the cage

The sandbox couldn't reach the network directly. There was only 1 API available, to a backend server.

That backend has an endpoint, POST /api/v1/queries/import, meant for importing a saved query from a URL. Passing a URL to this endpoint, receives its response. This functionality was available in the API, however shouldn't be available to the sandbox.

That's a classic SSRF. The agent is stuck in an isolated container, but the backend doing the fetch is not. So the agent points the endpoint at an internal address it could never reach itself. Claude found this path pretty quick.

Another classic mistake

The backend had access to the Docker API. This allows access to the Docker Daemon. This access allowed us to list the containers AND then read each container's environment. And container environments are where the secrets live. This came back with every container's secrets: signing keys, API keys, database connection strings. That hurts, because it allows us to takeover the IVON backend.

This screenshot shows the isolated agent enumerating containers it should never have been able to see:

Sealed agent listing sibling containers through the SSRF

From secrets to root on the host

Being able to read from the Docker API is already pretty bad. But you can also write to it, and that is where it goes from leaking some secrets to fully taking over the host. We couldn't chain this part to the SSRF above, because that one only does GET requests and this needs a POST. But you get the point.

The proxy in front of the Docker socket allowed container creation and volume binds. And once you can create a container with an arbitrary bind mount, the escape is simple. Create a container that mounts the host's root filesystem inside itself, and run a command as root against it.

POST /containers/create
{ "HostConfig": { "Binds": ["/:/host"] }, ... }

Now there's a process running as uid=0 with the entire host filesystem mounted at /host. We now had root on the machine running the whole pipeline.

The interesting part is that we hear a lot of company's that their agents are breaking out (OpenAI, Antrophic, Meta). Probably those escapes are less spectacular then they sound. If you put them in weak sandboxes, they will escape. AI is already super powerful in findings vulnerabilities.

Verdict

Chained end to end, the worst case:

sandbox → host
Sandbox IVON in a sandbox. Only access to one single API
POST /api/v1/queries/import SSRF
Backend not isolated, full network access
GET /containers/{id}/json secrets
Docker API backend connects via socket proxy to Docker API
POST /containers/create Binds ["/:/host"] not chained: SSRF is GET-only
Host full root access on the host system

A few things I took away from it:

  • The current solutions to preventing prompt injection feel vulnerable.
  • Be careful what input you allow into a powerful agent such as Claude Code. Otherwise may get hacked by your own agent some day. 🥲
  • Design your sandboxes very carefully and pentest them (using AI)

None of this is a knock on running an AI agent in production. We still do, with these paths closed now.

Next up is the finale: a real, shipping consumer device. Thanks for reading!