Lỗ hổng Kerberos Bronze Bit (Phần 1)

Mũ Nồi

Member
18/02/2021
4
9 bài viết
Lỗ hổng Kerberos Bronze Bit (Phần 1)
Phần I. Tìm hiểu về giao thức Kerberos

I. Kerberos là gì?

- Giao thức xác thực, sử dụng trên đường truyền không an toàn

- Là giao thức mặc định sử dụng trên HĐH Window, Unix, MacOS

- Được sử dụng trong mô hình Client – Server để đảm bảo xác thực, chống nghe lén hay gửi các gói tin cũ, đảm bảo toàn vẹn dữ liệu

- Xây dựng dựa trên mã khóa đối xứng và cần một bên thứ ba mà cả hai phía tin tưởng

II. Cơ chế hoạt động

1. Hệ thống gồm:

- Người dùng dịch vụ (Client)

- Máy chủ cung cấp khóa – KDC (Key Distribution Center)
  • Máy chủ xác thực – AS (Authentication Server)
  • Máy chủ cấp vé – TGS (Ticket Granting Server)
  • CSDL thông tin của client – server
- Máy chủ cung cấp dịch vụ - AP (Applycation Server)

2. Tổng quan về cách thức hoạt động:

- Client xác thực với AS -> AS check trong CSDL sau đó cấp quyền cho Client đến TGS -> TGS cấp cho client vé để sử dụng dịch vụ trên SS -> Client mang vé đến SS để sử dụng dịch vụ.

- Để dễ hiểu thì có thể hiểu là: Muốn sử dụng dịch vụ thì phải có vé, mà muốn có vé phải đi mua vé ở quầy bán vé, muốn vào được quầy bán vé thì phải qua phòng bảo về để xác thực)

3. Cụ thể cách thức hoạt động:



1.png

Pha 1: kết nối với AS để lấy vé TGT (ticket-granting ticket) để truy nhập TGS

- Client gửi yêu cầu xác thực (AS_REQ) đến AS yêu cầu xác thực
  • Client nhập định danh (ID) và mật khẩu
  • Phần mềm client thực hiện băm 1 chiều trên mật khẩu nhận được và dùng làm khóa bí mật của client
  • Client gửi gói tin (không mã hóa) đến AS để yêu cầu dịch vụ. Trong gói tin chỉ có Client ID, không chứa khóa bí mật hay mật khẩu
- AS nhận được yêu cầu của client thì kiểm tra Client có thuộc DB không. Nếu có thì gửi tới Client AS_REP gồm 2 gói tin:
  • Gói A: “khóa phiên Client/TGS” được mã hóa với private key của Client
  • Gói B: “Ticket Granting Ticket – TGT”, gồm ClientID, IP của Client, thời hạn của vé và “khóa phiên Client/TGS”. TGT được mã hóa bằng private key của TGS
- Khi Client nhận được 2 gói tin trên sẽ giải mã Gói A bằng mật khẩu và thu được “khóa phiên Client/TGS”. Gói B mã hóa với private key của TGS nên không giải mã được. Lúc này Client đã có thể xác thực mình với TGS.

2.png

Pha 2: Client xác thực với TGS

- Client gửi TGS_REQ, gồm 2 gói tin đến TGS để yêu cầu dịch vụ:
  • Gói C: TGT từ gói tin B và định danh của dịch vụ yêu cầu (Service ID)
  • Gói D: Phần xác thực, chứa Client ID và thời điểm yêu cầu (timestamp) được mã hóa bằng “khóa phiên Client/TGS”
- TGS giải mã C bằng private key của mình và thu được “khóa phiên Client/TGS”. Khóa này sau đó được dùng để giải mã D và thu được phần xác thực. Tiếp theo TGS gửi TGS_REP trở lại cho Client gồm 2 gói tin:
  • Gói E: “Vé Client/AP” (gồm ClientID, IP của Client, thời hạn sử dụng và “khóa phiên Client/AP”) và được mã hóa bằng private key của AP
  • Gói F: “Khóa phiên Client/AP” mã hóa bằng “khóa phiên Client/TGS”
- Sau khi nhận được E, F; Client giải mã F để lấy “khóa phiên Client/AP”. Lúc này người dùng đã có đủ thông tin để xác thực với AP.

3.png

Pha 3: Client truy cập và yêu cầu cấp phép sử dụng dịch vụ

