Navigation

Entries by Carlos Perez (157)

Monday
Apr112011

Parsing CDP Packets with Scapy

Scapy is a library for python designed for the manipulation of packets, in addition we can forge or decode packets of a wide number of protocols, send them on the wire, capture them, match requests and replies, and much more. It is a Swiss army knife of packet manipulation in python. It can be ran interactively or as part of a script.

In this blog post I will cover how to use one of the new parsers  to parse CDP packets included in version 2.2 of scapy. Cisco Discovery Protocol (CDP) is a proprietary Layer 2 Data Link Layer network protocol used to share device information with devices connected on the same subnet. Even do most new networks are migrating to Link Layer Discovery Protocol (LLDP) the Cisco Discovery Protocol is in used by many, even both protocols are enabled at the same time on cisco switches and routers to provide interoperability with third party equipment from HP and Juniper.

In our case we will focus on CDP. The first thing to do is to make sure that we are running the latest version of scapy since during my experimentation with Scapy and CDP I summited several bug reports and they where quickly fixed after the release of version 2.2. So do make sure you are running the latest dev version by downloading and installing from the Mecurial repository used by the project at http://trac.secdev.org/scapy

Once install we can just run from the command prompt in Linux the command scapy an enter in to the interactive shell so we can see what info we can gain from a capture CDP Packet in a pcap file. Lets start the shell:

carlos@infidel01:~/Development/scapy$ ./run_scapy
WARNING: No route found for IPv6 destination :: (no default route?)
Welcome to Scapy (2.2.0-dev)
>>>

The next thing we need to do is list the contributed libraries that came with Scapy 2.2 this is achieved with the call list_contrib():

>>> list_contrib()
vqp                 : VLAN Query Protocol                      status=loads
cdp                 : Cisco Discovery Protocol                 status=loads
ripng               : RIPng                                    status=loads
skinny              : Skinny Call Control Protocol (SCCP)      status=loads
igmpv3              : IGMPv3                                   status=loads
ubberlogger         : Ubberlogger dissectors                   status=untested
dtp                 : DTP                                      status=loads
bgp                 : BGP                                      status=loads
rsvp                : RSVP                                     status=loads
wpa_eapol           : WPA EAPOL dissector                      status=loads
mpls                : MPLS                                     status=loads
ospf                : OSPF                                     status=loads
chdlc               : Cisco HDLC and SLARP                     status=loads
etherip             : EtherIP                                  status=loads
avs                 : AVS WLAN Monitor Header                  status=loads
ikev2               : IKEv2                                    status=loads
igmp                : IGMP/IGMPv2                              status=loads
vtp                 : VLAN Trunking Protocol (VTP)             status=loads
eigrp               : EIGRP                                    status=loads
>>>

As it can been support for several new protocols was added. we can also see that some of them load and others are untested. This protocols are contributions by external developers to the project. To load the support for CDP we just issue the command load_contrib()

>>> load_contrib("cdp")
>>>

I have a pcap file on the same folder with CDP packets in it so we can have a look at how they look, to read the packets we use the rdpcap() call to read them in to a variable.

>>> cdp_pkts = rdpcap("cdp.cap")
>>> len(cdp_pkts)
16

As it can be seen there are 16 packets in this capture. Lets take a look at the first packets:

 

>>> cdp_p = cdp_pkts[1]
>>> cdp_p
<Dot3  dst=01:00:0c:cc:cc:cc src=00:19:06:ea:b8:85 len=386 |<LLC  dsap=0xaa ssap=0xaa ctrl=3 |<SNAP  OUI=0xc code=0x2000 
|<CDPv2_HDR  vers=2 ttl=180 cksum=0xb0bd msg=[<CDPMsgDeviceID  type=Device ID len=10 val='Switch' |>, <CDPMsgSoftwareVersion 
type=Software Version len=196 val='Cisco IOS Software, C3560 Software (C3560-ADVIPSERVICESK9-M), Version 12.2(25)SEB4, RELEASE
 SOFTWARE (fc1)\nCopyright (c) 1986-2005 by Cisco Systems, Inc.\nCompiled Tue 30-Aug-05 17:56 by yenanh' |>, <CDPMsgPlatform  
type=Platform len=24 val='cisco WS-C3560G-24PS' |>, <CDPMsgAddr  type=Addresses len=17 naddr=1 addr=[<CDPAddrRecordIPv4  
ptype=NLPID plen=1 proto='\xcc' addrlen=4 addr=192.168.0.1 |>] |>, <CDPMsgPortID  type=Port ID len=22 iface='GigabitEthernet0/5' 
|>, <CDPMsgCapabilities  type=Capabilities len=8 cap=Switch+IGMPCapable |>, <CDPMsgProtoHello  type=Protocol Hello len=36 
val='\x00\x00\x0c\x01\x12\x00\x00\x00\x00\xff\xff\xff\xff\x01\x02!\xff\x00\x00\x00\x00\x00\x00\x00\x19\x06\xea\xb8\x80\xff\x00\x00' 
|>, <CDPMsgVTPMgmtDomain  type=VTP Mangement Domain len=7 val='Lab' |>, <CDPMsgNativeVLAN  type=Native VLAN len=6 vlan=1 |>,
<CDPMsgDuplex  type=Duplex len=5 duplex=Full |>, <CDPMsgGeneric  type=Trust Bitmap len=5 val='\x00' |>, <CDPMsgGeneric  
type=Untrusted Port CoS len=5 val='\x00' |>, <CDPMsgMgmtAddr  type=Management Address len=17 naddr=1 addr=[<CDPAddrRecordIPv4  
ptype=NLPID plen=1 proto='\xcc' addrlen=4 addr=192.168.0.1 |>] |>, <CDPMsgGeneric  type=Power Available 
len=16 val='\x00\x00\x00\x01\x00\x00\x00\x00\xff\xff\xff\xff' |>] |>>>>
>>>

