Tuesday, October 7, 2014

Post Exploitation, Metasploit and Windows Hashes

What is a Windows hash?

A Windows hash is a non-salted algorithmic encoding of a plaintext password.  Windows has used two different algorithms for hashing to date, the result being an  LAN Manager (LM) hash, or an NT hash.  In a Microsoft Windows network, NT LAN Manager (NTLM) is a suite of protocols used to provide authentication, integrity and confidentiality to users.  NTLM is the successor to LAN Manager (LANMAN), and attempts to provide backwards compatibility with LANMAN.

In the world of cryptography, salting is a known piece of additional random data that is “mixed in” as an additional input to the one way hashing function.   The advantage of salting is that the hashed representation of a password will never be the same for the same plaintext string.   Unfortunately this technique is not used with stored hashes in Windows.

The LANMAN hash is constructed as follows:
  • The plaintext password is padded with NULL characters to a length of fourteen bytes, and converted to all uppercase.
  • The resulting string is split into two seven character strings.  Each string is used as a key to encrypt the constant string value of “KGS!@#$%”. The data encryption standard (DES) algorithm is used for encryption.
  •  The resulting ciphertext is concatenated into a sixteen byte hash value.

The NT hash is constructed by using the MD4 hashing algorithm over the plaintext string.   A plaintext password, used to construct the NT hash, can be up to 256 characters in length with mixed case and special characters.  Unlike the LM hash, special characters, upper and lower case are all preserved with an NT hash.

How is a Windows hash passed across the network?

From a network transmission perspective, there are two different challenge response algorithms in use.   The LANMAN, and NTLMv1 algorithm operates as follows:
1)    Workstation client initiates authentication
2)    Server responds with a random challenge
3)    Client formulates and sends a response to the challenge by:
a)    Padding the LANMAN/NT hash to 21 bytes
b)    Splitting the hash into three seven character pieces
c)    Using each piece as a DES key to encrypt the server challenge.

NTLMv2 challenge/response is significantly more secure, and operates as follows:
1)    Workstation client initiates authentication
2)    Server responds with a random challenge
3)    Client formulates/sends a response by:
a)    Creating an HMAC-MD5 string using the username, domain name, and NT hash as a key.  This result is called the NTLMv2 one way function (OWF)
b)    Combining the HMAC-MD5 string, server challenge, timestamp, and client challenge into a response. 

Obtaining Hashes during a Penetration Test

In a post exploitation scenario, and assuming you have administrative access, it is useful to be able to retrieve the hashed representation of passwords. Windows hashed passwords are stored in the Security Accounts Manager (SAM) registry hive which is a file named “%SystemRoot%\System32\Config\SAM”.   By default, the SAM file is locked on a running system, and inaccessible to all users including administrative users.  If an NT file system recovery was performed in the past, and the Administrator has not removed the backup data, you might be able to find the SAM file in the “%SystemRoot%\repair” directory.

Since you cannot read the file directly on the disk volume, there are a few alternative tricks to get hold of the data.   The local security authentication sub-system process (LSASS.EXE) on a running windows system reads this data and caches it in memory.

Method 1: Meterpreter “hashdump” command 

The hashdump command is an in-memory version of “pwdump”.   Hashdump allocates memory inside the LSASS process, injects assembly code, and executes it using the CreateThread() function.   The injected assembly code is designed to read the hashes out of LSASS memory, and print them out.   No files are written to disk, thus detecting the technique without using memory forensic techniques is difficult.

In January, 2010, HD Moore noted that Anti-Virus, and host intrusion prevention (HIPS) vendors had developed techniques to detect the API calls made by the meterpreter hashdump command, and block the calls.   In the process of detection however, LSASS will often crash leading to system instability.

Method 2: Meterpreter “hashdump” post module

The hashdump post module (post/windows/gather/hashdump.rb) uses a registry based technique to directly access the SYSKEY, and decrypt the raw LANMAN, and NT hashes.      The significant advantage of this technique is that there is no in-memory manipulation of LSASS with its potential for instability.

The caveat is that a SYSTEM token is required to use the technique.  An account in the local administrators group does not have read access to the SAM registry tree that contains the hashes.   If you have exploited a system service, or perhaps something like a DCERPC vulnerability, you are in great shape.   Alternatively you can consider migrating your meterpreter to a service process, or load the incognito module, and impersonate a token.

Method 3: Meterpreter “smart_hashdump” post module