- Client kết nối với AP và gửi AP_REQ gồm 2 gói tin:
  • Gói E: Vé thu được từ pha trên
  • Gói G: Phần xác thực mới, gồm ClientID và timestamp, được mã hóa bằng “khóa phiên Client/AP” thu được từ việc giải mã F.
- AP giải mã E bằng private key của mình để lấy “khóa phiên Client/AP”. Khóa này sau đó được dùng để giải mã G. Nhờ đọc được phần xác thực mới, AP gửi AP_REP chứa gói tin H tới người dùng để xác nhận định danh của mình cũng như đồng ý cho sử dụng dịch vụ:
  • Gói H: chứ timestamp trong G cộng thêm 1, mã hóa bằng “khóa phiên Client/AP”
- Client giải mã gói H, xác nhận và kiểm tra thời gian có được cập nhận đúng hay không. Nếu đúng thì người dùng có thể tin tưởng AP và tiến hành gửi request để sử dụng dịch vụ, AP cung cập dịch vụ mà Client yêu cầu.

Phần II. Ủy quyền trong Kerberos
Ví dụ: Khi người dùng xác thực ứng dụng web sau đó ứng dụng web cần truy cập cơ sở dữ liệu dưới quyền của người dùng. Cơ sở dữ liệu sẽ kiểm soát việc liệu một người dùng nhất định có được phép truy cập một bản ghi cụ thể hay không. Khi ứng dụng web cố gắng truy cập bản ghi trong cơ sở dữ liệu nó phải thực hiện ủy quyền của người dùng trong request để cơ sở dữ liệu xác định request đó được cho phép hay từ chối. Điều này gọi là “double-hop” (nhảy đôi).

4.png

Sự cố được khai thác thông qua “ủy quyền trong Kerberos” khi cho phép Service1 mạo danh người dùng và tương tác với Service2 như thể các request đến trực tiếp từ người dùng. Một số kiểu ủy quyền Kerberos trong Active Derectory sẽ đươc nên ở dưới

- Unconstrained Delegation (Ủy quyền không giới hạn)

- Constrained Delegation (Ủy quyền có ràng buộc)
  • Không chuyển đổi giao thức
  • Có chuyển đổi giao thức
- Resource-Based Constrained Delegation (Ủy quyền hạn chế dựa trên nguồn)

5.png

I. Unconstrained Delegation (Ủy quyền không giới hạn)

Lỗ hổng không ảnh hưởng đến cấu hình này, tuy nhiên cần tránh việc ủy quyền không giới hạn. Service1 được ủy quyền không giới hạn với cài đặt “Trust this computer for delegation to any service (Kerberos only)”. Khi người dùng nhận được service ticket cho Service1, KDC sẽ nhúng TGT của người dùng vào service ticket. Khi “Ticket Service” được chuyển đến Service1, Service1 có thể lấy ra TGT. Với TGT của người dùng, Service1 có thể thực hiện việc “Ticket-Granting Service Exchange” và nhận “Ticket service” với tư cách người dùng cho bất kỳ dịch vụ nào. Điều này cho phép hoàn toàn mạo danh người dùng.

II. Constrained Delegation (Ủy quyền hạn chế)

Chỉ định trước các mục tiêu ủy quyền của dịch vụ. Ví dụ: cấu hình Service1 chỉ được phép ủy quyền cho Service2, thay vì mọi dịch vụ trong domain. Khi người dùng nhận được ticket service cho Service1, KDC sẽ không nhúng TGT của người dùng vào service ticket nữa.

1. Ủy quyền hạn chế mà không chuyển đổi giao thức

Người dùng xác thực với Service1 thông qua Kerberos, Service1 cần truy cập đến Service2 dưới quyền của người dùng. Vì service ticket của người dùng dành riêng cho Service1, nếu chuyển tiếp đến Service2 sẽ bị từ chối. Nếu không có TGT của người dùng, Service1 không thể nhận được service ticket tới Service2 từ KDC. Vậy làm thế nào để Service1 xác thực với Service2 với tư cách người dùng?

Sử dụng MS-SFU để giải quyết thông qua giao thức “Service for User to Proxy” (S4U2proxy) (MS-SFU là tiền ích mở rộng của giao thức Kerberos: dịch vụ này cho phép người dùng ủy quyền ràng buộc).

