內網滲透之Windows認證(二)


title: 內網滲透之Windows認證(二)
categories:

  • 內網滲透
    id: 6
    key: 域滲透基礎
    description: Windows認證協議
    abbrlink: d6b7
    date: 2022-06-26 14:01:22

  • 為什麼有這篇文章呢,因為我們知道平常的Web系統有註冊、登錄是依賴資料庫和後端的加密解密演算法。那麼Windows系統登錄的時候是如何進行身份驗證的呢,是否也有一個類似資料庫的東西,或者就是一個單純的文本呢?
  • 參考–Windows內網協議學習NTLM篇之NTLM基礎介紹
  • Windows也有一個類似於數據的東西,存放在%SystemRoot%\system32\config\sam,裡面存放著用戶的憑證資訊,當然這肯定不是明文,不然Windows這麼寫也太不安全了。這裡的加密演算法不同於常見的MD5,加密後的數據有兩種分別為LM HashNTLM Hash

LM Hash

  • LM Hash全稱LAN Manager Hash,由IBM設計一般用於Windows XPWindows 2000Windows 2003 這一類系統中。加密演算法如下。
  • 密碼長度不能超過14個字元。
  • 密碼轉換為大寫,再轉換成16進位的字元串,沒有28位長度的,在右邊加0。
  • 再將十六進位的字元串分為兩組14位的字元串。
  • 再將這兩組14位的字元串進行十六進位轉二進位,轉換完成後不滿足56位的在左邊加0。
  • 兩部分分別劃分為每組七位,在其末尾加0,再分別轉換為十六進位。
  • 最後將這兩組數據作為DES加密所需的Key,KGS!@#$%作為需加密的字元,將DES加密後的數據依次拼接。
  • 這裡借用zjun的腳本。
import binascii
import codecs
from pyDes import *

def DesEncrypt(str, Key):
    k = des(Key, ECB, pad=None)
    EncryptStr = k.encrypt(str)
    return binascii.b2a_hex(EncryptStr)

def ZeroPadding(str):
    b = []
    l = len(str)
    num = 0
    for n in range(l):
        if (num < 8) and n % 7 == 0:
            b.append(str[n:n + 7] + '0')
            num = num + 1
    return ''.join(b)

if __name__ == "__main__":
    passwd = sys.argv[1]
    print('你的輸入是:', passwd)
    print('轉化為大寫:', passwd.upper())

    # 用戶的密碼轉換為大寫,並轉換為 16 進位字元串
    passwd = codecs.encode(passwd.upper().encode(), 'hex_codec')
    print('轉為 hex:', passwd.decode())

    # 密碼不足 28 位,用 0 在右邊補全
    passwd_len = len(passwd)
    if passwd_len < 28:
        passwd = passwd.decode().ljust(28, '0')
    print('補齊 28 位:', passwd)

    # 28 位的密碼被分成兩個 14 位部分
    PartOne = passwd[0:14]
    PartTwo = passwd[14:]
    print('兩組 14 位的部分:', PartOne, PartTwo)

    # 每部分分別轉換成比特流,並且長度為 56 位,長度不足用 0 在左邊補齊長度
    PartOne = bin(int(PartOne, 16)).lstrip('0b').rjust(56, '0')
    PartTwo = bin(int(PartTwo, 16)).lstrip('0b').rjust(56, '0')
    print('兩組 56 位比特流:', PartOne, PartTwo)

    # 兩組分別再分為 7 位一組末尾加 0,再分別組合成新的字元
    PartOne = ZeroPadding(PartOne)
    PartTwo = ZeroPadding(PartTwo)
    print('兩組再 7 位一組末尾加 0:', PartOne, PartTwo)

    # 兩組數據轉 hex
    PartOne = hex(int(PartOne, 2))[2:]
    PartTwo = hex(int(PartTwo, 2))[2:]
    if '0' == PartTwo:
        PartTwo = "0000000000000000"
    print('兩組轉為 hex:', PartOne, PartTwo)

    # 16 位的二組數據,分別作為 DES key 為"KGS!@#$%"進行加密。
    LMOne = DesEncrypt("KGS!@#$%", binascii.a2b_hex(PartOne)).decode()
    LMTwo = DesEncrypt("KGS!@#$%", binascii.a2b_hex(PartTwo)).decode()
    print('兩組 DES 加密結果:', LMOne, LMTwo)

    # 將二組 DES 加密後的編碼拼接,得到 LM HASH 值。
    LM = LMOne + LMTwo
    print('LM hash:', LM)

