Reproduction by: Dev Himanshu Patel (2023UCP1795), Parineeta Soni(2023UCP1127) — Department of Computer Science and Engineering, Malaviya National Institute of Technology
Original Paper: De Pasquale et al., USENIX Security 2024 — Link
This repository documents my reproduction of ChainReactor, a research project published at USENIX Security 2024 that received the Distinguished Artifact Award. ChainReactor uses AI planning to automatically discover multi-step privilege escalation chains on Unix systems — something no prior tool did end-to-end.
The core idea is elegant: instead of scanning for individual vulnerabilities, ChainReactor models the entire Unix system state (users, groups, file permissions, CVEs, binaries) as a PDDL planning problem and lets a state-of-the-art planner search for a sequence of actions that achieves root access. The result is a fully ordered, working exploitation chain rather than a flat list of potential issues.
As part of this reproduction, I set up the environment using Nix, ran the extractor on a controlled Linux VM, generated PDDL problem files, solved them with the bundled planner, and verified the resulting plan as a working exploit.
- Successfully set up the development environment using the Nix flake provided by the authors.
- Ran the BFG9000 extractor on a test Ubuntu 22.04 VM configured with intentional misconfigurations mirroring the paper's motivating example.
- Generated valid PDDL problem files from the extracted system facts using the encoder.
- Solved the generated problems using the Powerlifted planner bundled with the repository.
- Verified the output plan as a working 3-step exploitation chain that produces a root shell.
The reproduced chain matched the paper's motivating example exactly:
- Write a malicious file to a world-writable
/etc/certs/directory. - Trigger
c_rehash(CVE-2022-2068) — executes attacker code as theopenssluser. - Modify a systemd service file writable by the
opensslgroup — on service restart, commands execute as root.
ChainReactor has three main components that form a pipeline:
1. Extractor — runs unprivileged on the target and collects:
- All system users, groups, and group memberships (
/etc/passwd,/etc/group) - All ELF binaries and scripts, their linked libraries, and SUID/SGID bits
- GTFOBins capabilities mapped to discovered binaries
- Installed package versions cross-referenced with CVE databases (NVD)
- World-writable or group-writable files and directories
- Writable systemd service unit files
2. Encoder — converts all extracted facts into a PDDL problem file. Every binary, permission bit, CVE, and group membership becomes a predicate in the initial state. The goal state specifies the attacker reaching a root shell.
3. Planner — a modern forward-search PDDL planner (Powerlifted) solves the problem, navigating potentially millions of states to find an ordered exploitation chain. The plan is then translated into concrete shell commands.
The authors strongly recommend using Nix for a reproducible, hermetic build environment. I followed this approach.
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- installVerify the installation:
nix --versionFlakes need to be explicitly enabled. For a permanent fix, add the following to ~/.config/nix/nix.conf:
experimental-features = nix-command flakes
For NixOS, add this to your system configuration instead:
nix.settings.experimental-features = [ "nix-command" "flakes" ];For Home Manager:
nix = {
package = pkgs.nix;
settings.experimental-features = [ "nix-command" "flakes" ];
};Restart the Nix daemon or reboot for changes to take effect.
From the root of the repository:
nix developThis reads flake.nix and automatically installs all dependencies including the Powerlifted planner, Python packages, and all tools needed to run ChainReactor. No manual dependency management required.
The main entry point is bfg9000.py, which wraps the full pipeline: connection, extraction, encoding, and solving.
./bfg9000.py <command> [options]Three commands are available: extract, cloud, and solve.
Used to extract facts from a local or remote target and generate PDDL problem files.
./bfg9000.py extract [-h] -p PORT [-t TARGET] [-n NAME] [-uc] [-l | -r | -s] [-u USER] [-k KEY]
| Flag | Description |
|---|---|
-p PORT |
Port to connect or listen on |
-t TARGET |
Target IP address (used with -r or -s) |
-n NAME |
Name for output files (pickled facts and PDDL problems) |
-uc |
Assume CVEs in remote binaries are unpatched |
-l |
Listen for an incoming reverse shell |
-r |
Connect to an exposed shell on the target |
-s |
Connect via SSH |
-u USER |
SSH username |
-k KEY |
SSH private key path |
Example — listen for a reverse shell on port 5555:
./bfg9000.py extract -p 5555 -lExample — connect to a shell already exposed on a remote host:
./bfg9000.py extract -p 4444 -r -t 192.168.1.100After extraction, generated PDDL problems appear under generated_problems/. Filenames encode the escalation goal — for example, micronix-problem-root.pddl means the planner will search for a path to root.
Spawns a cloud VM, extracts facts, generates problems, and solves them automatically. Supports AWS and Digital Ocean.
./bfg9000.py cloud [-h] [-s SCRIPT] [-uc] {aws,do} image
| Argument | Description |
|---|---|
provider |
Cloud provider: aws (Amazon EC2) or do (Digital Ocean) |
image |
Provider-specific image ID |
-s SCRIPT |
Optional local script to execute on the remote instance |
-uc |
Assume CVEs in remote binaries are unpatched |
Example — analyse an AWS AMI:
./bfg9000.py cloud aws ami-12345678Example — run a custom setup script on a Digital Ocean droplet:
./bfg9000.py cloud do ubuntu-20-04-x64 -s my_script.shTakes an existing PDDL problem file and invokes the planner to find an exploitation chain.
./bfg9000.py solve -p path/to/problem.pddl
The domain.pddl file defines the planning domain — the full space of actions an attacker can take on a Unix system.
| Type | Description |
|---|---|
file, data, location, user, group, permission, process, purpose |
General object types |
executable |
Subtype of file |
local, remote, directory |
Subtypes of location |
| Constant | Meaning |
|---|---|
FS_READ, FS_WRITE, FS_EXEC |
Standard Unix file permissions |
SHELL |
Marks a file as attacker-corrupted |
SYSFILE_PASSWD |
Marks a file as behaving like /etc/passwd |
File Manipulation
propagate_loaded_file_contents— copy file contents from one file to anotherwrite_data_to_file— write arbitrary data to a fileread_file— read file contents into a buffer
Permission and Ownership
make_executable_suid— set the SUID bit on an executablechange_file_owner— change file ownershipadd_permission_of_owned_file— add a permission to a user-owned file
Process and Execution
spawn_process— spawn a process from an executablespawn_suid_process— spawn a process from a SUID executablespawn_shell— spawn a shell using a GTFOBins-capable binary
Network
download_file— download a file from a remote locationupload_file— upload a file to a remote location
CVE-Specific Actions
derive_executable_with_cap_cve_shell_command_injection_has_other_capabilitiescheck_cve_shell_command_injection_needs_writable_directoryderive_user_can_read_anything_from_executable_with_CAP_CVE_read_any_filewrite_data_to_file_using_executable_with_CAP_CVE_write_any_file
The repository includes a test suite (run_tests.sh) that validates individual domain actions. I ran these tests during reproduction to verify the domain was correctly set up.
./run_tests.shThe script runs the planner on each PDDL test file in the tests directory, checks for a plan.1 output file to determine success, and prints a summary. Key test cases include:
| Test File | What It Validates |
|---|---|
escalate_shell.pddl |
Privilege escalation by injecting shellcode into a sensitive script |
escalate_shell_via_chmod_suid.pddl |
Escalation by making a binary SUID and spawning a shell |
escalate_shell_sideload.pddl |
Escalation by sideloading a library into a shell executable |
cve_shell_command_injection_write_to_file.pddl |
Command injection via CVE to write arbitrary data |
passwd_writable.pddl |
Overwriting /etc/passwd to gain control of another user |
corrupt_daemon_file.pddl |
Corrupting a daemon-managed file to inject a command |
read_file_suid.pddl |
Reading a restricted file using a SUID executable |
write_to_file_group.pddl |
Writing to a group-owned file via group membership |
All tests passed during my reproduction.
The authors included pre-computed artifacts (pickle files, generated problems, and plans) for the AWS and Digital Ocean instances evaluated in the paper under the artifacts/ directory.
To reproduce any solution from these artifacts:
Option 1 — Solve a specific problem manually:
./bfg9000.py solve -p generated_problems/<PROBLEM_FILE>.pddlOption 2 — Run the full reproduction script:
./reproduce_results.shNote: The authors note that artifacts for 6 AWS instances could not be retrieved and are absent from the repository.
BFG9000 logs all significant events and maintains a SQLite database (stats.sqlite) recording per-run statistics including problem generation time and solve time. This was useful during reproduction to compare my runtimes against the paper's reported numbers.
@inproceedings{depasquale_chainreactor,
author = {Giulio De Pasquale and Ilya Grishchenko and Riccardo Iesari and Gabriel Pizarro
and Lorenzo Cavallaro and Christopher Kruegel and Giovanni Vigna},
title = {{ChainReactor}: Automated Privilege Escalation Chain Discovery via {AI} Planning},
booktitle = {33rd USENIX Security Symposium (USENIX Security 24)},
year = {2024},
isbn = {978-1-939133-44-1},
address = {Philadelphia, PA},
pages = {5913--5929},
url = {https://www.usenix.org/conference/usenixsecurity24/presentation/de-pasquale},
publisher = {USENIX Association},
month = aug
}All credit for ChainReactor goes to the original authors: Giulio De Pasquale, Ilya Grishchenko, Riccardo Iesari, Gabriel Pizarro, Lorenzo Cavallaro, Christopher Kruegel, and Giovanni Vigna. The original work was supported by DARPA (agreement N66001-22-2-4037), the National Science Foundation (grant 2229876), the Department of Homeland Security, IBM, and Cisco.
This repository is a course reproduction conducted as part of the A* paper reproduction assignment at MNIT Jaipur, Department of Computer Science and Engineering.