Giao thức S4U2proxy cho phép Service1 lấy service ticket cho Service2 với tư cách người dùng bằng cách gửi cho KDC service ticket mà nhận được từ người dùng, cùng với TGT của riêng Service1. KDC gửi lại bằng “TGS_REP” bao gồm service ticket sử dụng cho Service2 được ủy quyền với tư cách người dùng. Sau khi khi có service ticket, Service1 và Service2 tiến hành việc “Client/Server exchange”. Quá trình trao đổi hoàn tất, Service2 xử lý request từ Service1 như đến từ người dùng.

6.png

Giao thức S4U2proxy cho phép ủy quyền ràng buộc mà không cần chuyển đôi giao thức vì giao thức Kerberos được dùng trong mọi bước. Tất cả các bước được xác thực với nhau thông qua Kerberos và trao đổi ticket

2. Ủy quyền hạn chế có chuyển đổi giao thức

Xảy ra khi người dùng được phép xác thực với Service1 bằng 1 giao thức không phải Kerberos.

Ví dụ: Service1 có thể xác thực người dùng thông qua xác thực NTLMv2. Nếu Service1 sau đó cần xác thực ủy quyền đó cho Service2 sẽ không thực hiện được (vì không có vé).

Trong trường hợp này, Service1 cần chuyển đổi giao thức bằng cách sử dụng giao thức thứ 2 được cung cấp trong MS-SFU là “Service for User to Self” (S4U2self).

Giao thức S4U2self cho phép dịch vụ nhận được một service ticket thay mặt cho bất kỳ người dùng nào. Giao thức này là sự thay đổi khi “Tick-Granting Exchange”. Service1 gửi TGT + timestamp được mã hóa bằng session key của KDC và chỉ định người dùng mà nó muốn có vé. KDC xử lý request, thực hiện xác thực và trả về cho Service1 service ticket, tên người dùng được chỉ định trong trường “cname”.

7.png

Bây giờ Service1 đã có service ticket cho chính nó. Service1 sử dụng vé này trong S4U2proxy Exchange và nhận service ticket tới Service2 thay mặt người dùng

Điều quan trọng cần lưu ý là một dịch vụ có thể yêu cầu service ticket cho bất kỳ người dùng nào thông qua giao thức S4U2self. Dịch vụ không phải đưa ra bằng chứng cho thấy người dùng thực sự xác thực với dịch vụ.

III. Resource-Based Constrained Delegation (RBCD) (ủy quyền dựa trên nguồn)

Xác định danh sách các dịch vụ mà một dịch vụ cụ thể có thể ủy quyền.

Ví dụ: ServiceA được phép ủy quyền xác thực Kerberos cho ServiceB, ServiceC, ServiceD. Danh sách sẽ được cấu hình tại “AllowedToDelegateTo” của ServiceA trong Active Derectory. RBCD có trong Windows Server 2012 trở đi.

IV. Bảo vệ trong ủy quyền hạn chế

Dù phạm vi hẹp hơn ủy quyền không hạn chế nhưng ủy quyền hạn chế vẫn có thể mạo danh người dùng.

- Dịch vụ để ủy quyền có chuyển đổi giao thức thì thuộc tính “TrustedToAuthForDelegation” trong AD sẽ được bật. Điều này tương ứng với tùy chọn “Trust this computer for delegation to specified services only – Use any authentication protocol” (Chỉ tin cậy máy tính này để ủy quyền cho các dịch vụ được chỉ định - Sử dụng bất kỳ giao thức xác thực nào) trong AD GUI

- Dịch vụ để ủy quyền không chuyển đổi giao thức thì thuộc tính “TrustedToAuthForDelegation” trong AD không sử dụng nhưng vẫn có danh sách “AllowedToDelegateTo” được điền. Điều này tương ứng với tùy chọn Trust this computer for delegation to specified services only – Use Kerberos only” (Chỉ tin cậy máy tính này để ủy quyền cho các dịch vụ được chỉ định - Chỉ sử dụng Kerberos) trong AD GUI. Mặc dù bấy kỳ dịch vụ nào cũng có thể tự mình thực hiện S4U2self exchange để lấy service ticket với tư cách là bất kỳ người dùng nào nhưng nếu chuyển đổi giao thức không được phép thì service ticket sẽ có Forwardable flag là 0. Khi đó service ticket chuyển trong S4U2proxy exchange tiếp theo sẽ không thành công.

V. Bảo vệ người dùng và tài khoản nhạy cảm

Người dùng và các tài khoản AD khác có thể cấu hình để không cho phép ủy quyền xác thực:

- Enable “Account is sensitive and cannot be delegated” trong AD cho tài khoản.

8.png