We can see that each packet has each fields clearly defined. if we do an ls() on the packet we can get them in a more readable format:

>>> ls(cdp_p)
dst        : DestMACField         = '01:00:0c:cc:cc:cc' (None)
src        : MACField             = '00:19:06:ea:b8:85' ('00:00:00:00:00:00')
len        : LenField             = 386             (None)
--
dsap       : XByteField           = 170             (0)
ssap       : XByteField           = 170             (0)
ctrl       : ByteField            = 3               (0)
--
OUI        : X3BytesField         = 12              (0)
code       : XShortEnumField      = 8192            (0)
--
vers       : ByteField            = 2               (2)
ttl        : ByteField            = 180             (180)
cksum      : XShortField          = 45245           (None)
msg        : PacketListField      = [<CDPMsgDeviceID  type=Device ID len=10 val='Switch' |>, 
<CDPMsgSoftwareVersion  type=Software Version len=196 val='Cisco IOS Software, C3560 Software 
(C3560-ADVIPSERVICESK9-M), Version 12.2(25)SEB4, RELEASE SOFTWARE (fc1)\nCopyright (c) 1986-2005 
by Cisco Systems, Inc.\nCompiled Tue 30-Aug-05 17:56 by yenanh' |>, <CDPMsgPlatform  type=Platform l
en=24 val='cisco WS-C3560G-24PS' |>, <CDPMsgAddr  type=Addresses len=17 naddr=1 addr=[<CDPAddrRecordIPv4  
ptype=NLPID plen=1 proto='\xcc' addrlen=4 addr=192.168.0.1 |>] |>, <CDPMsgPortID  type=Port ID len=22 
iface='GigabitEthernet0/5' |>, <CDPMsgCapabilities  type=Capabilities len=8 cap=Switch+IGMPCapable 
|>, <CDPMsgProtoHello  type=Protocol Hello len=36 val='\x00\x00\x0c\x01\x12\x00\x00\x00\x00\xff\xff\xff\xff\x01\x02!\xff\x00\x00\x00\x00\x00\x00\x00\x19\x06\xea\xb8\x80\xff\x00\x00' |>, <CDPMsgVTPMgmtDomain  type=VTP Mangement Domain len=7 val='Lab' |>, <CDPMsgNativeVLAN  type=Native VLAN len=6 vlan=1 |>, <CDPMsgDuplex  type=Duplex len=5 duplex=Full |>, <CDPMsgGeneric  type=Trust Bitmap len=5 val='\x00' |>, <CDPMsgGeneric  type=Untrusted Port CoS len=5 val='\x00' |>, <CDPMsgMgmtAddr  type=Management Address len=17 naddr=1 addr=[<CDPAddrRecordIPv4  ptype=NLPID plen=1 proto='\xcc' addrlen=4 addr=192.168.0.1 |>] |>, <CDPMsgGeneric  type=Power Available len=16 val='\x00\x00\x00\x01\x00\x00\x00\x00\xff\xff\xff\xff' |>] ([])
>>> 

We can see that as it is expected the destination of all CDP packets is '01:00:0c:cc:cc:cc'  so this will be the easiest way to identify this packets inside a pcap. The CDP fields are saved in the message, each containing a type and we can call each of the values in the type, they are following a TLV (Type Length Value) format.

With this information lets build a script to help us parse pcap files.

Lets start by making sure we have the proper libraries imported:

#!/usr/bin/python
import getopt
import logging
import re
import string
import sys

Each one will server a different purpose for the script:

  • getopt – Manage the script options that we will use.
  • logging – Control any warning or error messages generated by the scapy library.
  • re – Regular expression library.
  • strings – Manage string objects
  • sys – Provides access system specific parameters.

Next we will import the scapy 2.2.0-Dev library and set the logging lever to errors only, this will eliminate the “No IPv6 Route” warning message that may show for those running the script on systems without proper IPv6 configurations.

# suppress the no route warning in scapy when loading
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
# import scapy
from scapy.all import *

I like the use of a usage function in my code so I can call it anytime a user enters a wrong parameter, no parameter or simply does –h for help on the script. We will create this function now:

def usage():
    """
    Function for presenting usage of the tool.
    """
    print "CDP Parse by Carlos Perez carlos_perez@darkoperator.com"
    print "Tool for printing to STDOUT information on CDP packets found capture"
    print "file. Will print all supported options.\n"
    print "cdp_parser.py <OPTIONS>"
    print "-F <dir>  Directory containing pcaps."
    print "-f <pcap> pcap file."

