“Một dịch vụ nội bộ từ trước đến nay chúng tôi chạy dưới LocalSystem bị đánh dấu trong kiểm toán bảo mật là ‘đặc quyền quá mức’. Phải đổi sang cái gì?” “Dịch vụ không truy cập được thư mục dùng chung nên chúng tôi chạy nó dưới người dùng miền. Khi mật khẩu hết hạn dịch vụ dừng, nên chúng tôi đặt không bao giờ hết hạn và viết mật khẩu dạng văn bản thuần trong runbook.” — Trong các cuộc tư vấn quanh dịch vụ Windows của khách, hai câu này là món quen.
Điểm chung của cả hai hiện trường là tài khoản đăng nhập của dịch vụ bị đóng băng thành “thiết lập tình cờ chạy được”, chứ không phải quyết định thiết kế. Dịch vụ Windows luôn chạy trong ngữ cảnh bảo mật của một tài khoản nào đó, và tài khoản đó quyết định toàn bộ những gì nó làm được ở cục bộ, nó trông như ai từ phía xa của mạng, và ai quản lý mật khẩu. Để mặc định thì một lỗ hổng ở một dịch vụ dẫn thẳng tới chiếm cả máy, và mật khẩu văn bản thuần rải vào runbook cùng tập lệnh.
flowchart TB
accTitle: Ba điều tài khoản đăng nhập quyết định
accDescr: Dịch vụ luôn chạy trong ngữ cảnh bảo mật của một tài khoản nào đó, và tài khoản đó quyết định toàn bộ những gì nó làm được ở cục bộ, nó trông như ai từ phía xa của mạng, và ai quản lý mật khẩu
acct["Tài khoản đăng nhập của dịch vụ"] --> local["Những gì nó làm được ở cục bộ"]
acct --> net["Nó trông như ai từ phía xa của mạng"]
acct --> pwd["Ai quản lý mật khẩu"]
Hình 1: Chọn tài khoản đăng nhập là quyết định thiết kế đồng thời quyết định đặc quyền cục bộ, danh tính mạng và quản lý mật khẩu.
Có hiệu quả sáu lựa chọn — LocalSystem, LocalService, NetworkService, tài khoản ảo (NT SERVICE\
Cách xây dịch vụ chính nó (chọn giữa Task Scheduler và dịch vụ, triển khai bằng .NET Worker Service) được trình bày trong “Cách xây và vận hành dịch vụ Windows”. Bài này tập trung vào “tài khoản đăng nhập”, nơi xảy ra nhiều tai nạn nhất.
1. Kết luận trước
- Khi còn phân vân, tài khoản ảo là ứng viên đầu cho dịch vụ kết thúc trong một máy, và gMSA là ứng viên đầu cho dịch vụ truy cập tài nguyên trong miền bằng danh tính riêng của dịch vụ. Microsoft cũng hướng dẫn dùng tài khoản được quản lý (MSA / tài khoản ảo) bất cứ khi nào có thể.12
- Đừng chọn LocalSystem vì “chạy được”. Token gồm SYSTEM và BUILTIN\Administrators và giữ các đặc quyền mạnh như SeDebugPrivilege, nên bị chiếm là gần như mất hết trên máy đó. Mặc định của
sc.exe createlà LocalSystem chính là ổ tai nạn này.34 - Khác biệt giữa LocalService và NetworkService là danh tính mạng. Đặc quyền cục bộ đều tối thiểu, nhưng với phía xa LocalService trông ẩn danh và NetworkService trông như tài khoản máy tính.5
- **Tài khoản ảo (NT SERVICE\
) là mặc định hiện đại có thể tách danh tính theo từng dịch vụ mà không cần quản lý mật khẩu.** Bạn có thể ghi "NT SERVICE\\tên-dịch-vụ" trực tiếp trên ACL, và tài khoản dịch vụ mặc định của SQL Server cũng là loại này.[^understand-service-accounts][^sql-service-accounts] - Khi LocalSystem, NetworkService hoặc tài khoản ảo đi ra mạng, nó trở thành tài khoản máy tính (DOMAIN\tên-máy$). Cấp PC$ trên ACL thư mục dùng chung hoặc SQL Server thường giúp bạn không cần người dùng miền.36
- Cấu hình dùng người dùng miền cho dịch vụ trở thành nợ cả về vận hành mật khẩu lẫn Kerberoasting. SCM đăng nhập bằng mật khẩu đã lưu, nên hết hạn thành lỗi khởi động, và “không bao giờ hết hạn + ghi chú văn bản thuần” để tránh điều đó trở thành quà cho kẻ tấn công.78
- gMSA để Active Directory sinh và xoay mật khẩu tự động. Điều kiện là miền và khóa gốc KDS, và bạn đặt dịch vụ thành “DOMAIN\tên-tài-khoản$” với ô mật khẩu để trống. Một số ứng dụng không hỗ trợ, nên cần kiểm thử trước.910
- Đổi tài khoản làm đổi giả định của hồ sơ, %TEMP% và DPAPI. Dữ liệu được bảo vệ bằng DPAPI của tài khoản cũ không giải mã được bằng tài khoản mới.
- Kiểm kê trạng thái hiện tại có thể xác nhận từ tài khoản đăng nhập của danh sách dịch vụ và từ sự kiện ID 4624 (loại đăng nhập 5).11
Một câu kết luận của bài này: hãy lấy cấu hình “không đưa mật khẩu do người đặt cho dịch vụ” (tài khoản built-in, tài khoản ảo, gMSA) làm mặc định, và coi người dùng miền là phương án cuối.
2. Bức tranh lớn của các lựa chọn — sáu tài khoản đăng nhập trong một bảng
Một bước ôn lại trước. Khi dịch vụ khởi động, Service Control Manager (SCM) đăng nhập bằng tài khoản đã cấu hình và, nếu thành công, tạo access token rồi gán cho tiến trình dịch vụ. Sau đó, mọi truy cập tài nguyên — tệp, pipe và tương tự — được quyết định bằng cách khớp token này với ACL.7 Vậy chọn tài khoản đăng nhập là thiết kế quyết định nội dung token trao cho tiến trình dịch vụ. Đây là sáu lựa chọn.
flowchart TB
accTitle: SCM làm gì khi dịch vụ khởi động
accDescr: SCM đăng nhập bằng tài khoản đã cấu hình, nếu thành công tạo access token và gán cho tiến trình dịch vụ, sau đó truy cập tài nguyên được quyết định bằng cách khớp token với ACL
scm["SCM"] --> logon["Đăng nhập bằng tài khoản đã cấu hình"]
logon --> token["Tạo access token"]
token --> proc["Gán cho tiến trình dịch vụ"]
proc --> access["Truy cập tệp hoặc pipe"]
access --> check{"ACL có cho phép không?"}
check -->|Có| ok["Truy cập thành công"]
check -->|Không| deny["Truy cập bị từ chối"]
Hình 2: Mọi truy cập tài nguyên của dịch vụ được quyết định bằng cách khớp token SCM tạo lúc khởi động với ACL.
| Tài khoản | Đặc quyền cục bộ | Danh tính mạng | Quản lý mật khẩu | Dùng điển hình |
|---|---|---|---|---|
| LocalSystem | Gần như không giới hạn (SYSTEM+Administrators) | Tài khoản máy tính (PC$) | Không cần (không mật khẩu) | Dịch vụ ngoại lệ chạy như một với OS |
| LocalService | Tối thiểu (cấp Users) | Ẩn danh | Không cần | Xử lý cục bộ không cần danh tính mạng |
| NetworkService | Tối thiểu (cấp Users) | Tài khoản máy tính (PC$) | Không cần | Xử lý đặc quyền thấp khi danh tính cấp máy là đủ |
| Tài khoản ảo NT SERVICE\ |
Tối thiểu + cấp riêng trên ACL | Tài khoản máy tính (PC$) | Không cần (quản lý tự động) | Mặc định cho dịch vụ nghiệp vụ chạy trên một máy chủ |
| Người dùng miền | Chỉ những gì bạn cấp | Chính người dùng đó | Thủ công (hết hạn, rò, xoay đều để cho người) | Phương án cuối cho ứng dụng không hỗ trợ gMSA |
| gMSA | Chỉ những gì bạn cấp | Chính gMSA đó | AD sinh và xoay tự động | Khi môi trường miền cần danh tính riêng của dịch vụ |
LocalSystem, LocalService, NetworkService và tài khoản ảo đều không có khái niệm mật khẩu nào. Chỉ người dùng miền và người dùng cục bộ mới đăng nhập bằng mật khẩu lưu trong SCM (= hết hạn và rò là có thể).73
Dưới đây chúng ta đào từng hàng của bảng này.
3. LocalSystem sai ở đâu
3.1. Còn mạnh hơn cả “Chạy với tư cách quản trị viên”
LocalSystem (tên hiển thị Local System, NT AUTHORITY\SYSTEM) là tài khoản định sẵn SCM dùng, và nó giữ đặc quyền rộng trên máy cục bộ. Token gồm SID của NT AUTHORITY\SYSTEM và BUILTIN\Administrators, và nó truy cập được hầu hết đối tượng trên hệ thống. Hơn nữa, SeDebugPrivilege, có thể gỡ lỗi tiến trình khác, và SeTcbPrivilege, hành động như một phần của OS, được bật mặc định.3
Sức mạnh này đồng nghĩa với mức thiệt hại khi bị chiếm. Nếu dịch vụ chạy dưới LocalSystem có một lỗ hổng thực thi mã tùy ý, kẻ tấn công trong một hơi đến được đọc và sửa tệp của mọi người dùng trên máy đó (SYSTEM có Full Control mặc định trên NTFS5), đọc bộ nhớ tiến trình khác qua SeDebugPrivilege, rồi đánh cắp thông tin xác thực và di chuyển ngang từ đó (điểm xuất phát của Pass-the-Hash và tương tự). Chuỗi đánh cắp thông tin xác thực và di chuyển ngang như đã trình bày trong “NTLM và Kerberos giải thích bằng sơ đồ” và “Hướng dẫn thực hành Windows LAPS”.
flowchart TB
accTitle: Thiệt hại khi dịch vụ LocalSystem bị chiếm
accDescr: Nếu dịch vụ chạy dưới LocalSystem có một lỗ hổng thực thi mã tùy ý, kẻ tấn công đến được đọc và sửa tệp mọi người dùng, đọc bộ nhớ tiến trình khác, rồi đánh cắp thông tin xác thực và di chuyển ngang
vuln["Một lỗ hổng thực thi mã tùy ý"] --> sys["Kẻ tấn công có đặc quyền SYSTEM"]
sys --> files["Đọc và sửa tệp"]
sys --> mem["Đọc bộ nhớ tiến trình khác"]
sys --> cred["Đánh cắp thông tin xác thực"]
cred --> lateral["Di chuyển ngang sang máy khác"]
Hình 3: Một lỗ hổng ở dịch vụ LocalSystem để kẻ tấn công trong một hơi đến được chiếm cả máy và điểm xuất phát di chuyển ngang.
3.2. Vì sao vẫn được chọn
Lý do đơn giản: nó là mặc định, và access-denied không bao giờ xuất hiện. Mặc định khi bạn bỏ obj= trên sc.exe create là LocalSystem,4 và nhiều mã mẫu cũ cùng mẫu cài đặt vẫn giả định LocalSystem. Vì bạn có thể thoát lỗi đặc quyền khi phát triển, cấu trúc sản xuất hàng loạt “chạy được nên để vậy” nằm sẵn. Tài liệu của chính Microsoft cũng nói hầu hết dịch vụ không cần mức đặc quyền cao đến thế, và nếu không cần thì nên cân nhắc LocalService hoặc NetworkService.3
flowchart TB
accTitle: Cấu trúc khiến LocalSystem tiếp tục được chọn
accDescr: Mặc định của sc.exe create là LocalSystem, và mã mẫu cùng mẫu cũ cũng giả định LocalSystem, nên access-denied không xuất hiện khi phát triển và cấu hình chạy được nên để vậy được sản xuất hàng loạt
def["Mặc định của sc.exe create"] --> lsys["Được tạo dưới LocalSystem"]
old["Mẫu và mẫu cũ"] --> lsys
lsys --> noerr["Không access-denied khi phát triển"]
noerr --> asis["Chạy được nên để vậy"]
asis --> mass["Dịch vụ đặc quyền quá mức được sản xuất hàng loạt"]
Hình 4: Mặc định và trải nghiệm phát triển “không access-denied” sản xuất hàng loạt dịch vụ đóng băng dưới LocalSystem.
3.3. Khác TrustedInstaller — LocalSystem cũng không vô hạn
Gọi LocalSystem “tài khoản mạnh nhất của Windows” không chính xác. Windows Resource Protection (WRP) từ Windows Vista chỉ cho TrustedInstaller (dịch vụ Windows Modules Installer) thay đổi tệp hệ thống OS quan trọng, thư mục và khóa registry, và ngay cả SYSTEM hay quản trị viên cũng bị access denied khi ghi lại.12 “Bạn cần quyền từ TrustedInstaller” của Explorer là cơ chế này. Nói ngược lại, LocalSystem với tới gần như mọi thứ ngoài vùng được WRP bảo vệ, và thường không có lý do nào để trao điều đó cho một dịch vụ nghiệp vụ.
flowchart TB
accTitle: Quan hệ giữa vùng được WRP bảo vệ và TrustedInstaller
accDescr: Thay đổi tệp hệ thống quan trọng và khóa registry mà WRP bảo vệ chỉ được phép cho TrustedInstaller, và ngay cả SYSTEM hay quản trị viên cũng bị access denied
ti["TrustedInstaller"] -->|Có thể thay đổi| wrp["Tệp hệ thống được WRP bảo vệ và tương tự"]
sysadm["SYSTEM và quản trị viên"] -->|Access denied| wrp
sysadm -->|Gần như mọi thứ được phép| other["Ngoài vùng được WRP bảo vệ"]
Hình 5: LocalSystem cũng không vô hạn; thay đổi vùng được WRP bảo vệ chỉ được phép cho TrustedInstaller.
3.4. Trường hợp LocalSystem hợp lý
Điều ngoại lệ hợp lý là dịch vụ mà đặc quyền cần thiết vốn đã vượt cấp quản trị viên — làm việc sát với trình điều khiển thiết bị, vận hành nền tảng bảo mật OS, quản lý dịch vụ hoặc phiên khác, và tương tự. Phần mềm như tác nhân sao lưu hoặc EDR thuộc loại này. Ngay cả khi đó, đáng xác nhận rằng có đường mã thật sự dùng đặc quyền đó, và cân nhắc liệu công việc cần đặc quyền có tách được không (cách phân biệt, xem “Khi nào bạn thật sự cần đặc quyền quản trị viên trên Windows?”).
4. LocalService và NetworkService — tài khoản built-in với đặc quyền tối thiểu
LocalService (NT AUTHORITY\LOCAL SERVICE, SID: S-1-5-19) và NetworkService (NT AUTHORITY\NETWORK SERVICE, SID: S-1-5-20) là tài khoản built-in chuẩn bị cho dịch vụ đặc quyền thấp. Cả hai chỉ giữ đặc quyền tối thiểu ở cục bộ, và làm được không nhiều hơn thành viên nhóm Users.51
Khác biệt giữa hai cái là một điểm: chúng trông như ai từ phía xa của mạng.5
- LocalService: Kết nối phía xa bằng thông tin xác thực ẩn danh. Nó không truy cập được tài nguyên đòi hỏi xác thực.
- NetworkService: Trình thông tin xác thực của máy tính cho phía xa (trong môi trường miền, DOMAIN\tên-máy$).
Tách là LocalService nếu “không ra mạng, hoặc nếu ra thì không cần danh tính”, và NetworkService nếu “bạn muốn truy cập tài nguyên trong miền bằng danh tính của máy”.
flowchart TB
accTitle: Khác biệt giữa LocalService và NetworkService
accDescr: Đặc quyền cục bộ đều tối thiểu, nhưng với phía xa LocalService kết nối bằng thông tin xác thực ẩn danh và NetworkService trình thông tin xác thực của máy tính
ls["LocalService"] --> anon["Kết nối bằng thông tin xác thực ẩn danh"]
anon -.-> ng["Tài nguyên đòi hỏi xác thực là không thể"]
ns["NetworkService"] --> comp["Trình thông tin xác thực của máy tính"]
comp -.-> pc["Trong môi trường miền trông như PC$"]
Hình 6: Đặc quyền cục bộ cùng mức tối thiểu, nhưng danh tính nhìn từ phía xa của mạng tách thành ẩn danh hoặc tài khoản máy tính.
Hai cái này, tuy nhiên, có điểm yếu theo góc nhìn hiện đại. Cùng một tài khoản được nhiều dịch vụ dùng chung. Nếu năm dịch vụ chạy dưới LocalService, thì miễn ACL theo tài khoản, năm dịch vụ truy cập được tài nguyên của nhau. SQL Server không hỗ trợ tài khoản Local Service vì cùng lý do: đó là tài khoản dùng chung và không tách được khỏi dịch vụ khác.1
flowchart TB
accTitle: Tài khoản dùng chung không tách được
accDescr: Nếu vài dịch vụ dùng chung cùng LocalService, thì miễn ACL theo tài khoản chúng truy cập được tài nguyên của nhau
sva["Dịch vụ A"] --> acct["Cùng LocalService"]
svb["Dịch vụ B"] --> acct
svc["Dịch vụ C"] --> acct
acct --> mutual["Truy cập được tài nguyên của nhau"]
mutual -.-> reason["Vì ACL theo tài khoản"]
Hình 7: Các dịch vụ dùng chung cùng tài khoản không tách được tài nguyên của nhau bằng ACL.
Giải “vẫn đặc quyền thấp, nhưng tách theo từng dịch vụ” là chủ đề tiếp theo, tài khoản ảo.
5. Tài khoản ảo (NT SERVICE\) — mặc định hiện đại
5.1. Có danh tính theo từng dịch vụ mà không cần mật khẩu
Tài khoản ảo là “tài khoản cục bộ được quản lý” có từ Windows Server 2008 R2 / Windows 7 trở đi. Có ba đặc điểm.6
- Tài khoản được quản lý tự động; không cần tạo cũng không cần đặt mật khẩu
- Tên là
NT SERVICE\<tên-dịch-vụ>, và trở thành danh tính riêng của từng dịch vụ - Trong môi trường miền, nó truy cập mạng bằng thông tin xác thực của tài khoản máy tính (DOMAIN\tên-máy$)
Nói cách khác, nó giữ ưu điểm “không quản lý mật khẩu” của LocalService/NetworkService và bỏ nhược điểm “không tách được vì tài khoản dùng chung”. Đó cũng là lý do cài SQL Server mặc định tài khoản ảo như NT SERVICE\MSSQLSERVER.1
flowchart TB
accTitle: Tài khoản ảo làm tương thích điều gì
accDescr: Tài khoản ảo giữ ưu điểm không-quản-lý-mật-khẩu của LocalService và NetworkService, bỏ nhược điểm không-tách-được-vì-dùng-chung, và có danh tính riêng từng dịch vụ
merit["Ưu điểm (không quản lý mật khẩu)"] -->|Giữ| va["Tài khoản ảo"]
demerit["Nhược điểm (không tách được vì dùng chung)"] -->|Bỏ| va
va --> ident["Danh tính riêng từng dịch vụ"]
va --> auto["Không cần tạo cũng không cần đặt mật khẩu"]
Hình 8: Tài khoản ảo giữ ưu điểm của tài khoản built-in và chỉ bỏ nhược điểm không-tách-được-vì-dùng-chung.
5.2. Có thể ghi “NT SERVICE\tên-dịch-vụ” trực tiếp trên ACL
Tiện ích thực tế là bạn có thể thêm chỉ dịch vụ đó vào ACL theo tên. “Chỉ dịch vụ này được ghi thư mục dữ liệu này” thực hiện được mà không tạo nhóm cũng không quản lý mật khẩu.
# Đổi tài khoản đăng nhập của dịch vụ thành tài khoản ảo
# Giá trị obj= là "NT SERVICE\tên-dịch-vụ". Đừng chỉ định mật khẩu
sc.exe config MyAppService obj= "NT SERVICE\MyAppService"
# Xác nhận cấu hình (kiểm SERVICE_START_NAME)
sc.exe qc MyAppService
# Cấp quyền modify trên thư mục dữ liệu chỉ cho dịch vụ này
icacls "C:\ProgramData\MyApp" /grant "NT SERVICE\MyAppService:(OI)(CI)M"
Trong GUI, ở services.msc mở thuộc tính dịch vụ → tab “Log On” → nhập NT SERVICE\tên-dịch-vụ vào “This account”, và để trống ô mật khẩu (với tài khoản ảo hoặc MSA, không chỉ định mật khẩu là quy cách của SCM). Sau khi đổi, khởi động lại dịch vụ áp dụng.
5.3. Ràng buộc — ngoài máy nó không phải “dịch vụ đó”
Danh tính tài khoản ảo là cục bộ máy và miền không nhận ra. Trên mạng nó sụp thành tài khoản máy tính như mô tả sau, nên phía xa không phân biệt được “là dịch vụ nào”, và bạn cũng không chia cùng danh tính trên nhiều máy chủ.10
flowchart TB
accTitle: Danh tính tài khoản ảo sụp ngoài máy
accDescr: Tài khoản ảo riêng từng dịch vụ trong máy cũng sụp thành tài khoản máy tính trên mạng, và phía xa không phân biệt được là dịch vụ nào
vaa["Tài khoản ảo A"] --> pc["Tài khoản máy tính PC$"]
vab["Tài khoản ảo B"] --> pc
pc --> remote["Danh tính phía xa nhìn thấy"]
remote -.-> nodist["Không phân biệt được là dịch vụ nào"]
Hình 9: Dù có danh tính riêng trong máy, phía xa của mạng mọi dịch vụ đều trông như cùng một PC$.
Khoảnh khắc ràng buộc này — cần danh tính riêng của dịch vụ phía xa mạng, cần cùng danh tính trên nhiều máy chủ — trở thành vấn đề là lúc gMSA (Chương 8) được gọi.
6. Danh tính khi ra mạng — thực hành tài khoản máy tính (PC$)
6.1. “Dịch vụ không truy cập được thư mục dùng chung” là hiểu nhầm
Trên máy đã gia nhập miền, khi dịch vụ chạy dưới LocalSystem, NetworkService hoặc tài khoản ảo truy cập tài nguyên xa, nó xác thực với tư cách tài khoản máy tính (DOMAIN\tên-máy$).36 Nhiều cuộc tư vấn mở đầu “không truy cập được thư mục dùng chung nên chúng tôi biến thành người dùng miền” thực ra được giải bằng điều này. ACL đích chỉ đơn giản không cho phép PC$.
flowchart TB
accTitle: Truy cập xa với tư cách tài khoản máy tính
accDescr: Dịch vụ LocalSystem, NetworkService hoặc tài khoản ảo trên máy đã gia nhập miền xác thực với phía xa với tư cách tài khoản máy tính, và nếu ACL đích cho phép PC$ thì truy cập được
svc["Dịch vụ (LocalSystem, tài khoản ảo và tương tự)"] --> auth["Xác thực với tư cách PC$"]
auth --> acl{"ACL đích có cho phép PC$ không?"}
acl -->|Có| ok["Truy cập thư mục dùng chung hoặc DB thành công"]
acl -->|Không| ng["Truy cập bị từ chối"]
Hình 10: Trong môi trường miền, chỉ cấp PC$ trên ACL đích đã lập truy cập xa mà không cần người dùng miền.
Cấp phía máy chủ tệp giống thao tác ACL thường; chỉ định tên-máy$ làm tên tài khoản (trong hộp chọn đối tượng GUI, đưa “Computers” vào kiểu đối tượng).
# Phía máy chủ tệp: cấp dịch vụ trên APPSV01 quyền modify trên thư mục dùng chung
# Cần cấp cả quyền chia sẻ lẫn quyền NTFS
Grant-SmbShareAccess -Name "AppData" -AccountName "CORP\APPSV01$" -AccessRight Change -Force
icacls "D:\Shares\AppData" /grant "CORP\APPSV01$:(OI)(CI)M"
SQL Server cũng vậy: tạo tài khoản máy tính làm login và chuỗi kết nối đi được với Integrated Security=true mà không mật khẩu.
-- Phía máy chủ DB: cho phép xác thực tích hợp Windows từ dịch vụ trên APPSV01
CREATE LOGIN [CORP\APPSV01$] FROM WINDOWS;
6.2. Biết giới hạn của cách PC$
Cách này có hai giới hạn.
- Độ hạt theo máy. LocalSystem, NetworkService và mọi dịch vụ tài khoản ảo chạy trên cùng máy đều trông như cùng một PC$ từ phía xa. Bạn không “chỉ cho phép dịch vụ này” ở đích, và cũng không kiểm toán được dịch vụ nào đã dùng tài khoản đó.2
- Không dùng được trong môi trường workgroup. Tài khoản máy tính là đối tượng Active Directory, nên máy chưa gia nhập miền không có. Bạn cần thiết kế xử lý rõ ràng thông tin xác thực của tài khoản đích.
Khi muốn vượt giới hạn 1, câu trả lời năm 2026 không phải người dùng miền ở chương sau… mà là bỏ qua vấn đề đó và tiến tới gMSA.
flowchart TB
accTitle: Hai giới hạn của cách PC$
accDescr: Xác thực với tư cách PC$ có độ hạt cấp máy nên không phép cũng không kiểm toán theo dịch vụ được, và trong môi trường workgroup chính tài khoản máy tính không tồn tại nên không dùng được
pcs["Cách PC$"] --> lim1["Giới hạn 1: theo máy"]
pcs --> lim2["Giới hạn 2: không workgroup"]
lim1 -.-> noaudit["Không phép cũng không kiểm toán theo dịch vụ"]
lim2 -.-> nocred["Dùng thông tin xác thực tường minh"]
lim1 --> gmsa["Vượt cái này: gMSA"]
Hình 11: Khi muốn vượt hai giới hạn độ hạt cấp máy và điều kiện miền, bỏ qua người dùng miền và tiến tới gMSA.
7. Vấn đề dùng người dùng miền cho dịch vụ
7.1. Vấn đề cấu trúc của mật khẩu
Nếu bạn gán người dùng miền (hoặc người dùng cục bộ) cho dịch vụ, SCM lưu mật khẩu đó và dùng nó để đăng nhập mỗi lần khởi động. SCM không quản lý hết hạn, nên khi mật khẩu hết hạn đăng nhập thất bại và dịch vụ sẽ không khởi động.7
Từ đó, vòng xoáy tiêu cực thường thấy ngoài thực tế bắt đầu.
- Tai nạn dịch vụ dừng vì hết hạn xảy ra
- Để phòng tái diễn, “mật khẩu không bao giờ hết hạn” được đặt
- Quy trình đổi không bao giờ được lập, và cùng mật khẩu được viết văn bản thuần vào runbook, tập lệnh và Task Scheduler của vài máy chủ
- Dù người nào đó nghỉ, mật khẩu không đổi (nếu đổi, không biết cái gì sẽ dừng)
flowchart TB
accTitle: Vòng xoáy tiêu cực khi vận hành bằng người dùng miền
accDescr: Mật khẩu hết hạn và dịch vụ dừng, không-bao-giờ-hết-hạn được đặt để phòng tái diễn, mật khẩu văn bản thuần lan vào runbook và tập lệnh, và dù người nghỉ cũng không đổi được
expire["1. Hết hạn dừng dịch vụ"] --> forever["2. Không-bao-giờ-hết-hạn được đặt để phòng"]
forever --> spread["3. Mật khẩu văn bản thuần lan"]
spread -.-> where["Runbook, tập lệnh, tác vụ"]
spread --> stuck["4. Dù người nghỉ cũng không đổi được"]
Hình 12: Bắt đầu từ tai nạn hết hạn, không-bao-giờ-hết-hạn và sự lan của mật khẩu văn bản thuần trở thành cố định.
Microsoft cũng chỉ ra rằng cấu hình dùng tài khoản miền cho dịch vụ tốn khá nhiều công vận hành trong quản lý thủ công mật khẩu và SPN, và bảo trì có thể dẫn tới dừng dịch vụ.1
7.2. Kerberoasting — tài khoản dịch vụ bị nhắm
Một tấn công khác riêng với tài khoản dịch vụ người dùng miền là Kerberoasting. Dịch vụ nhận xác thực Kerberos đăng ký SPN (service principal name) trên tài khoản đăng nhập. Mọi người dùng đã xác thực trong miền có thể yêu cầu vé dịch vụ tới tài khoản đã đăng ký SPN, nên kẻ tấn công lấy vé và thử brute-force mật khẩu ngoại tuyến. Mật khẩu 10-đến-16 ký tự do người quyết định sẽ không chịu nổi tấn công này.
flowchart TB
accTitle: Luồng Kerberoasting
accDescr: Vé dịch vụ tới tài khoản dịch vụ đã đăng ký SPN có thể được mọi người dùng đã xác thực yêu cầu, nên kẻ tấn công lấy vé và thử brute-force mật khẩu ngoại tuyến
atk["Người dùng đã xác thực trong miền"] --> req["Yêu cầu vé cho SPN"]
req --> tkt["Lấy vé dịch vụ"]
tkt --> brute["Brute-force ngoại tuyến"]
brute --> weak["Khoảng 10 đến 16 ký tự sẽ bị phá"]
Hình 13: Mọi người dùng đã xác thực có thể yêu cầu vé, và mật khẩu độ dài do người quyết định sẽ không chịu nổi brute-force ngoại tuyến.
Phản ứng hiệu quả là làm mật khẩu mạnh đến mức người không đoán hay phá được. Microsoft cũng liệt kê ép mật khẩu dài, và dùng gMSA mà mật khẩu trở thành giá trị ngẫu nhiên dài do máy sinh.8 Cùng tài liệu cũng nhắc Kerberos armoring (FAST), nhưng FAST bảo vệ dữ liệu tiền xác thực và sức chống giả mạo KDC; nó không ngăn người dùng đã xác thực yêu cầu vé dịch vụ tới SPN, nên không thay thế được độ mạnh mật khẩu của tài khoản dịch vụ. Quan hệ giữa SPN và Kerberos, cùng điều kiện xác thực rơi về NTLM, được vẽ trong “NTLM và Kerberos giải thích bằng sơ đồ”.
7.3. Nếu vẫn dùng người dùng miền
Nếu không còn cách nào khác phải dùng người dùng miền, vì lý do như ứng dụng không hỗ trợ gMSA, hãy coi những điều sau là giảm thiểu tối thiểu.
- Làm mật khẩu 25 ký tự trở lên sinh ngẫu nhiên, và đừng viết nó ở đâu ngoài công cụ quản lý mật khẩu (runbook, tập lệnh, Excel dùng chung)
- Làm tài khoản chuyên cho dịch vụ và tách theo từng dịch vụ (đừng dùng chung với tài khoản người2)
- Từ chối đăng nhập tương tác và Remote Desktop, và chỉ cho phép “Log on as a service”
- Thu nhỏ các nhóm nó thuộc (thêm vào Domain Admins là ngoài bàn)
- Lập quy trình xoay định kỳ và ghi vào sổ cái những chỗ một lần đổi sẽ ảnh hưởng
Làm hết những điều này vẫn kém an toàn và kém dễ hơn di chuyển sang gMSA — đó là chương tiếp theo.
8. gMSA — giao quản lý mật khẩu cho Active Directory
8.1. Cơ chế và hiệu quả
gMSA (group Managed Service Account) là tài khoản miền giao quản lý mật khẩu cho bộ điều khiển miền. Mật khẩu được bộ điều khiển miền tính từ khóa gốc KDS (Key Distribution Service), và chỉ các máy chủ được phép mới lấy được.13
flowchart TB
accTitle: Cách gMSA quản lý mật khẩu
accDescr: Bộ điều khiển miền tính mật khẩu từ khóa gốc KDS, chỉ máy chủ được phép lấy và dùng để chạy dịch vụ, và mật khẩu được xoay tự động mỗi 30 ngày theo mặc định
kds["Khóa gốc KDS"] --> dc["DC tính mật khẩu"]
dc --> host["Máy chủ được phép lấy"]
host --> svc["Dùng để chạy dịch vụ"]
dc -.-> rot["Xoay tự động mỗi 30 ngày theo mặc định"]
Hình 14: Bộ điều khiển miền đảm nhận sinh, phân phối và cập nhật mật khẩu, và con người vận hành mà không cần biết mật khẩu.
Hiệu quả rõ.9
- Mật khẩu 240 byte sinh ngẫu nhiên: brute-force và tấn công từ điển trở nên không thực tế, và sức chống Kerberoasting tăng đáng kể
- Xoay tự động mỗi 30 ngày theo mặc định: người không cần lên kế hoạch đổi, và dịch vụ không cần dừng
- Cùng danh tính có thể dùng chung trên nhiều máy chủ: trang trại máy chủ dưới cân bằng tải xác thực lẫn nhau với tư cách cùng một principal
- Quản lý SPN đơn giản hơn: đăng ký và quản lý SPN cũng có thể ủy quyền và đơn giản hóa
Con người vận hành mà không cần biết mật khẩu — nếu hiểu đây là cơ chế làm cho tài khoản dịch vụ điều mà Windows LAPS làm cho mật khẩu quản trị viên cục bộ, vị trí dễ nắm hơn.
8.2. Điều kiện
gMSA có điều kiện tiên quyết.10
- Môi trường miền Active Directory (không được trong workgroup)
- Mức chức năng miền và rừng Windows Server 2012 trở lên
- Khóa gốc KDS đã được tạo
- Tên gMSA duy nhất trong rừng, không chỉ trong miền
- Khoảng đổi mật khẩu chỉ đặt được lúc tạo
Tạo khóa gốc KDS là việc một lần, nhưng tối đa 10 giờ sau khi tạo bạn không tạo được gMSA, vì chờ sao chép tới mọi bộ điều khiển miền. Đó là thiết bị an toàn để ngăn tai nạn lấy mật khẩu thất bại trước khi sao chép xong.14
flowchart TB
accTitle: Từ tạo khóa gốc KDS đến tạo gMSA
accDescr: Sau khi khóa gốc KDS được tạo bạn chờ sao chép tới mọi bộ điều khiển miền, nên tối đa 10 giờ không tạo được gMSA; sau khi sao chép xong thì tạo được
add["Tạo khóa gốc KDS"] --> wait["Tối đa 10 giờ chờ sao chép"]
wait -.-> why["Thiết bị an toàn để ngăn tai nạn lấy thất bại"]
wait --> done["Sao chép tới mọi DC đã xong"]
done --> ok["Bạn có thể tạo gMSA"]
Hình 15: Thời gian chờ tối đa 10 giờ sau khi tạo khóa gốc là thời gian chờ để ngăn lấy thất bại khi sao chép chưa xong.
# Chạy với tư cách quản trị viên miền, trên bộ điều khiển miền (hoặc trạm làm việc
# quản trị có mô-đun AD PowerShell)
# Xác nhận khóa gốc KDS có tồn tại không, và tạo nếu chưa (một lần mỗi rừng)
Get-KdsRootKey
Add-KdsRootKey -EffectiveImmediately # Thực tế dùng được sau tối đa 10 giờ
8.3. Quy trình từ tạo đến cấu hình
Quy trình bốn giai đoạn: “① tạo nhóm được phép lấy → ② tạo gMSA → ③ cài trên các máy chủ → ④ đặt trên dịch vụ”.10
flowchart TB
accTitle: Bốn giai đoạn đưa gMSA vào
accDescr: Đưa vào theo bốn giai đoạn: tạo nhóm được phép lấy mật khẩu, tạo gMSA, cài trên từng máy chủ, và đặt làm tài khoản đăng nhập của dịch vụ
st1["① Tạo nhóm được phép lấy"] --> st2["② Tạo gMSA"]
st1 -.-> add["Thêm PC$ của các máy chủ"]
st2 --> st3["③ Cài trên từng máy chủ"]
st3 -.-> test["Xác nhận lấy bằng lệnh Test"]
st3 --> st4["④ Đặt trên dịch vụ"]
Hình 16: Từ tạo nhóm đến đặt dịch vụ, đưa gMSA vào đi theo bốn giai đoạn.
# ① Tạo nhóm bảo mật được phép lấy mật khẩu,
# và thêm tài khoản máy tính của các máy chủ sẽ chạy dịch vụ
New-ADGroup -Name "GG-SvcBatchHosts" -GroupScope Global
Add-ADGroupMember -Identity "GG-SvcBatchHosts" -Members "APPSV01$", "APPSV02$"
# Tư cách thành viên nhóm được đánh giá lúc máy tính đăng nhập, nên
# khởi động lại các máy chủ đích sau khi thêm là cách chắc
# ② Tạo gMSA
New-ADServiceAccount -Name "svc-batch" `
-DNSHostName "svc-batch.corp.example.com" `
-PrincipalsAllowedToRetrieveManagedPassword "GG-SvcBatchHosts"
# ③ Trên từng máy chủ sẽ chạy dịch vụ, cài gMSA và xác nhận
Install-ADServiceAccount -Identity "svc-batch"
Test-ADServiceAccount -Identity "svc-batch" # True nghĩa là lấy đang hoạt động
# ④ Đặt làm tài khoản đăng nhập của dịch vụ. Thêm $ vào tên, và đừng chỉ định mật khẩu
sc.exe config MyBatchService obj= "CORP\svc-batch$"
Restart-Service MyBatchService
Khi đặt từ services.msc cũng vậy, tên tài khoản dạng CORP\svc-batch$ — thêm $ ở cuối, và để trống ô mật khẩu. Tài khoản họ MSA không dùng được cho đăng nhập tương tác.1 Sau đó, cấp CORP\svc-batch$ trên ACL thư mục dùng chung hoặc SQL Server thay PC$, và truy cập mạng bằng danh tính riêng của dịch vụ hoàn tất, không mật khẩu.
8.4. Một số ứng dụng không hỗ trợ
Như lưu ý, không phải mọi phần mềm đều chạy được dưới gMSA. Những thứ cấu hình danh tính đăng nhập qua cơ chế chuẩn — dịch vụ Windows, nhóm ứng dụng IIS, tác vụ Task Scheduler — được hỗ trợ rộng, nhưng có ràng buộc như chính failover clustering không hỗ trợ gMSA, và ứng dụng mà phần trong đòi mật khẩu thì không dùng được.10 Microsoft cũng nói thẳng rằng bạn nên xác nhận hành vi dưới gMSA trong môi trường thử trước sản xuất.9
flowchart TB
accTitle: Phân biệt thứ gì hỗ trợ gMSA
accDescr: Ứng dụng cấu hình danh tính đăng nhập qua cơ chế chuẩn hỗ trợ gMSA rộng, nhưng failover clustering và ứng dụng mà phần trong đòi mật khẩu không dùng được, nên xác nhận trong môi trường thử trước sản xuất
app["Ứng dụng đích"] --> how{"Đăng nhập được đặt thế nào?"}
how -->|Cơ chế chuẩn| okapp["gMSA được hỗ trợ"]
okapp -.-> ex1["Dịch vụ, IIS, tác vụ"]
how -->|Đòi mật khẩu| ngapp["gMSA không được"]
ngapp -.-> ex2["Failover clustering"]
okapp --> test["Thử trước sản xuất"]
Hình 17: Ứng dụng cấu hình đăng nhập qua cơ chế chuẩn được hỗ trợ rộng, nhưng một số thiết kế không được hỗ trợ, nên kiểm thử trước sản xuất là không thể thiếu.
Còn các anh em: sMSA (standalone Managed Service Account) cho một máy chủ, và dMSA (delegated Managed Service Account, đưa vào Windows Server 2025, gắn với danh tính thiết bị để chống đánh cắp thông tin xác thực). Với xây mới, lấy gMSA làm nền và cân nhắc theo yêu cầu.6
9. Thiết kế đi kèm — quyền đăng nhập, hồ sơ, DPAPI và kiểm toán
Bốn điều nữa đổi theo tài khoản, cần giữ.
9.1. Quyền “Log on as a service” (SeServiceLogonRight)
Để khởi động với tư cách dịch vụ, tài khoản cần quyền người dùng “Log on as a service”. LocalSystem, LocalService và NetworkService có sẵn, nhưng mọi tài khoản khác (người dùng miền, gMSA và tương tự) cần gán tường minh.15
Nếu đặt từ tab “Log On” của GUI services.msc, snap-in cấp quyền này tự động. Mặt khác, CreateService / ChangeServiceConfig (API mà sc.exe config gọi) không xác minh tài khoản chỉ định có quyền này. Nguyên nhân điển hình của dịch vụ cấu hình bằng tập lệnh dừng lúc khởi động với “dịch vụ không khởi động do lỗi đăng nhập” là đây. Đừng dựa vào tác dụng phụ của công cụ; hãy đưa vào quy trình triển khai, tường minh, việc thêm vào “Log on as a service” trong Local Security Policy (secpol.msc), hoặc cấu hình qua GPO/Intune (trong môi trường cấu hình quyền này bằng Group Policy, cấp cục bộ bị ghi đè khi chính sách áp dụng, nên điều đó cũng cần chú ý). Ngược lại, bước chuẩn cho tài khoản chuyên dịch vụ là đặt “Deny log on locally” cùng lúc.
flowchart TB
accTitle: Khác biệt theo đường cấu hình quyền Log on as a service
accDescr: GUI services.msc cấp quyền tự động, nhưng API mà sc.exe config gọi không xác minh quyền, nên tài khoản không có quyền dừng dịch vụ với lỗi đăng nhập lúc khởi động
gui["Đặt trong services.msc"] --> auto["Quyền được cấp tự động"]
auto --> okgui["Dịch vụ khởi động được"]
cli["Đặt bằng sc.exe config"] --> noval["Quyền không được xác minh"]
noval --> has{"Có quyền không?"}
has -->|Có| okcli["Dịch vụ khởi động được"]
has -->|Không| stop["Dừng vì lỗi đăng nhập"]
stop -.-> fix["Cấp tường minh bằng secpol.msc hoặc GPO"]
Hình 18: GUI cấp quyền tự động, nhưng cấu hình bằng tập lệnh không xác minh, nên bạn cần đưa việc cấp tường minh vào quy trình.
9.2. Hồ sơ, %TEMP% và HKEY_CURRENT_USER đổi
SCM tải hồ sơ người dùng của tài khoản đó khi dịch vụ khởi động.7 Vậy %TEMP%, %APPDATA% và HKEY_CURRENT_USER thật là thứ khác theo từng tài khoản đăng nhập, và khi bạn đổi tài khoản, thiết lập và bộ nhớ đệm lưu trong hồ sơ tài khoản cũ trông như “biến mất”.
Phản ứng thiết kế đơn giản: đặt dữ liệu dịch vụ không dưới hồ sơ mà trên đường tường minh như C:\ProgramData\<tên-ứng-dụng>, và cấp ACL đó cho tài khoản đăng nhập. Như vậy đổi tài khoản không kèm di chuyển dữ liệu.
flowchart TB
accTitle: Phụ thuộc hồ sơ và phản ứng đặt dữ liệu
accDescr: Hồ sơ thật là thứ khác theo từng tài khoản đăng nhập, nên đổi tài khoản làm dữ liệu hồ sơ cũ trông như biến mất, nhưng đặt dữ liệu trên đường tường minh và cấp ACL thì không cần di chuyển
sw["Đổi tài khoản đăng nhập"] --> newprof["Hồ sơ khác được tải"]
newprof --> lost["Dữ liệu cũ trông như biến mất"]
lost -.->|Phản ứng| fix["Đặt dưới ProgramData"]
fix --> acl["Cấp ACL cho tài khoản đăng nhập"]
acl --> nomig["Không di chuyển dù tài khoản đổi"]
Hình 19: Tránh hồ sơ và đặt dữ liệu trên đường tường minh, thì đổi tài khoản không còn kèm di chuyển dữ liệu.
9.3. Dữ liệu được DPAPI bảo vệ gắn với tài khoản
Dễ bỏ sót hơn nữa là DPAPI. Dữ liệu mã hóa bằng DPAPI phạm vi người dùng (CryptProtectData hoặc ProtectedData của .NET) về nguyên tắc chỉ tài khoản đã bảo vệ mới giải mã được. Khoảnh khắc bạn đổi tài khoản, chuỗi kết nối hoặc khóa API đã lưu không đọc được nữa — đó là DPAPI làm đúng việc, nhưng nếu không có trong quy trình di chuyển thì thành sự cố.
flowchart TB
accTitle: Quan hệ giữa dữ liệu được DPAPI bảo vệ và đổi tài khoản
accDescr: Dữ liệu được bảo vệ bằng DPAPI phạm vi người dùng chỉ tài khoản đã bảo vệ mới giải mã được, nên sau khi đổi tài khoản đăng nhập bạn cần nhập lại bí mật
protect["Bảo vệ DPAPI bằng tài khoản cũ"] --> data["Chuỗi kết nối được bảo vệ và tương tự"]
data --> who{"Tài khoản nào đang giải mã?"}
who -->|Cùng tài khoản cũ| okdec["Giải mã được"]
who -->|Tài khoản mới| ngdec["Không giải mã được"]
ngdec --> re["Nhập lại bí mật"]
Hình 20: Dữ liệu được DPAPI bảo vệ gắn với tài khoản đã bảo vệ, và sau khi đổi tài khoản bạn cần nhập lại.
Phản ứng là đưa vào kế hoạch di chuyển quy trình “nhập lại bí mật sau khi đổi tài khoản” (về thiết kế nơi lưu, xem “Lưu bí mật trong ứng dụng Windows”). Cũng vậy, cấu hình có thể kết thúc bằng xác thực tích hợp Windows với tư cách gMSA hoặc PC$ có thể loại trừ việc lưu chính bí mật. Thứ tự đúng là cân nhắc “có thể không lưu không” trước “lưu ở đâu”.
Và nếu dịch vụ muốn xử lý “với đặc quyền của người dùng gọi”, bạn dùng giả danh chứ không làm tài khoản mạnh hơn. Về điều đó, xem “Xử lý token giả danh Windows cho đúng”.
9.4. Kiểm toán — nhìn 4624 loại đăng nhập 5
Khởi động dịch vụ được ghi trong nhật ký sự kiện Security thành sự kiện ID 4624 (An account was successfully logged on) với loại đăng nhập 5 (Service: SCM khởi động một dịch vụ). Trường “Virtual Account” trong sự kiện cho biết đăng nhập có phải bởi MSA / tài khoản ảo không, nên cũng dùng để theo dõi việc dùng tài khoản được quản lý.11
flowchart TB
accTitle: Luồng kiểm toán khởi động dịch vụ
accDescr: SCM khởi động dịch vụ được ghi thành sự kiện ID 4624 loại đăng nhập 5, và trường Virtual Account nhận diện đăng nhập có phải bởi tài khoản được quản lý không
start["SCM khởi động dịch vụ"] --> ev["Ghi sự kiện ID 4624"]
ev --> type5["Loại đăng nhập 5 (Service)"]
type5 --> vafield["Trường Virtual Account"]
vafield --> watch["Theo dõi tài khoản được quản lý"]
Hình 21: Khởi động dịch vụ được ghi thành 4624 loại đăng nhập 5, và bạn còn theo dõi được việc dùng tài khoản được quản lý.
Để kiểm kê trạng thái hiện tại, gom tài khoản đăng nhập của danh sách dịch vụ là cách nhanh.
# Gom dịch vụ nào đang chạy dưới tài khoản nào
Get-CimInstance Win32_Service |
Group-Object StartName |
Sort-Object Count -Descending |
Select-Object Count, Name
# Kiểm kê dịch vụ không chuẩn chạy dưới LocalSystem (phân biệt nội bộ / bên thứ ba theo đường)
Get-CimInstance Win32_Service |
Where-Object { $_.StartName -eq 'LocalSystem' -and $_.PathName -notlike '*\Windows\*' } |
Select-Object Name, DisplayName, PathName
Nếu đầu ra này xếp hàng “dịch vụ nghiệp vụ chạy dưới LocalSystem” và “dịch vụ chạy dưới người dùng miền”, luồng quyết định chương sau được gọi.
10. Luồng quyết định — quyết bằng bốn câu hỏi
Đây là nội dung đến nay, thành quy trình chọn. Trả lời bốn câu hỏi theo thứ tự.
flowchart TB
accTitle: Luồng quyết định tài khoản đăng nhập
accDescr: Quyết tài khoản đăng nhập bằng cách trả lời lần lượt bốn câu hỏi có truy cập mạng không, đã gia nhập miền không, danh tính cấp máy có đủ không, và hỗ trợ gMSA
q1{"Win auth tới đối tác?"} -->|Không| va["Tài khoản ảo"]
va -.-> sys["LocalSystem nếu cần"]
q1 -->|Có| q2{"Đã gia nhập miền?"}
q2 -->|Không| cred["Bảo vệ thông tin xác thực đã lưu"]
q2 -->|Có| q3{"Cấp máy đủ?"}
q3 -->|Có| pcacl["Tài khoản ảo + PC$"]
q3 -->|Không| q4{"Ứng dụng hỗ trợ gMSA?"}
q4 -->|Có| gmsa["gMSA"]
q4 -->|Không| du["Người dùng + giảm thiểu"]
Hình 22: Trả lời bốn câu hỏi theo thứ tự thì lựa chọn nào trong sáu cái bạn nên dùng được quyết.
Câu 1: Dịch vụ đó có truy cập máy khác trên mạng (thư mục dùng chung, DB, API và tương tự) bằng xác thực Windows không?
Nếu không, tài khoản ảo là mặc định. Chỉ khi cần đặc quyền cục bộ đặc biệt, xác nhận nhu cầu đó rồi mới cân nhắc LocalSystem.
Câu 2: (Nếu có truy cập) Máy đã gia nhập miền chưa?
Trong workgroup, cả PC$ lẫn gMSA đều không dùng được. Dùng thiết kế xử lý rõ ràng thông tin xác thực của tài khoản đích (bảo vệ kho bằng DPAPI hoặc tương tự), hoặc cân nhắc gia nhập miền.
Câu 3: (Trong miền) Danh tính cấp máy (PC$) có đủ không?
Nếu đủ, tài khoản ảo (hoặc NetworkService) + cấp PC$ trên ACL đích là xong. Nếu cần danh tính riêng của dịch vụ, hoặc danh tính chung trên nhiều máy chủ, sang câu 4.
Câu 4: Ứng dụng có hỗ trợ gMSA không?
Nếu có (những thứ cấu hình đăng nhập qua cơ chế chuẩn — SCM, nhóm ứng dụng IIS, Task Scheduler — nhìn chung có), gMSA. Đừng quên kiểm hành vi trong môi trường kiểm thử. Nếu không hỗ trợ dù thế nào, dùng người dùng miền chuyên sau khi áp mọi giảm thiểu ở mục 7.3.
Trong bảng như sau.
| Tình huống | Khuyến nghị | Ghi chú |
|---|---|---|
| Chỉ cục bộ, đặc quyền thường | Tài khoản ảo | Cấp ACL cho NT SERVICE\<tên> |
| Chỉ cục bộ, cần đặc quyền vượt quản trị viên | LocalSystem | Kiểm thử nhu cầu đặc quyền trước |
| Xử lý cục bộ không cần danh tính mạng | LocalService | Chấp nhận được khi giữ dịch vụ sẵn như cũ |
| Truy cập tài nguyên trong miền bằng danh tính máy | Tài khoản ảo (hoặc NetworkService) | Cấp PC$ trên ACL đích |
| Truy cập tài nguyên trong miền bằng danh tính riêng dịch vụ | gMSA | Khóa gốc KDS + xác nhận hỗ trợ |
| Cùng danh tính trên nhiều máy chủ (cân bằng tải và tương tự) | gMSA | Không được với tài khoản ảo |
| Ứng dụng không hỗ trợ gMSA + cần danh tính cụ thể | Người dùng miền chuyên | Cần giảm thiểu ở mục 7.3 |
| Workgroup + cần truy cập xa | Bảo vệ và lưu thông tin xác thực tường minh | Cũng cân nhắc xem lại thiết kế |
11. Tóm tắt
- Tài khoản đăng nhập của dịch vụ là quyết định thiết kế đồng thời quyết định đặc quyền cục bộ, danh tính mạng và quản lý mật khẩu. Đừng để mặc định (LocalSystem).
- LocalSystem giữ token SYSTEM+Administrators và đặc quyền mạnh, và thiệt hại khi bị chiếm bị tối đa hóa. Hầu hết dịch vụ nghiệp vụ không cần đặc quyền này.
- LocalService và NetworkService đều đặc quyền thấp; khác biệt là danh tính mạng (ẩn danh, hoặc tài khoản máy tính). Vì tài khoản được vài dịch vụ dùng chung, chúng không tách được.
- Tài khoản ảo (NT SERVICE\
) là mặc định hiện đại tách theo từng dịch vụ mà không cần quản lý mật khẩu. Bạn ghi trực tiếp trên ACL, và cấu hình chỉ là đổi tên tài khoản đăng nhập. - LocalSystem, NetworkService và tài khoản ảo ra mạng với tư cách DOMAIN\PC$ trong môi trường miền. Cấp PC$ trên ACL thư mục dùng chung hoặc SQL Server thường giúp bạn không cần người dùng miền.
- Dùng người dùng miền cho dịch vụ có vấn đề cấu trúc dừng vì hết hạn, lan mật khẩu văn bản thuần, và Kerberoasting. Nếu dùng, cần tài khoản chuyên + mật khẩu ngẫu nhiên dài + hạn chế đăng nhập.
- gMSA là cơ chế AD sinh và xoay mật khẩu tự động; điều kiện là miền, mức chức năng 2012 trở lên, và khóa gốc KDS. Đặt dịch vụ thành “DOMAIN\tên$” với ô mật khẩu để trống.
- Khi đổi tài khoản, đưa quyền “Log on as a service”, chuyển hồ sơ và %TEMP%, và nhập lại dữ liệu được DPAPI bảo vệ vào quy trình di chuyển. Kiểm toán xác nhận bằng sự kiện ID 4624 loại đăng nhập 5.
Lần sau bạn cài dịch vụ, hãy dừng một lúc trên màn hình thiết lập đăng nhập và hỏi lại. Với tư cách ai, và đến đâu, dịch vụ này phải truy cập được? Câu trả lời phải là một hàng nào đó của bảng quyết định bài này.
Bài viết liên quan
- Cách xây và vận hành dịch vụ Windows ── Từ chọn giữa Task Scheduler và dịch vụ đến biến BackgroundService thành dịch vụ Windows
- Khi nào bạn thật sự cần đặc quyền quản trị viên trên Windows? - UAC, vùng được bảo vệ, và cách phân biệt theo thiết kế
- Xử lý token giả danh Windows cho đúng — Mượn đặc quyền theo luồng và hoàn nguyên an toàn
- NTLM và Kerberos giải thích bằng sơ đồ — Vì sao xác thực rơi về NTLM
- Hướng dẫn thực hành Windows LAPS — Ngừng mật khẩu quản trị viên cục bộ dùng chung trên mọi PC
- Lưu bí mật trong ứng dụng Windows - Tránh cấu hình văn bản thuần bằng DPAPI
Lĩnh vực tư vấn liên quan
KomuraSoft LLC đảm nhận thiết kế tài khoản đăng nhập và củng cố đặc quyền tối thiểu cho dịch vụ Windows và ứng dụng thường trú, di chuyển dịch vụ sẵn xây trên giả định LocalSystem sang tài khoản ảo hoặc gMSA, và điều tra sự cố do access denied, DPAPI và hồ sơ sau khi đổi tài khoản. Bắt đầu từ giai đoạn “bị đánh dấu trong kiểm toán nhưng không biết bắt đầu từ đâu” cũng được.
- Phát triển ứng dụng Windows
- Điều tra lỗi và nguyên nhân
- Tư vấn kỹ thuật và đánh giá thiết kế
- Liên hệ với chúng tôi
Liên kết tham khảo
-
Microsoft Learn, Configure Windows service accounts and permissions. Về việc tài khoản dịch vụ mặc định của SQL Server là tài khoản ảo (NT SERVICE\MSSQLSERVER và tương tự), khi chỉ định tài khoản ảo hoặc MSA thì để trống ô mật khẩu, MSA là tên có $ ở cuối và không dùng được cho đăng nhập tương tác, Local Service là tài khoản dùng chung nên không tách được và SQL Server không hỗ trợ, dùng tài khoản miền tốn công quản lý thủ công mật khẩu và SPN và bảo trì có thể dẫn tới dừng dịch vụ, và luôn nên chạy dịch vụ dưới tài khoản đặc quyền tối thiểu. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, Securing on-premises service accounts. Thứ tự ưu tiên trước hết gMSA cho dịch vụ tại chỗ, rồi sMSA nếu không dùng được, rồi tài khoản máy tính, cuối cùng tài khoản người dùng; khi dùng tài khoản máy tính không biết dịch vụ nào đang dùng tài khoản đó và không kiểm toán được lần đổi; và vai trò của tài khoản dịch vụ (nhận diện, xác thực và khởi động dịch vụ). ↩ ↩2 ↩3
-
Microsoft Learn, LocalSystem Account. Về việc LocalSystem giữ đặc quyền rộng trên máy cục bộ và token gồm SID của NT AUTHORITY\SYSTEM và BUILTIN\Administrators, không có mật khẩu, trình thông tin xác thực của máy tính cho máy chủ xa, danh sách đặc quyền gồm SE_DEBUG_NAME và SE_TCB_NAME, và hầu hết dịch vụ không cần mức đặc quyền này nên nên cân nhắc LocalService/NetworkService. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, sc.exe config. Về việc chỉ định tài khoản đăng nhập của dịch vụ bằng tham số obj=, mặc định là LocalSystem, và tham số password= khi dùng tài khoản người dùng khác LocalSystem. ↩ ↩2
-
Microsoft Learn, Local accounts. Về việc SYSTEM (S-1-5-18) có Full Control mặc định trên volume NTFS, NETWORK SERVICE (S-1-5-20) trình thông tin xác thực của máy tính cho máy chủ xa, và LOCAL SERVICE (S-1-5-19) giữ đặc quyền tối thiểu ở cục bộ và trình thông tin xác thực ẩn danh cho mạng. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Service accounts. Về việc tài khoản ảo là tài khoản cục bộ được quản lý tự động không cần quản lý mật khẩu, tên dạng NT SERVICE<SERVICENAME>, trong môi trường miền truy cập mạng bằng thông tin xác thực của tài khoản máy tính (
\ ↩ ↩2 ↩3 ↩4$), và tiêu chí chọn giữa sMSA, gMSA, dMSA và tài khoản ảo. -
Microsoft Learn, Service User Accounts. Về việc dịch vụ chạy trong ngữ cảnh bảo mật của tài khoản người dùng, SCM đăng nhập vào tài khoản lúc khởi động và gắn access token với tiến trình dịch vụ, SCM tải hồ sơ người dùng, và SCM không quản lý hết hạn mật khẩu nên hết hạn làm đăng nhập thất bại và dịch vụ không khởi động. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Protect SMB traffic from interception. Khuyến nghị gồm gMSA như bảo vệ tài khoản dịch vụ (mật khẩu ngẫu nhiên dài do máy sinh làm phá mật khẩu bằng brute-force hoặc tấn công từ điển không thực tế), ép mật khẩu dài, và nhắc Kerberos armoring (FAST). ↩ ↩2
-
Microsoft Learn, Secure group managed service accounts. Về việc mật khẩu gMSA là sinh ngẫu nhiên 240 byte khó brute-force hay tấn công từ điển, OS Windows đổi mật khẩu mỗi 30 ngày nên quản trị viên không cần lên kế hoạch đổi hay dừng dịch vụ, triển khai trang trại máy chủ và quản lý SPN đơn giản hơn, nếu dịch vụ không hỗ trợ gMSA thì dùng sMSA và nếu cũng không được thì tài khoản người dùng chuẩn với quản lý mật khẩu mạnh, và nên xác nhận hành vi dưới gMSA trong môi trường thử trước sản xuất. ↩ ↩2 ↩3
-
Microsoft Learn, Manage group Managed Service Accounts. Điều kiện gMSA (mức chức năng miền/rừng 2012 trở lên, tạo khóa gốc KDS), tên gMSA phải duy nhất trong rừng, khoảng đổi mật khẩu chỉ đặt được lúc tạo, chỉ định nhóm được phép lấy mật khẩu bằng -PrincipalsAllowedToRetrieveManagedPassword của New-ADServiceAccount, quy trình Install-ADServiceAccount/Test-ADServiceAccount, danh tính tài khoản ảo là cục bộ máy và miền không nhận ra, failover cluster không hỗ trợ gMSA, và SCM, nhóm ứng dụng IIS cùng Task Scheduler hỗ trợ cấu hình đăng nhập dưới gMSA. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, 4624(S): An account was successfully logged on. Về việc sự kiện 4624 được ghi trên máy được truy cập khi phiên đăng nhập được tạo, loại đăng nhập 5 nghĩa là dịch vụ (SCM khởi động một dịch vụ), và trường “Virtual Account” nhận diện đăng nhập bởi MSA hoặc tài khoản ảo và dùng để theo dõi tài khoản dịch vụ được quản lý. ↩ ↩2
-
Microsoft Learn, About Windows Resource Protection. Về việc Windows Resource Protection (WRP) ngăn thay thế tệp hệ thống, thư mục và khóa registry quan trọng, quyền đầy đủ với tài nguyên được WRP bảo vệ bị hạn chế cho TrustedInstaller và thay đổi chỉ qua cơ chế thay thế được hỗ trợ qua dịch vụ Windows Modules Installer, và ứng dụng cố đổi tài nguyên được bảo vệ nhận access denied. ↩
-
Microsoft Learn, Group Managed Service Accounts overview. Về việc gMSA là tài khoản miền giao quản lý mật khẩu cho Windows, bộ điều khiển miền tính mật khẩu từ bí mật dùng chung Key Distribution Service (kdssvc.dll) và máy chủ thành viên hỏi bộ điều khiển miền mật khẩu hiện tại và trước đó, và nó cho phép xác thực lẫn nhau với tư cách cùng một principal trong trang trại máy chủ. ↩
-
Microsoft Learn, Create a Key Distribution Service (KDS) root key. Về việc cần khóa gốc để bộ điều khiển miền bắt đầu sinh mật khẩu gMSA, quy trình tạo bằng Add-KdsRootKey -EffectiveImmediately, tối đa 10 giờ sau khi tạo không tạo được gMSA vì chờ sao chép AD hội tụ, và sao chép chưa xong có thể làm lấy mật khẩu thất bại. ↩
-
Microsoft Learn, Policy CSP - UserRights: LogOnAsService. Về việc quyền “Log on as a service” cho principal bảo mật đăng nhập với tư cách dịch vụ, Local System, Local Service và Network Service có sẵn quyền này, dịch vụ chạy dưới tài khoản khác cần được gán quyền này, và đường cấu hình Group Policy. ↩
Bài viết liên quan
Các bài viết gần đây có cùng thẻ để tìm hiểu sâu hơn những chủ đề lân cận.
Bên trong ảo hóa Windows (Phần 2) — Bộ nhớ ngay cả kernel cũng không thấy: VBS, HVCI và Credential Guard
Khi cài sạch trên phần cứng tương thích, VBS được bật mặc định và dùng hypervisor cùng SLAT để tạo cô lập mạnh hơn kernel. Bài viết này g...
Named pipe trong thực tiễn — IPC chuẩn của Windows, từ thiết kế đến bảo mật
Hướng dẫn thực tiễn về named pipe, cơ chế giao tiếp giữa các tiến trình chuẩn của Windows. Bài viết sắp xếp, từ nguồn gốc, việc chọn giữa...
Tắt Windows nhìn từ ứng dụng của bạn — Sống sót đúng với thông báo thoát, khởi động lại và mất điện
Một lần khởi động lại đêm của Windows Update làm hỏng dữ liệu đo — tai nạn kiểu đó có thể ngăn bằng thiết kế. Bài viết này trình bày, từ ...
Bên trong ảo hóa Windows (Phần 3) — Máy ảo khởi động trong vài giây: Vì sao WSL2, Windows Sandbox và container lại nhẹ
Vì sao WSL2 và Windows Sandbox khởi động trong vài giây và cảm giác nhẹ đến vậy? Bài viết này giải thích các cơ chế, từ ảnh cơ sở động và...
Bên trong ảo hóa Windows (Phần 1) — Windows của bạn thực sự chạy ở đâu? Hypervisor và phân vùng
Khi bạn bật Hyper-V, chính Windows máy chủ chạy trên hypervisor như phân vùng gốc. Bài viết này giải thích nền tảng ảo hóa qua vai trò củ...
Chủ đề liên quan
Các trang này đặt chủ đề trong bối cảnh rộng hơn của dịch vụ và quyết định.
Chủ đề kỹ thuật Windows
Cổng vào phát triển Windows, điều tra lỗi và khai thác tài sản hiện có.
Dịch vụ liên quan đến chủ đề này
Bài viết liên quan trực tiếp đến các dịch vụ sau.
Phát triển ứng dụng Windows
Ứng dụng nghiệp vụ, tích hợp thiết bị và công cụ liên lạc, từ yêu cầu đến phát triển.
Câu hỏi thường gặp
Các câu hỏi thường gặp khi tư vấn về chủ đề của bài viết.
- Có nên đổi ngay một dịch vụ từ trước đến nay vẫn chạy dưới LocalSystem không?
- Đổi ngay không phải lúc nào cũng là câu trả lời đúng cho mọi trường hợp. Trước hết hãy xác nhận dịch vụ đó có thật sự cần đặc quyền cục bộ cấp LocalSystem (đặc quyền mạnh hơn quản trị viên) hay không. Nếu chỉ đọc/ghi tệp và giao tiếp mạng, chuyển sang tài khoản ảo (NT SERVICE\tên-dịch-vụ) là ứng viên đầu tiên. Khi di chuyển, xác nhận cấp quyền truy cập các thư mục và khóa registry cần thiết, cách xử lý dữ liệu phụ thuộc hồ sơ hoặc DPAPI, và quyền "Log on as a service" có mặt hay không. Xác nhận khởi động và các chức năng chính trong môi trường kiểm thử, rồi mới chuyển sản xuất.
- Nên chọn tài khoản ảo hay NetworkService?
- Với lựa chọn mới, chúng tôi khuyên tài khoản ảo. Trên mạng cả hai đều hiện là tài khoản máy tính (DOMAIN\tên-máy$), và cả hai đều có đặc quyền cục bộ nhỏ. Tuy nhiên NetworkService được nhiều dịch vụ dùng chung, nên bạn không thể tách bằng ACL "chỉ cho phép dịch vụ này". Tài khoản ảo có danh tính riêng cho từng dịch vụ, và bạn có thể ghi NT SERVICE\tên-dịch-vụ trực tiếp trên ACL. Các sản phẩm Microsoft gần đây như SQL Server cũng mặc định tài khoản ảo.
- Có dùng được gMSA trong môi trường workgroup (không có miền) không?
- Không. gMSA là cơ chế trong đó bộ điều khiển miền Active Directory sinh và quản lý mật khẩu; miền cộng với tạo khóa gốc KDS là điều kiện tiên quyết. Trong môi trường workgroup, nền tảng là hoàn tất xử lý cục bộ bằng tài khoản ảo hoặc LocalService/NetworkService. Nếu cần truy cập máy khác, bạn cần thiết kế khác, ví dụ dùng rõ ràng thông tin xác thực của tài khoản chuẩn bị sẵn ở đích. Truy cập mạng với tư cách tài khoản máy tính (PC$) cũng chỉ đúng trong môi trường miền.
- Sau khi đổi tài khoản đăng nhập của dịch vụ, tôi không đọc được các thiết lập và thông tin xác thực đã lưu. Vì sao?
- Vì mỗi tài khoản đăng nhập gắn với hồ sơ người dùng, %TEMP%, HKEY_CURRENT_USER và khóa DPAPI riêng. Đặc biệt, dữ liệu được bảo vệ bằng DPAPI phạm vi người dùng (CryptProtectData và tương tự) về nguyên tắc chỉ tài khoản đã bảo vệ mới giải mã được. Tệp lưu dưới hồ sơ (AppData và tương tự) cũng là đường khác với tài khoản mới. Trước khi đổi tài khoản, hãy lập quy trình tạo lại dữ liệu được DPAPI bảo vệ (nhập lại khóa API và tương tự) và di chuyển tệp dưới hồ sơ.
- Nếu chỉ muốn dịch vụ truy cập thư mục dùng chung, có cần người dùng miền không?
- Trong nhiều trường hợp, không. Trong môi trường miền, dịch vụ chạy dưới LocalSystem, NetworkService hoặc tài khoản ảo xác thực với phía xa với tư cách tài khoản máy tính (DOMAIN\tên-máy$). Thêm PC$ đó vào quyền chia sẻ và quyền NTFS của thư mục dùng chung thì nó đọc và ghi được. Nếu muốn kiểm soát truy cập bằng danh tính riêng của dịch vụ, hoặc cùng một danh tính trên nhiều máy chủ, hãy cân nhắc gMSA thay vì người dùng miền.