image.png

  • 可以看出密碼長度小於7時,後面加密的數據是固定的,均為aad3b435b51404ee,因此其加密是不安全的。

NTML Hash

  • NTML Hash全稱NT LAN Manager , 目前 Windows 基本都使用 NTLM hash ,一個32位長度的字元串。支援Net NTLM認證協議及本地認證過程中的關鍵憑據。加密演算法如下:
  • 密碼轉換為十六進位
  • Unicode編碼
  • MD4加密
  • Python腳本如下:
import hashlib
import binascii
import sys

print(binascii.hexlify(hashlib.new("md4", sys.argv[1].encode("utf-16le")).digest()).decode())

image.png

  • 123456經過加密後則為32ed87bdb5fdc5e9cba88547376818d4

Windows本地認證

  • winlogon.exe -> 接收用戶密碼 -> lsass.exe -> 比對sam表。
  • winlogon就是登陸介面,接受用戶密碼之後會發送明文到lsass.exelsass.exe會存儲一份明文,然後加密明文和sam表的hash做比對,判斷是否可以登陸。
  • Windows Logon Process(即 winlogon.exe),是Windows NT 用戶登陸程式,用於管理用戶登錄和退出。LSASS用於微軟Windows系統的安全機制。它用於本地安全和登陸策略。
  • 這裡注意如果打了修補程式KB2871997,或者機器是win2012之後,則不會保存明文密碼了。

NTLM認證協議

  • 什麼是NTLM認證協議呢?和NTLM Hash又有什麼區別呢?NTLM是一種網路認證協議,它是基於挑戰(Chalenge)/響應(Response)認證機制的一種認證模式。NTLM 網路認證協議是以 NTLM Hash 作為根本憑證進行認證的協議。
  • 在內網滲透中,經常遇到工作組環境,而工作組環境是一個邏輯上的網路環境(工作區),隸屬於工作組的機器之間無法互相建立一個完美的信任機制,只能點對點,是比較落後的認證方式, 沒有信託機構。
  • 假設A主機與B主機屬於同一個工作組環境,A想訪問B主機上的資料,需要將一個存在於B主機上的賬戶憑證發送至B主機,經過認證才能夠訪問B主機上的資源。
  • 早期SMB協議在網路上傳輸明文口令。後來出現LAN Manager Challenge/Response驗證機制,簡稱LM,它是如此簡單以至很容易就被破解,現在又有了NTLM以及Kerberos
  • 認證流程分為三部分,分別是:協商質詢身份驗證

協商

  • 客戶端向伺服器發送協商請求,包含用戶名、密碼、認證協議版本等資訊。

質詢

  • 伺服器接收到客戶端發送到協商資訊,這時伺服器會生成一個隨機數,叫做challenge,這裡的不同的協議隨機數長度不同,NTLM V1是8位,NTLM V2是16位。
  • 伺服器將登陸的用戶對應的NTLM Hash加密challenge,得到Net NTLM Hash,和生成的challenge一起發送給客戶端。

驗證

  • 客戶端收到challenge後,將用戶的hash與challenge進行加密運算得到resposne,將username、response、challenge發送給伺服器,最後伺服器進行校驗返回認證結果。

WireShark

  • 知道了基本原理自己實戰試試