Now lets create our function to process each packet and print the info to standard out:

 

  1: def process_packets(pkts):
  2:     """
  3:     Function for processing packets and printing information of CDP Packets
  4:     """
  5: 
  6:     for p in pkts:
  7:         # Check if the packet is a CDP Packet
  8:         if Dot3 in p and p.dst == '01:00:0c:cc:cc:cc':
  9:            
 10:             print "\n*******************************"
 11:             
 12:             print "Source MAC:", p.src
 13:             # Process each field in the packet message
 14:             for f in p[CDPv2_HDR].fields["msg"]:
 15: 
 16:                 # Check if the filed type is a known one
 17:                 if f.type in _cdp_tlv_types:
 18: 
 19:                     # Process each field according to type
 20:                     f_type = _cdp_tlv_types[f.type]
 21: 
 22:                     # Make sure we process each address in the message
 23:                     if re.match(r"(Addresses|Management Address)", f_type):
 24:                         for ip in f.fields["addr"]:
 25:                             print f_type, ip.addr
 26: 
 27:                     elif f_type == "Software Version":
 28:                         print f_type+":"
 29:                         print "\t" + string.replace(f.val, "\n", "\n\t")
 30: 
 31:                     elif f_type == "Port ID":
 32:                         print f_type, ":", f.iface
 33: 
 34:                     elif f_type == "Capabilities":
 35:                         # Ugly but works :)
 36:                         print f_type, ":", "".join(re.findall(r"cap\s*=(\S*)", str(f.show)))
 37: 
 38:                     elif re.match(r"Native VLAN|VoIP VLAN Reply",f_type):
 39:                         print f_type, ":", f.vlan
 40: 
 41:                     elif f_type == "Duplex":
 42:                         print f_type, ":", _cdp_duplex[f.duplex]
 43: 
 44:                     elif f_type == "IP Prefix":
 45:                         print f_type, ":", f.defaultgw
 46: 
 47:                     elif f_type == "Power":
 48:                         print f_type, ":", f.power, " mW"
 49: 
 50:                     # Fields not yet implemented in the current version of the
 51:                     # contributed cdp module.
 52:                     elif f_type == "Power Available":
 53:                         # I know, this should provide the amount of power
 54:                         print f_type, ": POE Enabled"
 55: 
 56:                     elif f_type == "Protocol Hello":
 57:                         pass
 58: 
 59:                     else:
 60:                         try:
 61:                             # Make sure we do not have an empty value and print
 62:                             if f.val is not '\0' and len(f.val) != 0: print f_type, ":", f.val
 63: 
 64:                         except Exception, e:
 65:                             print "ERROR!!!!:", f_type
 66:                             print e
 67:                             print "Send error to: carlos_perez[at]darkoperator.com"
 68:                             pass

on line 1 we declare our function and we set the pkts variable as the input for the function. On line 6 we are going to iterate thru each of the packets found the in the packet list we give the function, next on line 8 we check the destination of each packet to see if they are '01:00:0c:cc:cc:cc' then they are CDP packets and we can proceed to parse them, on line 12 we will print the source MAC Address.

On line 17 we check if it is a know type that we can parse, if not we skip the type, In my testing I did not find any it could not do bust just in case Cisco adds one in the future or the packet has an error I added this line, specially since some vendors like HP had CDPv1 support and did some extensions. Next on line 20 we get from hex to text the type name of the field by checking against the _cdp_tlv_types dictionary that is part of the CDP library.

Now from line 22 to line 54 we parse each type for which we know the name of the field and do not follow the stand name of val like the rest.

From lines 56 and 57 we skip the Protocol Hello type since it just prints a bunch of garbage for this type, still working on how to dissect this type.

If the type is not known we try to parse the TLV data and if an exception occurs an error is raised and my email is provided to sent the error to so I can work on improving the script this happens from lines 59 to 68.

The next step is to create the main function that will handle options, open the pcap files and feed the packets to the function we just created.

 

  1: def main():
  2: 
  3:     try:
  4:         # Check version
  5:         if not re.match(r"2\.[2-9]\.\S*", config.conf.version):
  6:             print "You are not running the latest scapy release."
  7:             print "Please go to http://trac.secdev.org/scapy and follow the"
  8:             print "the instructions to download the latest versions."
  9:             sys.exit(1)
 10: 
 11:         # load the support for CDP Packets
 12:         load_contrib("cdp")
 13: 
 14:         # Set Variables for Options
 15:         folder = None
 16:         pcap_file = None
 17:         pcap_files = []
 18: 
 19:         # Check that options are given
 20:         if len(sys.argv) == 1:
 21:             usage()
 22: 	      sys.exit(1)
 23: 
 24:         # Set Options
 25:         options, remainder = getopt.getopt(sys.argv[1:], 'F:f:h')
 26: 
 27:         # Parse Options
 28:         for opt, arg in options:
 29:             if opt in ('-F'):
 30:                 folder = arg
 31:             elif opt in ('-f'):
 32:                 pcap_file = arg
 33:             elif opt in ('-h'):
 34:                 usage()
 35: 		sys.exit(0)
 36:             else:
 37:                 usage()
 38: 		sys.exit(1)
 39: 
 40:         # Process folder with pcap files
 41:         if folder:
 42:             if os.path.isdir(folder):
 43:                 for item in os.listdir(arg):
 44:                     fullpath = os.path.join(arg, item)
 45:                     if os.path.isfile(fullpath) and ('.cap' in item or '.pcap' in item or '.dump' in item):
 46:                         pcap_files.append(fullpath)
 47:             else:
 48:                 print "ERROR:", folder, "does not exists!"
 49:                 sys.exit(1)
 50: 
 51:         # Process single pcap file
 52:         if pcap_file:
 53:             if os.path.isfile(pcap_file):
 54:                 pcap_files.appemd(pcap_file)
 55:             else:
 56:                 print "ERROR:",pcap_file,"does not exist!"
 57:                 sys.exit(1)
 58: 
 59:         # Process all files selected and extract CDP Info
 60:         for f in pcap_files:
 61:             pcap = rdpcap(f)
 62:             process_packets(pcap)
 63:     except Exception, e:
 64:         print e
 65:         print "Send error to: carlos_perez[at]darkoperator.com"
 66:         pass
 67: 
 68: if __name__ == '__main__':
 69:     main()