Carlos Perez improved further on the hash extraction techniques in the sense of automating some of the additional steps, and logic required before the actual hashes are extracted.   The “smart_hashdump” post module works as follows:

  • Determine the privilege level, operating system, and test if the target is a domain controller
  •  If you have the right privileges, specifically a SYSTEM token, smart_hashdump will read the hashes from the SAM registry hive.
  • If the system is a Domain Controller, smart_hashdump will always inject assembly code into LSASS to obtain hashes.
  • If the target is a Windows 2008 server, and the process has administrative privileges, smart_hashdump will:
    • Attempt to gain SYSTEM by using “getsystem”.
    • If it fails to get system, smart_hashdump will attempt to automatically migrate to a process that has system privileges.
    • Inject the LSASS process with assembly code to dump the hashes
  • If the target is a Windows 7+ system with UAC disabled and the process has administrative privileges, smart_hashdump will run “getsystem” and use the registry reading method.If the target is a Windows 2000/2003/XP system, “getsystem” will be used followed by the registry reading method.
The take home point with “smart_hashdump” is that it will do the work for you to obtain SYSTEM privilege and prefer reading the SAM registry hive if at all possible.  The downside with this and all methods, is that within the context of a Domain Controller, you are still required to inject assembly code into LSASS in order to obtain hashes.   As pointed out above, this is a dangerous technique and can result in a crash which your client would certainly not appreciate.

Method 4: Extract hashes from Volume Shadow Copies of the file system

In 2011, Tim Tomes, and Mark Baggett were performing research on the topic of hiding malware in Volume Shadow Copies.   As a result of this work, they realized that by creating a volume shadow copy, or using a pre-existing volume shadow copy, the NTDS.DIT, SAM and SYSTEM files could be directly copied from a running system.

In summary, the process involves:
      Creating a volume shadow copy using system tool “vssadmin” or Tim’s visual basic script called “Vssown.vbs”
      Downloading the NTDS.DIT, SAM, and SYSTEM files
      Downloading and compiling tools from http://www.ntdsxtract.com/downloads/ntds_dump_hash.zip
      Using esedbdumphash to extract the database from NTDS.DIT
      Using dsdump.py, or bkhive2, and samdump2 to dump hashes.

The largest single advantage with using an offline method to extract hashes after copying from a volume shadow is the fact that you do not have to inject anything into the LSASS process on a running domain controller.   The disadvantage is that in a larger environment, you are faced with exfiltrating some potentially large files, and downloading them for analysis.  It is possible that network defenders might detect the network activity of a large data transfer, and/or a large file being written to disk on a workstation.

Choosing the right tool for the job

Which method of hash extraction you decide to use depends on the context of your test.  If you are dealing with an individual system that is not a domain controller, then the “smart_hashdump” module is a good solid choice.   If you are working with host based IPS or Anti-Virus that is detecting LSASS injection attempts, you are taking a significant risk when injecting assembly into this process.   In the context of a domain controller, a volume shadow copy extraction is the best approach to ensure stability.   It is apparent that the original LSASS injection process in meterpreter can be risky, and should probably be avoided.
While this article focuses on hashes, it would be remiss not to mention that LSASS also caches some plaintext data for other security service providers.  These include WDigest for HTTP authentication, Kerberos, and Terminal Services.  If you have administrative access on a local system, LSASS plaintext security service provider memory can be accessed using the Mimikatz or Kiwi extensions enabling the extraction of plaintext information to screen.  Kiwi can be thought of as the upgraded (version 2) release of Mimikatz and includes some excellent new functionality.

References




Thursday, January 16, 2014

Sending 802.11 Packets with Scapy


To accompany my recent technical segment on Paul Assadorian's Security Weekly show, here is a functional Python example of sending 802.11 beacons, probe requests, ARP and DNS requests.   Enjoy!



#!/usr/bin/env python

"""
802.11 Scapy Packet Example
Author: Joff Thyer, 2014
"""

# if we set logging to ERROR level, it supresses the warning message
# from Scapy about ipv6 routing
#   WARNING: No route found for IPv6 destination :: (no default route?)
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *


class Scapy80211():

    def  __init__(self,intf='wlan0',ssid='test',\
          source='00:00:de:ad:be:ef',\
          bssid='00:11:22:33:44:55',srcip='10.10.10.10'):

      self.rates = "\x03\x12\x96\x18\x24\x30\x48\x60"

      self.ssid    = ssid
      self.source  = source
      self.srcip   = srcip
      self.bssid   = bssid
      self.intf    = intf
      self.intfmon = intf + 'mon'

      # set Scapy conf.iface
      conf.iface = self.intfmon

      # create monitor interface using iw
      cmd = '/sbin/iw dev %s interface add %s type monitor >/dev/null 2>&1' \
        % (self.intf, self.intfmon)
      try:
        os.system(cmd)
      except:
        raise


    def Beacon(self,count=10,ssid='',dst='ff:ff:ff:ff:ff:ff'):
      if not ssid: ssid=self.ssid
      beacon = Dot11Beacon(cap=0x2104)
      essid  = Dot11Elt(ID='SSID',info=ssid)
      rates  = Dot11Elt(ID='Rates',info=self.rates)
      dsset  = Dot11Elt(ID='DSset',info='\x01')
      tim    = Dot11Elt(ID='TIM',info='\x00\x01\x00\x00')
      pkt = RadioTap()\
        /Dot11(type=0,subtype=8,addr1=dst,addr2=self.source,addr3=self.bssid)\
        /beacon/essid/rates/dsset/tim

      print '[*] 802.11 Beacon: SSID=[%s], count=%d' % (ssid,count)
      try:
        sendp(pkt,iface=self.intfmon,count=count,inter=0.1,verbose=0)
      except:
        raise


    def ProbeReq(self,count=10,ssid='',dst='ff:ff:ff:ff:ff:ff'):
      if not ssid: ssid=self.ssid
      param = Dot11ProbeReq()
      essid = Dot11Elt(ID='SSID',info=ssid)
      rates  = Dot11Elt(ID='Rates',info=self.rates)
      dsset = Dot11Elt(ID='DSset',info='\x01')
      pkt = RadioTap()\
        /Dot11(type=0,subtype=4,addr1=dst,addr2=self.source,addr3=self.bssid)\
        /param/essid/rates/dsset

      print '[*] 802.11 Probe Request: SSID=[%s], count=%d' % (ssid,count)
      try:
        sendp(pkt,count=count,inter=0.1,verbose=0)
      except:
        raise



    def ARP(self,targetip,count=1,toDS=False):
      if not targetip: return

      arp = LLC()/SNAP()/ARP(op='who-has',psrc=self.srcip,pdst=targetip,hwsrc=self.source)
      if toDS:
        pkt = RadioTap()\
                /Dot11(type=2,subtype=32,FCfield='to-DS',\
                addr1=self.bssid,addr2=self.source,addr3='ff:ff:ff:ff:ff:ff')\
                /arp
      else:
        pkt = RadioTap()\
                /Dot11(type=2,subtype=32,\
                addr1='ff:ff:ff:ff:ff:ff',addr2=self.source,addr3=self.bssid)\
                /arp

      print '[*] ARP Req: who-has %s' % (targetip)
      try:
        sendp(pkt,inter=0.1,verbose=0,count=count)
      except:
        raise

      ans = sniff(lfilter = lambda x: x.haslayer(ARP) and x.op == 2,
        store=1,count=1,timeout=1)

      if len(ans) > 0:
        return ans[0][ARP].hwsrc
      else:
        return None


    def DNSQuery(self,query='www.google.com',qtype='A',ns=None,count=1,toDS=False):
      if ns == None: return
      dstmac = self.ARP(ns)

      dns = LLC()/SNAP()/IP(src=self.srcip,dst=ns)/\
        UDP(sport=random.randint(49152,65535),dport=53)/\
        DNS(qd=DNSQR(qname=query,qtype=qtype))

      if toDS:
        pkt = RadioTap()\
                /Dot11(type=2,subtype=32,FCfield='to-DS',\
                addr1=self.bssid,addr2=self.source,addr3=dstmac)/dns
      else:
        pkt = RadioTap()\
                /Dot11(type=2,subtype=32,\
                addr1=dstmac,addr2=self.source,addr3=self.bssid)/dns

      print '[*] DNS query %s (%s) -> %s?' % (query,qtype,ns)
      try:
        sendp(pkt,count=count,verbose=0)
      except:
        raise

# main routine
if __name__ == "__main__":
    print """
[*] 802.11 Scapy Packet Crafting Example
[*] Assumes 'wlan0' is your wireless NIC!
[*] Author: Joff Thyer, 2014
"""
    sdot11 = Scapy80211(intf='wlan0')
    sdot11.Beacon()
    sdot11.ProbeReq()
    sdot11.DNSQuery(ns='10.10.10.2')