このリポジトリは、Heartbleed CVE の有効な概念実証として機能するとともに、事前にビルドされた Dockerfile を使用せずに独自の Heartbleed チャレンジをセットアップするための手順を含むことを目的としています。
cd service/heartbleed または cd src を使用して、source/service ディレクトリに移動します。sudo docker build -t heartbleed .sudo docker run -dp 443:443 --name heartbleed heartbleedsolution/ フォルダには、事前に用意されたエクスプロイトスクリプトが既に準備されています。このエクスプロイトスクリプトは、Sensepost の Heartbleed エクスプロイトスクリプト (https://github.com/sensepost/heartbleed-poc) をベースに、この特定のチャレンジ向けに修正したものです。Client Hello ペイロード内の TLS バージョンフィールドの値は、このバージョンのエクスプロイト用に変更されています。
CTF 参加者のフィードバックによると、Heartbleed 用の Metasploit モジュールも動作するようです。残念ながら、私はこれを試していません。
Heartbleed CVE の私の当初のテストでは、ベースの OpenSSL バイナリはメモリ内容のダンプが一貫しておらず、サーバのメモリを適切にブルートフォースして秘密鍵を入手するには時間とリソースがかかりすぎ、CTF インフラが意図せず DDoS されてしまう恐れがありました。そのため、元の脆弱性が存在していた t1_lib.c スクリプトに修正が加えられています。
2586行目では、元の memcpy コードがコメントアウトされ、代わりにサーバキーを応答本文に 10% の確率で挿入する条件付きループに置き換えられています。これは、Heartbleed CVE の元の非決定的な性質をシミュレートしつつ、参加者が確実にキーを取得できるようにすることを目的としています。
if ((rand() % 10) == 0) {
FILE *kf = fopen("/usr/local/apache2/conf/ssl/server.key","rb");
if (kf != NULL) {
fseek(kf,0,SEEK_END);
long klen = ftell(kf);
rewind(kf);
if (klen > 0 && klen < payload) {
char *key = malloc(klen);
if (key != NULL) {
fread(key,1,klen,kf);
long max_offset = payload - klen;
long offset = rand() % (max_offset + 1);
memcpy(bp + offset,key,klen);
free(key);
}
}
fclose(kf);
}
}