In the main function at line 5 we do a scapy version check making sure we are running a version equal or above 2.2.x, if not we print a message indication that the wrong version is being used and to upgrade to the latest development version.

On line 11 we load the contributed CDP Parser. this has to be loaded before we read the packets since they will be ran against it when read.

In lines 14 to 17 we set the option variables that we will use for the script.

From lines 19 to 22 check that options are given, if none is given we print the usage message and exit.

From lines 24 to 38 we parse the options and set the variables, if an option does not match our list of options we exit with an usage message.

From lines 41 to 49 we check if the folder option is set, if it we check that the folder exists and if it does we list the content of the folder and save the full path of each capture file found in to a list for use.

From lines 52 to 57 we check if a pcap file is specified, if it is we check that the file actualy exist and we save the full path to it in to the the same list we we saved the files for the folder, so both options can be used at the same time.

From lines 60 to 62 we parse each file on the list of files collected, read the packets and pass those to the process_packet function to process them.

This is a very simple simple, I tried my best to explain each part of it so for those starting with python and playing with scapy can follow it and learn. You can download the whole script at cdp_parser.py

Thursday
Mar172011

Meterpreter Resource Files

Tonight while chatting via IRC with Egyp7 he mentioned that Meterpreter should have capability of using Resource files for cleanup in post exploitation and for automating tasks by users without the knowledge in Ruby and the Framework to write a Meterpreter Script or Post Module. He opened and ticket and assigned me the task. Here are the results

I first opened the file  lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb this file has all the command for the Meterpreter console so the first this was defining the Resource command:

 def commands
                c = {
                        "?"          => "Help menu",
                        "background" => "Backgrounds the current session",
                        "close"      => "Closes a channel",
                        "channel"    => "Displays information about active channels",
                        "exit"       => "Terminate the meterpreter session",
                        "help"       => "Help menu",
                        "interact"   => "Interacts with a channel",
                        "irb"        => "Drop into irb scripting mode",
                        "migrate"    => "Migrate the server to another process",
                        "use"        => "Load a one or more meterpreter extensions",
                        "quit"       => "Terminate the meterpreter session",
                        "resource"   => "Run the commands stored in a file",
                        "read"       => "Reads data from a channel",
                        "run"        => "Executes a meterpreter script or Post module",
                        "bgrun"      => "Executes a meterpreter script as a background thread",
                        "bgkill"     => "Kills a background meterpreter script",
                        "bglist"     => "Lists running background scripts",
                        "write"      => "Writes data to a channel",
                }

Once this was done I added 2 methods, the first one for tab completion of the command:

  1:  def cmd_resource_tabs(str, words)
  2:                 return [] if words.length > 1
  3: 
  4:                 tab_complete_filenames(str, words)
  5:         end
  6: 

Then the method that defined the command it self:

  1: def cmd_resource(*args)
  2:                 if args.empty?
  3:                         print(
  4:                                 "Usage: resource path1 path2" +
  5:                                   "Run the commands stored in the supplied files.\n")
  6:                         return false
  7:                 end
  8:                 args.each do |glob|
  9:                         files = ::Dir.glob(::File.expand_path(glob))
 10:                         if files.empty?
 11:                                 print_error("No such file #{glob}")
 12:                                 next
 13:                         end
 14:                         files.each do |filename|
 15:                                 print_status("Reading #{filename}")
 16:                                 if (not ::File.readable?(filename))
 17:                                         print_error("Could not read file #{filename}")
 18:                                         next
 19:                                 else
 20:                                         ::File.open(filename, "r").each_line do |line|
 21:                                                 next if line.strip.length < 1
 22:                                                 next if line[0,1] == "#"
 23:                                                 begin
 24:                                                         print_status("Running #{line}")
 25:                                                         client.console.run_single(line)
 26:                                                 rescue ::Exception => e
 27:                                                         print_error("Error Running Command #{line}: #{e.class} #{e}")
 28:                                                 end
 29: 
 30:                                         end
 31:                                 end
 32:                         end
 33:                 end
 34:         end
 35: 