- Theo tài khoản vào nhóm bảo mật trong AD “Protected Users”. Bất kỳ thành viên nào trong nhóm này đều không được ủy quyền xác thực

9.png

=> Giống như “Use kerberos only”, các biện pháp này đảm bảo rằng khi một vé tạo cho những người dùng này thì gia trị Forwardable flag luôn bằng 0. Một dịch vụ có thể có vé của người dùng thông qua giao thức S4U2self nhưng vì vé không chuyển tiếp được nên không sử dụng được trong S4U2proxy để lấy vé cho dịch vụ khác.

Phần III: Tổng quan về ủy quyền

Service1 muốn xác thực với Service2 với tư cách là người dùng nhưng người dùng chưa xác thực với Service1 thông qua Kerberos


Bước 1: Authentication Service Exchange
  • Mã hóa timestamp bằng “long term key” (màu xanh)
  • KDC xác thực timestamp sau đó trả về AS_REP (logon session key (khóa phiên đăng nhập) + TGT)

10.png

Bước 2: S4U2self Exchange
  • Service1 có khóa phiên đăng nhập và TGT.
  • Service1 mã hóa timestamp khác bằng khóa phiên đăng nhập
  • Service1 gửi timestamp đã mã hóa + TGT + tên người
  • KDC xác nhận TGT và timestamp. Chuẩn bị một service ticket cho Service1. Ban đầu, Forwardable flag = 1
  • KDC sẽ kiểm tra xem Service1 có đặt thuộc tính "TrustedToAuthForDelegation" hay không; người dùng mục tiêu có được bảo vệ khỏi sự ủy quyền hay không; có là thành viên của nhóm "Protected Users" hoặc được định cấu hình “Account is sensitive and cannot be delegated” hay không? Nếu không thì Forwardable flag = 0.
  • KDC trả lại phiếu dịch vụ mới cho Service1. Service1 hiện có một vé hợp lệ với tư cách là người dùng, có thể chuyển tiếp hoặc không thể chuyển tiếp.

11.png

Bước 3: S4U2proxy Exchange

  • Service 1 gửi service ticket cho KDC để chứng minh người dùng đã xác thực với Service1 và yêu cầu một service ticket mới cho Service2 với tư cách người dùng
  • KDC xác thực mối quan hệ ủy quyền giữa Service1 và Service2
+ Service2 có trong danh sách “AllowedToDelegateTo” của Service1 không => ủy quyền bị ràng buộc​
+ Nếu không KDC kiểm tra Service1 có nằm trong danh sách “PrincipalsAllowedToDelegateToAccount” của Service2 không => ủy quyền dựa trên tài nguyên (RBCD)​
+ Cả 2 lần kiểm tra không thành công => trao đổi không thành công​
  • Sau khi xác nhận Service1 được phép ủy quyền xác thực cho Service2, KDC giải mã service ticket và kiểm tra Forwardable flag
+ Nếu Forwardable flag = 0 => KDC kiểm tra bổ sung và trao đổi không thành công do lỗi​

+ Nếu Forwardable flag = 1 => KDC trả về service ticket hợp lệ cho Service2 với tư cách là người dùng​
12.png
Phần IV: Lỗ hổng
Để ý kỹ cấu trúc của TGS_REP do KDC trả về sau S42Uself exchange. Giả sử Service1 không phải “TrustedToAuthForDelegation” hoặc người dùng chỉ định được bảo vệ khỏi ủy quyền thì Forwardable flag = 0. Điều này có nghĩ là session ticket sẽ bị từ chối nếu sử dụng trong S42Uproxy exchange

14.png

Để ý kỹ sẽ thấy Forwardable flag được mã hóa bằng “long-term key” của Service1. Và Forwardabe cũng không có trong PAC.

=> Service1 có thể dùng “long-term key” của mình giải mã (gói tin màu xanh), đặt lại giá trị của Forwardable flag = 1 rồi mã hóa lại service ticket. Do không có trong PAC nên KDC không thể phát hiện rằng giá trị Forwardable flag đã bị giả mạo.
Vậy đã có thể chuyển đổi một service ticket không thể chuyển tiếp thành một service ticket có thể chuyển tiếp. Service ticket này có thể sử dụng trong S4U2prox exchange, cho phép Service1 ủy quyền xác thực cho Service2 với tư cách là bất kỳ người dùng nào.

Blog: MoonLuna
 
Chỉnh sửa lần cuối bởi người điều hành:
Thẻ
bronze bit kerberos bronze bit
Bên trên