Navigation

Entries from April 1, 2011 - April 30, 2011

Saturday
Apr302011

Zero Day Review

 

Zero Day is a novel by Mark Russinovich, his name is very well known to security professionals and system administrators that work with Microsoft systems alike, all have used the great set of utilities that he has written under his own company Winternals before being acquired by Microsoft and still available and updated as part of the sys internals suite of tools. He has used his experience in the Security field and community to write this novel in an action style story Tom Clancy style.

The story starts via a series of events caused by computer systems failing and data and information being altered with catastrophic events, this opens the story to the introduction of the main character Jeff Aiken a security consultant that is called to look at an infection the destroyed the systems of a New York law firm. The character is of a bright security consultant driven by events in his past and the passion for the trill of the chase of hackers and solving the complex puzzle of digital forensics.  As he delves deeper in the origins of the virus and the work of Daryl Hagen a bright determined women that manages a US CERT team and is part CISU/DHS looking at the other cases they discover that this infections are all connected and just the tip of the iceberg of bigger attack that will hit the western governments. The story covers the typical terrorist plot of vengeance against the corrupted west that has been seen in so many novels after 9/11 but this one presents the twist that this time the attack is a cyber attack with very dark consequences.

As as security researcher and professional I can relate to what Mark exposes in the book, specially the reality that our capacity to defend against a coordinated cyber attack is just not existent.  All of us in the industry that have found holes in systems have been frustrated many times with the speed of the response of private companies to address these holes and the lack of cooperation between them. He mentions how antivirus vendors are flooded with more samples of malware code than what they can handle. He cover the reality how we are loosing the battle against malware writers but in this case the malware writers have a more deadly agenda than feeding their egos or making money like many out there in the real world. I do have to say I do relate to all the problems faced by the heroes in the story making it more real in my imagination as I read the book. I could even relate to the pain of some of the victims having gone to clients to assist in recovering from security breaches and malware infections. I even related to the addictive nature that we in the security field have when we are faced with the hunt of an adversary while doing incident response and how that trill of the chance consumes us in the process.

He also covered the problems that some of the bright women that are in this industry faced with prejudice and lack of respect by their peers. I found this part of the story very interesting knowing myself women in the industry and in general that have had to face this and fought to be measured and valued by the quality of their work and knowledge.

I don have to say that I really liked the book and the pace of the story. My tactical side related to the accuracy of the depiction of the action and the weapons and my info sec side related perfectly with main characters and their frustrations with government and industry and the drive that pushed them. I even related with Russian character persona and the choices that many starting in the security field are faced with in term of the direction our research takes and the consequences of those decisions and what may drive many ton make the wrong ones.

I recommend d this book to any security professional in the industry and to any person who likes actions and intrigue found in Tom Clancy and Alex Berenson books. I do hope that Mark writes another one like this and gives life to the characters behind this book.

Book on Amazon

Friday
Apr292011

Microsoft EMET

Many times we are faced with the situation of not being able to patch software in time and many times do to the way companies work and handle security vulnerabilities the time of exposure is a very long one. Microsoft has worked in to making it harder for attacker to exploit code by adding in to the operating system and to several of their products mitigating technologies, but sadly not all Microsoft products or third party products use these mitigating technologies. To help with this Microsoft released the Enhanced Mitigation Experience Toolkit. This toolkit include several pseudo mitigation technologies aimed at disrupting current exploit techniques, it is not a perfect solution in terms that it can make it harder for known techniques used out there, so this makes this toolkit very effective in managing risk. It provides 7 protections:

Structure Exception Handler Overwrite Protection (SEHOP)

  • Dynamice Data Execution Prevention (DEP) Application Level
  • Dynamice Data Execution Prevention (DEP) System Level
  • Heapspray Allocations
  • Null Page Allocation
  • Mandatory Address Space Layout Randomization (ASLR)
  • Export Address Table Access Filtering (EAF)

This options are not present on all Operation Systems

 

image

 

Also depends on the CPU

 

image

 

As it can be be seen from the table, the latest the OS the more protection can be used. The advantage of EMET is that many applications have to be compiled with proper flags and libraries to be able to use these protections, but with EMET they can be forced at the system and application level. With attackers moving more and more to client side attacks and with many companies dependent on applications that many times can not be updated do to the vendor not supporting them on newer versions of Windows, patches taking to much time or just plain quality problems from the company that programed the tool.

Once you install the tool the main screen is very Spartan in terms of information given:

image

You can see 2 configuration areas the top part for configuring the system settings and the lower part for configuring the application protection settings. The System configuration

image

You can select one of 2 recommended profiles:

  • Maximum Security
  • Recommended Security Settings

or you can set each of the protection settings.

You can also configure several protections per application:

image

You can push the tool to your servers and client systems thru any package manager that can automate the installation thru MSI. The configuration of the programs to add for protection can be automated very easily via the command line:

C:\Program Files (x86)\EMET>EMET_Conf.exe
Usage: EMET_Conf.exe [--list | --add path\program.exe | --delete path\program.ex
e | --delete_all]

I highly recommend this tools for anyone that run Microsoft Windows. I highly recomend it for all web browsers, Document editors , media player and for any service that can be touched via the network. I have test a large number of Metasploit exploits and found that this Microsoft solution has bloqued all exploits I could throw at my test machine, machines that I was able to compromise with each before I installed and configured EMET. I do hope MS integrates this in to Service Packs and on the next versions of Windows.

Download at:

EMET 20.0

 

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