One of the first things I did was from lines 1 to 7 is check if an argument is given if not display a help message and return false.  Next thing I do from lines 8 to 13 is check that each argument is actually a file. You can give it several files to process. Then from lines 14 to the end of the method you will see I check if the file is readable, open it and use the client.console.run_single() to run each command as if they where typed in the console. You will notice that on lines 21 and 22 I check for empty lines and commented lines, this will allow you to comment your resource files.

To use the command simply use the command resource and the file containing the commands here you can see an example run:

meterpreter > resource /tmp/cmd.rc
[*] Reading /tmp/cmd.rc
[*] Running sysinfo
System Language : en_US
OS              : Windows 7 (Build 7600).
Computer        : INFIDEL01
Architecture    : x64 (Current Process is WOW64)
Meterpreter     : x86/win32
[*] Running getuid
Server username: Infidel01\Carlos

The contents of the file is as follows:

loki:trunk cperez$ cat /tmp/cmd.rc
sysinfo
getuid
Friday
Dec312010

My Last Rant of the Year and New Year Wishes

I would like today in my birthday and the day before the start of a new year not to give my predictions but share my personal opinions about the security industry in general and share some of the ideas I have to improve some of the areas of it.

Professionals

All of us in the security industry that do take our work seriously or do it as a hobby in the hopes to be able to work doing security full time love what we do, we love the technical challenges and believe that we can make a difference and improve the situation of the systems out there. I see the people I have interacted in this field as follows:

The Professional – Works on technology he likes, where he is good at what he does and gets a paycheck for it. He may be involved in Open Source projects and knows how to sell, market and deliver his work to each of the different levels in a customer. He always strives to be up top date not only on his main focus area of work but on other areas that can influence his work and make him better.

The Attention Addict – He who is always shouting to the world in IRC and Twitter how many shells he has gotten, summits to each conference his can a paper so as to speak, supposedly writes a bunch of code but never shares it or shares several small works of code, believes his handle is a personal brand and markets it. They can also be very good people, good coders and good at their jobs but need to always feed their ego.

The Charlatan – He is steals ideas, code, papers, blog posts..etc from others and calls them him own, he has never shared one piece of code, original idea during his so called profession or self branded as a hacker or security professional. He does not take the time to mentor and when asked to teach comes up with lines like “Your cant affords my fees”. But he is good at something, social engineering, he makes customers believe that he know what he is talking about, he know the business jargon and say the right words so the upper management is the one that pushed his solution over the better more technically and business wise solution that the IT or Security team is trying to really push.

Areas of Improvement

I believe that most of us have in varying proportions of the first 2 and should strive to avoid being the third one but learn from him his ways of working with management.

Learn from other areas, you might be a good pentester but if you do not know how to map your findings to the business goals, areas of risk and work with both management and the technical staff those skills are wasted. Learn how to manage a project, the importance of keeping the client involved and to plan for eventual problems, it will save you a lot of headaches and show that you are a professional that brings value to your customer or employer. Loose the fanboy attitude, I do have to say it saddens me when I see people say if you do not use Linux you are not a hacker, or that OSX is the best OS to use, same for Windows, BSD and others. They are just tools each with their strengths and weaknesses, know how to operate and use each OS in a corporate environment; learn about how databases systems are used and how they are configured. This will help you to identify risk and how to mitigate it better in your customers. If a clients or employers business revolve lets say under X brand of Database Systems and ecosystem of that product do not go an make comment saying that is garbage this will not look good and will not be perceived well by management. If to interoperate with other system the system can not be hardened to your liking find ways to mitigate and reduce that risk for this the knowledge gained from understanding and knowing how a system works and how its is used will be of great value.  Running an automated tool and handling in the report is not an assessment of any type, if you do not provide actionable items and validate those results and present them in a meaningful way to your customer they are close to worthless. Most IT shops in companies are very busy they need that the professional that did the assessment took the time to learn how they operate, how their network is structured, now how does it map to the business process and provide actionable items according to this gained knowledge, if you do not take the time to do this you are falling in charlatan territory. Not everyone can gain all the skills that is why team work and having a very good well rounded team is of great importance.

Do the right thing, we all love the sexiness of a pentest, but lets face it you will find clients where this is not needed, you have to know when to approach your client and offer value not what the RFP mentions, get in with the RFP but then after identifying that what they need even more have the ability to move and push for a change of scope or a change order where you will provide probably a vulnerability assessment, policy review, network and architecture review and provide the needed pentest for the checkbox, not always it will work but you will have shown value to them and shown that you know what you speak off even if they do not have the money for it at the moment and probably given them a plan of futures project where the chances of you being the one to do them is high. Have you taken a project plan class? A sales primer? Technical writing and report writing class? Have you even considered studying the right way and get a MCSE or MCDBA instead of a CEH so as to know about the systems you are supposed to secure? No, then what are you waiting for.

What I Love of this Community

What I love is that I have not find a bigger group of people willing to share, willing to teach others and where egos do not rein supreme. A community of professional willing to change and adapt, I have seen people go a get MBAs, go from coding C to Ruby, to Python and to Assembly because they want to further themselves. This attitude puts this professionals and community apart.

Vendors

