# Solutions

> The seed solutions that ship in the repository.

import SupportedProtocols from '../../components/docs/SupportedProtocols.astro';
import SolutionsTable from '../../components/docs/SolutionsTable.astro';

The `solutions/` folder holds the seed solutions. Each entry was verified against a vulnerable replica (mostly Docker containers built for the purpose) and, where the check is behavioral, falsified on a fixed build. A solution is listed by its `id`, with the identity it uses and the CVE it exercises. The source files live in the [exploitmatic/solutions repository](https://github.com/exploitmatic/solutions/tree/main/solutions).

## Supported protocols

The runtime implements eighteen protocols.

<SupportedProtocols />

## Browse the solutions

Sort any column or filter by protocol.

<SolutionsTable />

The detailed notes for each entry follow.

## tls/openssl-heartbleed-mem-leak

CVE-2014-0160, `tls` identity. A hand-crafted TLS 1.2 ClientHello carrying the Heartbeat extension, then a heartbeat request with a spoofed payload length. The server replies with more bytes than were sent, proving the over-read. Verified on OpenSSL 1.0.1f (nginx), falsified on 1.0.1g. The entry carries the exact openssl-generated hello bytes and the `1803030003014000` heartbeat request.

## http/log4j-jndi-rce

CVE-2021-44228, `http` identity. A `${jndi:ldap://...}` lookup injected via the `X-Api-Version` header. The vulnerable logger resolves the JNDI reference and the LDAP provider calls back the out-of-band listener; the OOB assert on the LDAP bind prefix proves the lookup executed. Verified on a live vulnerable app. A containerized target needs the listener on a routable address (`-oob-host`), because `127.0.0.1` inside a container is the container's own loopback.

## http/tpl-jinja2-ssti-rce

`http` identity, Jinja2 server-side template injection. The probe step confirms the template engine evaluates user input, the RCE step runs a command, and the read step pulls the flag back. Verified against a local Flask app using `render_template_string`.

## https/apache-cve-2021-42013-rce

CVE-2021-42013 / CVE-2021-41773, `https` identity. Apache 2.4.49 path traversal (`/icons/.%%32%65/...`) reaches a CGI handler and executes `/bin/sh` with an encoded command. Verified over TLS on httpd 2.4.49 with mod_ssl.

## smtp/opensmtpd-cve-2020-7247-rce

CVE-2020-7247, `smtp` identity. OpenSMTPD 6.6.1p1 command injection through a crafted `MAIL FROM` address: the injected `wget` command phones home to the OOB listener. Note that the OpenSMTPD address parser strips colons, so the command must use a no-scheme `wget` with the implicit port 80 and the listener must run on port 80. Assert is `oob "GET /pwned"`.

## ftp/vsftpd-cve-2011-2523-backdoor

CVE-2011-2523, `ftp` identity. The vsftpd 2.3.4 backdoor opens a root shell on port 6200 after `USER backdoor:)` followed by `PASS`. The solution uses the per-step `port` field to reconnect from 21 to 6200. Verified on a vulnerable vsftpd 2.3.4 container.

## dns/bind-cve-2015-5477-tkey-dos

CVE-2015-5477, `dns` identity. A crafted TKEY query hits an assertion failure in BIND 9.9.7-P1 and kills `named`. The `assert empty` type passes when the server stops responding. Verified on a from-source BIND build; the container exits 139 after the crash.

## snmp/cve-2018-18066-net-snmp-null-deref-dos

CVE-2018-18066, `snmp` identity. A crafted SNMPv3 UDP packet (EDB 45544) reaches `snmp_oid_compare` in `snmplib/snmp_api.c` in net-snmp before 5.8, dereferences a NULL pointer, and the agent segfaults. The solution proves the agent is up with a normal SNMPv2c GET, fires the malformed packet (the agent answers with a report echoing the attacker username, then crashes), and asserts an empty response to a follow-up GET. Verified against a from-source net-snmp 5.7.3 build; the container exits 139 after the crash.

## tcp/memcached-cve-2011-4971-dos

CVE-2011-4971, `tcp` identity. A memcached `ADD` with a negative value length triggers an integer underflow that crashes the process. `assert empty` verifies the crash. Verified on a vulnerable memcached container.

## ldap/openldap-cve-2015-6908-ber-dos

CVE-2015-6908, `ldap` identity. OpenLDAP 2.4.42 `ber_get_next` assertion failure from a malformed BER packet crashes `slapd`. `assert empty` verifies the crash. Verified on a vulnerable OpenLDAP container.

## ssh/openssh-cve-2018-15473-username-enum

CVE-2018-15473, `ssh` identity via the `process` identity. A malformed userauth request makes OpenSSH 7.7 bail early for nonexistent users, so the response differs for existing and missing usernames. The runtime drives the public exploit script (Rhynorater) through a process step. Verified against a vulnerable OpenSSH 7.7 container.

## websocket/ws-cve-2021-32640-redos

CVE-2021-32640, `websocket` identity. The `ws` 7.4.5 ReDoS: a crafted frame makes the server stall on a pathological regex. `assert empty` verifies the stall. Verified against a `ws@7.4.5` server container.

## smb/samba-cve-2017-7494-rce

CVE-2017-7494, `smb` identity via the `process` identity. Samba `is_known_pipename` calls `smb_probe_module` on a client-supplied absolute path, and `dlopen` runs a shared object's constructor. The exploit uploads `pwn.so` to a writable guest share, then triggers the load with a raw SMB1 NT_CREATE_ANDX that preserves forward slashes (impacket otherwise normalizes them to backslashes). The constructor writes `id` output back to the share; the assert reads it. Verified on a from-source Samba 4.6.3 container.

## mysql/mysql-cve-2012-2122-auth-bypass

CVE-2012-2122, `mysql` identity via the `process` identity. MySQL 5.5.23's `check_scramble` memcmp returns a value treated as zero for about 1 in 256 wrong passwords, so looping wrong-password logins eventually authenticates as root. The process step runs a pymysql loop and asserts on `LOGIN BYPASS OK`. Note the server's `max_connect_errors` blocks the host after enough failures; flush it before running, and give the step a long `-timeout`.

## process/bash-cve-2014-6271-shellshock

CVE-2014-6271, `process` identity. Bash 4.3 parses past the closing brace of a function definition in an exported variable and runs trailing commands. The step runs `docker exec` into a container with an unpatched bash 4.3.0, sets the crafted variable, and reads back the injected `id` output as root. Verified against a from-source bash 4.3.0.

## file/imagemagick-cve-2016-3714-rce

CVE-2016-3714, `file` identity. A crafted MVG image whose fill color contains an `url(...)` value with an embedded pipe runs a shell command when processed by vulnerable ImageMagick. The file step writes the crafted image, the process step runs a vulnerable ImageMagick 6.8.9-9 `convert` on it, and the injected `id` output is read back. Verified against a from-source ImageMagick 6.8.9-9.

## telnet/telnet-cve-2011-4862-encryption-keyid-dos

CVE-2011-4862, `telnet` identity. GNU inetutils telnetd copies a client KEYID into a fixed 64-byte buffer with `memmove` and no length check. The solution negotiates TELOPT ENCRYPT (IS with IV, SUPPORT, REPLY), then sends a 400-byte KEYID that smashes the buffer and the adjacent function pointer, crashing the telnetd child. `assert empty` verifies the crash. Verified against a from-source inetutils 1.8 telnetd with ENCRYPTION and AUTHENTICATION enabled.

## http/wp-batch-route-confusion-sqli-rce

CVE-2026-63030 plus CVE-2026-60137, `http` identity. Requires a live WordPress lab; the route-confusion path lets an unauthenticated batch request reach a SQL injection sink.

## http/keycloak-cve-2026-18963-reset-credentials-bypass

CVE-2026-18963 (GHSA-4gv3-mc9p-5wqc), `http` identity. Keycloak 26.0.0 through 26.7.1 unauthenticated account takeover through the reset-credentials flow. The flow trusts a boolean `AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED` note and `ResetCredentialEmail.action()` succeeds without an action token, so a caller who knows a username skips the email gate, lands on UPDATE_PASSWORD, sets a new password, and logs in as the victim. The solution replays cookies and rotating session codes with `capture`, uses `raw-form` bodies for the multi-field update-password form, and ends with a direct-grant login as the final assert. Verified on Keycloak 26.7.1 (8/8), falsified on 26.7.2 (the selector re-show and bypass steps fail). Adjust the `vars` (realm, client, username, newpass) for the target.

## http/nextjs-cve-2026-75604-rce

CVE-2026-75604 (GHSA-p293-qw3h-jr36), `http` identity. Unauthenticated remote command execution in Windows-hosted Next.js. The solution walks the reference attack chain: it reads the dynamic Pages ISR page for the build id, primes the dynamic App-route cache with a backslash traversal (`Connection: close`, required for the cache entry to flush), leaks the private Server Action manifest through the pages data route (`encryptionKey` plus action ids), parses the Server Action form for the reference and action id, seals the bound arguments with a `set` AES-GCM transform, and POSTs a forged multipart action whose constructor gadget runs `cmd.exe` and phones the output back to the OOB listener. The forge step's report line shows the command output (`body "command\\goldendivider"`). Verified on next@16.2.11 (4/4), falsified on next@16.3.3 (the leak-manifest step fails and the run reports not verified). The target must be a native Windows server with a pristine `.next` cache; a failed traversal attempt writes a rendered cache entry that shadows the manifest until the build is rebuilt. Adjust `origin`, `field`, and `command` in `vars`.