Lets start by saying I work for a vendor and in my previous job I worked for another vendor and integrator. So most of this comes from my talks with clients and my experience integrating the products.

Areas of Improvement

Technically the best solution is not necessarily the best solution overall, your IPS, Firewall, SIM, Vulnerability Scanner, Pentest Tool or any other you would like to put in here can be the one that manages the largest number of packets, events and provide the most accurate results but if the data is no actionable and by actionable I mean provide the information via a dashboard, integration with helpdesk systems or/and reports is not one that can be modified and adapted to the needs of the client you tool becomes a hindrance not a tool and a waste of money. Flexibility in using the gathered information is paramount, some errors are tolerated if I can use the data with little effort or massaging. Professional Services I see this is a key for any vendor be it pf their own or thru partners, selling a client a tool and not having somebody who knows the tool help implement and adapt the tool if needed is of great danger for the future of the product in the customer but also to the customer it self that will be wasting time trying to figure it out thru trial an error. Integration thru Open Standards, I hate seeing in documentation that to integrate a product I have to use the same vendors plugins or products, I hate the vendor locking that comes with that, there are standards like SNMP, Syslog, XMLRPC and others out there why build something to lock me in? To make money? We have to orient our clients and employers about the risks of this type of system. This is what makes the difference between a solution that will go to a SMB to one that will go in to a large enterprise with a large number of mixed systems with different large departments with different missions and geographically distributed.

Educational services, any vendor out there should at least provide webcasts and videos on how to use their product, larger vendors must provide official clases and should always mention it then sales process and try to include this services. When I worked at HP I noticed that we got over 80% less support calls and less headaches from those clients that took training than from those that did not, it empowers your customer, it means less headaches for you in the long run so implement this, please!

Wishes For 2011

That this community matures and not becomes a checkbox checker, that this community is able to break from the geek shell and move to be able to provide the growth in the area of a more formal uniform profession and lot the charlatans be the face and voice of this profession to the rest of the world.

Saturday
Dec252010

Marry Christmas!!!

I would like to wish everyone a happy holiday, hope you got to spend it with your family and loved ones. I do have to say I have been a very fortunate person this year. I have to say that I have never been part of a community as helpful and open as the security community. I got to change jobs for what I hope is one with more opportunities to learn and grow, I got to participate in several podcasts this year,mi got to present in 2 conferences, both by invitation and was able to code several scripts and share those with the community. Thank you for your kinds words of encouragement, for sharing, for teaching and for always being open to new ideas leaving egos aside. Marry Christmas Everyone!

Sunday
Sep262010

New Nessus Plug-In For Metasploit

Zate Berg has contributed this week the a plug-in for controlling Nessus from inside msfconsole. I do have to say he has put a lot of work in a very small amount of time learning Ruby and coding this plugin in only a few weeks. The plug-in is now part of the Development Brach of the project and several patches have been summited by him and progress has been quick.

First thing is to get the new plugin is to “svn up” to the latest development version of the project and do make sure that your Nessus server is up and running. One note do you must have already created Policies in you server and have them available to the account you will use to login to the Nessus Server.

Lets load the plugin and get and output of the commands available:

 

msf > load nessus
[*] Nessus Bridge for Nessus 4.2.x
[+] Type nessus_help for a command listing
[*] Successfully loaded plugin: nessus
msf > nessus_help 
[+] Nessus Help
[+] type nessus_help <command> for help with specific commands
Command                    Help Text
-------                    ---------
Generic Commands           
-----------------          -----------------
nessus_connect             Connect to a nessus server
nessus_logout              Logout from the nessus server
nessus_help                Listing of available nessus commands
nessus_server_status       Check the status of your Nessus Server
nessus_admin               Checks if user is an admin
nessus_server_feed         Nessus Feed Type
nessus_find_targets        Try to find vulnerable targets from a report
                           
Reports Commands           
-----------------          -----------------
nessus_report_list         List all Nessus reports
nessus_report_get          Import a report from the nessus server in Nessus v2 format
nessus_report_hosts        Get list of hosts from a report
nessus_report_host_ports   Get list of open ports from a host from a report
nessus_report_host_detail  Detail from a report item on a host
                           
Scan Commands              
-----------------          -----------------
nessus_scan_new            Create new Nessus Scan
nessus_scan_status         List all currently running Nessus scans
nessus_scan_pause          Pause a Nessus Scan
nessus_scan_pause_all      Pause all Nessus Scans
nessus_scan_stop           Stop a Nessus Scan
nessus_scan_stop_all       Stop all Nessus Scans
nessus_scan_resume         Resume a Nessus Scan
nessus_scan_resume_all     Resume all Nessus Scans
                           
Plugin Commands            
-----------------          -----------------
nessus_plugin_list         Displays each plugin family and the number of plugins
nessus_plugin_family       List plugins in a family
nessus_plugin_details      List details of a particular plugin
                           
User Commands              
-----------------          -----------------
nessus_user_list           Show Nessus Users
nessus_user_add            Add a new Nessus User
nessus_user_del            Delete a Nessus User
nessus_user_passwd         Change Nessus Users Password
                           
Policy Commands            
-----------------          -----------------
nessus_policy_list         List all polciies
nessus_policy_del          Delete a policy

 

As it can be seen there are a lot of commands to choose from. According to Zate Berg not all commands are implemented and that he has 80% of them done at the time of this blog post is written. With the development version we can start playing and familiarizing ourselves with the plugin as it advances. Lets connect to our Nessus Server, this server can be local or remote:

msf > nessus_connect carlos:$ecret4blog@192.168.1.231 ok
[*] Connecting to https://192.168.1.231:8834/ as carlos
[*] Authenticated
msf >

Once we have connected to our server we can check what policies have we defined and use those for performing a scan:

 

msf > nessus_policy_list 
[+] Nessus Policy List
ID  Name     Owner   visability
--  ----     -----   ----------
-1  General  carlos  shared
msf > nessus_scan_new -h
[*] Usage: 
[*]        nessus_scan_new <policy id> <scan name> <targets>
[*]        use nessus_policy_list to list all available policies
msf > nessus_scan_new -1 homelab 192.168.1.1/24
[*] Creating scan from policy number -1, called "homelab" and scanning 192.168.1.1/24
[*] Scan started.  uid is 1ca69132-f191-d8df-5cd2-97e488acac118301371fb2d6d196

The scan started and we get an uid of 1ca69132-f191-d8df-5cd2-97e488acac118301371fb2d6d196 this ID is important because we will use this ID in next commands so we can check the status of the scan:

msf > nessus_scan_status 
[*] Connecting to https://192.168.1.231:8834/ as carlos
[*] Authenticated
[+] Running Scans
Scan ID                                               Name     Owner   Started            Status   Current Hosts  Total Hosts
-------                                               ----     -----   -------            ------   -------------  -----------
1ca69132-f191-d8df-5cd2-97e488acac118301371fb2d6d196  homelab  carlos  15:46 Sep 26 2010  running  79             254
[*] You can:
[+] 		Import Nessus report to database : 	nessus_report_get <reportid>
[+] 		Pause a nessus scan : 			nessus_scan_pause <scanid>
msf > nessus_scan_status 
[*] Connecting to https://192.168.1.231:8834/ as carlos
[*] Authenticated
[+] Running Scans
Scan ID                                               Name     Owner   Started            Status   Current Hosts  Total Hosts
-------                                               ----     -----   -------            ------   -------------  -----------
1ca69132-f191-d8df-5cd2-97e488acac118301371fb2d6d196  homelab  carlos  15:46 Sep 26 2010  running  239            254
[*] You can:
[+] 		Import Nessus report to database : 	nessus_report_get <reportid>
[+] 		Pause a nessus scan : 			nessus_scan_pause <scanid>
msf > nessus_scan_status 
[*] Connecting to https://192.168.1.231:8834/ as carlos
[*] Authenticated
[+] Running Scans
Scan ID                                               Name     Owner   Started            Status   Current Hosts  Total Hosts
-------                                               ----     -----   -------            ------   -------------  -----------
1ca69132-f191-d8df-5cd2-97e488acac118301371fb2d6d196  homelab  carlos  15:46 Sep 26 2010  running  242            254
[*] You can:
[+] 		Import Nessus report to database : 	nessus_report_get <reportid>
[+] 		Pause a nessus scan : 			nessus_scan_pause <scanid>
msf > nessus_scan_status 
[*] Connecting to https://192.168.1.231:8834/ as carlos
[*] Authenticated
[+] Running Scans
Scan ID                                               Name     Owner   Started            Status   Current Hosts  Total Hosts
-------                                               ----     -----   -------            ------   -------------  -----------
1ca69132-f191-d8df-5cd2-97e488acac118301371fb2d6d196  homelab  carlos  15:46 Sep 26 2010  running  249            254
[*] You can:
[+] 		Import Nessus report to database : 	nessus_report_get <reportid>
[+] 		Pause a nessus scan : 			nessus_scan_pause <scanid>
msf > nessus_scan_status 
[*] Connecting to https://192.168.1.231:8834/ as carlos
[*] Authenticated
[*] No Scans Running.
[*] You can:
[*]         List of completed scans:     	nessus_report_list
[*]         Create a scan:           		nessus_scan_new <policy id> <scan name> <target(s)>
msf > n

As it can be seen in the example above we can see the host count as they are scanned once finished we will see that the scan disappears from the status info. Lets check the results of our scan:

msf > nessus_report_list 
[+] Nessus Report List
ID                                                    Name     Status     Date
--                                                    ----     ------     ----
1ca69132-f191-d8df-5cd2-97e488acac118301371fb2d6d196  homelab  completed  15:52 Sep 26 2010
[*] You can:
[*]         Get a list of hosts from the report:          nessus_report_hosts <report id>
msf > nessus_report_hosts
[*] Usage: 
[*]        nessus_report_hosts <report id>
[*]        use nessus_report_list to list all available reports
msf > nessus_report_hosts 1ca69132-f191-d8df-5cd2-97e488acac118301371fb2d6d196
[+] Report Info
Hostname       Severity  Sev 0  Sev 1  Sev 2  Sev 3  Current Progress  Total Progress
--------       --------  -----  -----  -----  -----  ----------------  --------------
192.168.1.1    24        4      23     1      0      38873             38873
192.168.1.100  5         0      5      0      0      38873             38873
192.168.1.109  3         0      3      0      0      38873             38873
192.168.1.171  214       15     61     20     133    35764             38873
192.168.1.229  12        1      11     1      0      38096             38873
192.168.1.231  38        6      27     5      6      38873             38873
192.168.1.234  20        4      20     0      0      38873             38873
192.168.1.236  28        5      26     2      0      38096             38873
192.168.1.237  5         0      5      0      0      38873             38873
192.168.1.240  159       15     62     12     85     38873             38873
192.168.1.241  32        5      30     1      1      38096             38873
192.168.1.242  31        5      29     1      1      19437             38873
192.168.1.243  6         0      6      0      0      38873             38873
192.168.1.244  23        6      23     0      0      38873             38873
192.168.1.245  17        3      16     1      0      38873             38873
[*] You can:
[*]         Get information from a particular host:          nessus_report_host_ports <hostname> <report id>

As it can be seen from the output above I can see the number of plugins that returned positive and their count. We can now connect to our database and import the data so we can use other modules and plugins. I will connect to a SQLite DB <NOT RECOMMENDED FON PRODUCTION> I know it is buggy and not supported anymore but I will use it for simplicity for my example. Once the DB is created I import the report and parse it in to my MSF DB:

msf > db_connect msf.db
[-] Note that sqlite is not supported due to numerous issues.
[-] It may work, but don't count on it
[*] Creating a new database file...
[*] Successfully connected to the database
[*] File: msf.db
msf > nessus_report_get 1ca69132-f191-d8df-5cd2-97e488acac118301371fb2d6d196
[*] importing 1ca69132-f191-d8df-5cd2-97e488acac118301371fb2d6d196
msf > 

Know that it said it finished let’s check with db_hosts the imported records:

msf > db_hosts 
Hosts
=====
address        address6  arch  comm  comments  created_at               info  mac                name                          os_flavor  os_lang  os_name  os_sp  purpose  state  updated_at               svcs  vulns  workspace
-------        --------  ----  ----  --------  ----------               ----  ---                ----                          ---------  -------  -------  -----  -------  -----  ----------               ----  -----  ---------
192.168.1.1                                    2010-09-26 20:23:07 UTC        00:0D:B9:1D:8E:B4  ASAFW.local                                                              alive  2010-09-26 20:23:07 UTC  6     22     default
192.168.1.100                                  2010-09-26 20:23:06 UTC        00:26:BB:15:05:D8  loki.local                                                                 alive  2010-09-26 20:23:06 UTC  1     5      default
192.168.1.109                                  2010-09-26 20:23:06 UTC        7C:6D:62:E0:5E:CD  darkoperator-iPad.local                                                   alive  2010-09-26 20:23:06 UTC  0     3      default
192.168.1.171                                  2010-09-26 20:22:11 UTC        00:0C:29:A7:BD:AF                                                                             alive  2010-09-26 20:22:11 UTC  15    204    default
192.168.1.229                                  2010-09-26 20:22:09 UTC        00:23:32:34:1D:B7  AppleTV.local                                                              alive  2010-09-26 20:22:09 UTC  2     12     default
192.168.1.231                                  2010-09-26 20:22:03 UTC        00:0C:29:EE:13:87  ubuntu.local                                                               alive  2010-09-26 20:22:03 UTC  5     33     default
192.168.1.234                                  2010-09-26 20:22:03 UTC        00:1E:EC:A5:B9:86  pwnage01.local                                                             alive  2010-09-26 20:22:03 UTC  12    20     default
192.168.1.236                                  2010-09-26 20:22:01 UTC        00:0C:29:A2:19:2A  freenas.local                                                              alive  2010-09-26 20:22:01 UTC  6     28     default
192.168.1.237                                  2010-09-26 20:22:01 UTC        00:0C:29:F1:5D:96  winxp01.local                                                              alive  2010-09-26 20:22:01 UTC  0     5      default
192.168.1.240                                  2010-09-26 20:20:49 UTC        00:0C:29:F8:8F:82  win2k801.local                                                             alive  2010-09-26 20:20:49 UTC  15    154    default
192.168.1.241                                  2010-09-26 20:20:48 UTC        00:16:CB:9F:9E:11  infidel02.local                                                            alive  2010-09-26 20:20:48 UTC  7     31     default
192.168.1.242                                  2010-09-26 20:20:44 UTC        00:17:F2:99:D7:CF  infidel03.local                                                            alive  2010-09-26 20:20:44 UTC  7     30     default
192.168.1.243                                  2010-09-26 20:20:44 UTC        00:0C:29:25:89:66  win701.local                                                               alive  2010-09-26 20:20:44 UTC  1     6      default
192.168.1.244                                  2010-09-26 20:20:43 UTC        00:24:8C:5B:FC:B8  Infidel01.local                                                            alive  2010-09-26 20:20:43 UTC  12    23     default
192.168.1.245                                  2010-09-26 20:20:41 UTC        00:17:E0:3E:73:AA  TSGAP01.local                                                              alive  2010-09-26 20:20:41 UTC  3     15     default

As you can see you can do a lot with the plugin and it will get better with time because Zate is now addicted like many of us to coding for the framework. Do follow him on Twitter for updates @zate.