Chiếm đoạt DLL (DLL hijacking) xảy ra khi kẻ tấn công chèn mã độc vào một ứng dụng để thao túng cách các thư viện liên kết động (DLL) được nạp. Một trong những vụ tấn công lớn nhất nhắm vào các cơ quan liên bang Hoa Kỳ xâm nhập nhiều cơ quan chính phủ và có khả năng liên quan đến nhóm tấn công từ Nga — đã lợi dụng kỹ thuật chiếm đoạt DLL. Chiếm đoạt DLL khai thác nền tảng Windows và có thể làm tê liệt toàn bộ hệ thống chỉ từ một tệp bị nhiễm. Thực hành mã hóa/viết mã an toàn có thể giúp ngăn chặn chiếm đoạt DLL. Bên cạnh đó, biết cách phát hiện và kiểm thử chiếm đoạt DLL cũng rất quan trọng để ngăn mối đe dọa leo thang. Mạng lưới an ninh vững mạnh và đội ngũ nhân viên được đào tạo bài bản sẽ là hàng rào quan trọng chống lại tội phạm mạng.
Chiếm đoạt DLL là gì?
Khi kẻ tấn công đưa một tệp bị nhiễm lên máy nạn nhân, tệp này sẽ được thực thi khi ứng dụng có lỗ hổng về việc nạp DLL được chạy. Chiếm đoạt DLL là phương thức tấn công chèn một tệp DLL nhiễm mã vào vùng tìm kiếm (search path) của ứng dụng. Người dùng hoặc ứng dụng sau đó cố gắng nạp một tệp từ thư mục đó và vô tình nạp tệp DLL nhiễm thay vì DLL hợp lệ. Tệp nhiễm sẽ thực hiện mã độc khi ứng dụng được khởi chạy. Do nhiều DLL thường được tiền nạp (preloaded) và nhiều ứng dụng tự động nạp DLL khi khởi động, chỉ một tệp DLL bị nhiễm cũng có thể làm toàn bộ máy tính bị xâm phạm, từ đó kẻ tấn công có thể chiếm quyền truy cập.
Thư viện DLL là gì?
DLL chỉ tồn tại trên hệ điều hành Microsoft Windows và chứa các tài nguyên cần thiết để một ứng dụng hoạt động đúng. Rất nhiều chức năng của hệ điều hành Windows được cung cấp bởi các thư viện liên kết động. DLL thường được mở/nạp khi một ứng dụng khởi động; chúng giúp dùng chung chức năng giữa các chương trình và tiết kiệm không gian ổ đĩa. Vì một DLL có thể được nhiều chương trình sử dụng, nên một tấn công chiếm đoạt DLL có thể làm hỏng và xâm phạm đồng thời nhiều chương trình chỉ bằng một tệp nhiễm duy nhất.
Cơ chế hoạt động của chiếm đoạt DLL
Các ứng dụng Windows sử dụng thứ tự tìm kiếm DLL (DLL search order) để nạp thành công các thư viện. Bằng cách đặt một DLL payload (DLL chứa mã độc) vào thư mục của ứng dụng bị nhắm mục tiêu, ứng dụng có thể bị đánh lừa nạp tệp nhiễm thay vì tệp hợp lệ. Thứ tự tìm kiếm DLL của các ứng dụng Microsoft đã được công bố nên có thể bị khai thác. Để chiếm đoạt thành công, kẻ tấn công phải khiến ứng dụng tìm và nạp tệp nhiễm trước tệp DLL hợp pháp, vì ứng dụng sẽ nạp tệp đầu tiên mà nó gặp khi khởi động. Điều này có thể thực hiện bằng các cách sau:
-
Cắm một tệp DLL trojan vào thư mục mà hệ thống sẽ tìm trước thư viện hợp pháp.
-
DLL preloading: đặt một DLL nhiễm có cùng tên với DLL được chỉ định mơ hồ, khiến hệ thống tìm DLL độc hại trước.
-
DLL redirection: chỉnh sửa trực tiếp thứ tự tìm kiếm DLL để ép chương trình nạp DLL độc hại thay vì DLL hợp lệ.
Tệp DLL nhiễm có thể được cài đặt thông qua tấn công chuỗi cung ứng, phishing (lừa đảo qua email) hoặc social engineering. Càng đặt tệp nhiễm ở vị trí có đặc quyền cao trong hệ thống thì kẻ tấn công càng có nhiều quyền truy cập. Nếu không chỉ định đầy đủ đường dẫn của DLL liên quan, ứng dụng Windows sẽ sử dụng cơ chế tìm kiếm mặc định và thư mục từ đó ứng dụng được nạp sẽ là thư mục đầu tiên được tìm kiếm — kẻ tấn công đặt DLL nhiễm vào vị trí này để nó được nạp trước thư mục hệ thống. Đây gọi là chiếm đoạt thứ tự tìm kiếm DLL (DLL search order hijacking). DLL độc hại thường dùng chữ ký số giả mạo giống ứng dụng mục tiêu để tạo vẻ hợp lệ, qua đó né tránh phát hiện và có thể lây lan qua chuỗi cung ứng.
Cách xác định tấn công chiếm đoạt DLL
Một công cụ Windows tên Process Explorer có thể giúp nhận diện nỗ lực chiếm đoạt DLL bằng cách hiển thị theo thời gian thực các tệp/thư viện đang được nạp. Với bộ lọc phù hợp, người dùng có thể phát hiện các DLL không thuộc về hệ thống. Các bước cơ bản:
-
Cài đặt và chạy Process Explorer.
-
Tìm tiến trình/ứng dụng nghi ngờ là mục tiêu của tấn công chiếm đoạt DLL.
-
Nhấn Ctrl + L và áp dụng bộ lọc chỉ hiển thị các tệp có đường dẫn kết thúc bằng
.dll
(thực hiện bằng cách nhấp Add rồi Apply). -
Nhấn Ctrl + L, áp dụng bộ lọc
directory: name not found
bằng cách đặt điều kiện Result: NAME NOT FOUND, rồi Add → Apply để hiện các tệp đang được nạp ngoài thư mục hệ thống. -
Nhấn Ctrl + L để thêm bộ lọc chỉ hiển thị các tệp DLL trong thư mục của ứng dụng bằng điều kiện Path is [địa chỉ đường dẫn], sau đó Add → Apply.
Các mục hiển thị kết quả NAME NOT FOUND thường chỉ ra nỗ lực chiếm đoạt DLL (tức ứng dụng đang cố nạp DLL từ một vị trí mà tệp DLL không tồn tại trong hệ thống chuẩn).
Cách phòng ngừa chiếm đoạt DLL
Phương pháp hiệu quả nhất để ngăn chặn chiếm đoạt DLL bắt đầu từ phía nhà phát triển phần mềm: chỉ rõ đường dẫn tuyệt đối đến tất cả DLL để ngăn Windows sử dụng cơ chế tìm kiếm mặc định. Ngoài ra:
-
Luôn cập nhật phần mềm chống virus/EDR — dù một số nỗ lực chèn DLL có thể qua mặt, AV hiện đại vẫn có thể chặn nhiều cuộc tấn công.
-
Thường xuyên quét và rà soát hạ tầng để phát hiện lỗ hổng.
-
Nhận thức an ninh cho nhân viên: nhiều vụ tấn công DLL khởi nguồn khi nhân viên vô ý mở tệp/mã độc. Đào tạo nhận diện phishing và kỹ thuật social engineering rất quan trọng.
Một số thực hành bảo mật tiêu biểu:
-
Thiết lập và duy trì Chính sách An ninh Thông tin.
-
Chuyển các email nghi ngờ tới bộ phận an ninh trước khi mở hoặc tương tác.
-
Bật xác thực đa yếu tố (MFA) cho các đăng nhập.
-
Triển khai giải pháp quản lý rủi ro với nhà cung cấp (vendor risk management).
Ví dụ thủ thuật triển khai
Kẻ xấu thường tìm các lỗ hổng DLL, ví dụ DLL bị thiếu trong ứng dụng. Thứ tự tìm kiếm DLL truyền thống như sau:
-
Thư mục từ đó ứng dụng được nạp.
-
Thư mục hiện tại.
-
Thư mục hệ thống (System directory).
-
Thư mục Windows.
-
Các thư mục trong biến môi trường PATH.
Kẻ tấn công đặt DLL độc hại vào một trong những vị trí này sao cho nó được tìm trước DLL hợp pháp. Một phương pháp khác là lợi dụng AppInit_DLLs để cho phép DLL tùy chỉnh được nạp ở nhiều nơi:
-
Tạo DLL độc hại.
-
Đặt LoadAppInit_DLLs = TRUE.
-
Trỏ vào DLL độc hại qua AppInit.
-
Chạy tiến trình để chèn DLL.
Trojan DLL cũng có thể được triển khai qua DLL forwarding (chuyển tiếp DLL) — DLL nhiễm đóng vai trung gian:
-
Phân tích DLL gốc và các hàm của nó.
-
Xác định hàm cần bị chặn/sửa đổi.
-
Cài đặt các hàm này trong DLL nhiễm.
-
Forward (chuyển tiếp) các hàm còn lại tới DLL gốc.
-
Đổi tên DLL gốc.
-
Chuyển forward imports sang DLL đã đổi tên.
-
Thay thế DLL gốc bằng DLL nhiễm.
-
Đổi tên DLL nhiễm thành tên DLL gốc.
Ví dụ các mối đe dọa thực tế
Chiếm đoạt DLL tồn tại nhiều năm và vẫn là mối đe dọa với Windows. Một số nhóm/mã độc đã sử dụng thủ thuật này, ví dụ: APT41, FinFisher, Chaes, Astaroth, BOOSTWRITE, BackdoorDipolomacy, HinKit, Crutch, Downdelph, InvisiMole, HTTPBrowser, Ramsey, menuPass, ThreatGroup-3390, Whitefly, RTM, Tonto Team, Melcoz — nhiều trường hợp sử dụng chiếm đoạt thứ tự tìm kiếm DLL để nạp payload độc hại hoặc leo thang đặc quyền.
Giảm thiểu rủi ro (Mitigations)
Các biện pháp giảm thiểu gồm:
-
Audit (kiểm toán): dùng công cụ như PowerUp để phát hiện và sửa lỗi chiếm đoạt thứ tự tìm kiếm DLL.
-
Hạn chế nạp thư viện: không cho phép nạp DLL từ nguồn từ xa; bật chế độ DLL safe search để tăng ràng buộc khi tìm DLL.
-
Ngăn thực thi: áp dụng giải pháp kiểm soát ứng dụng (application control) để nhận diện và chặn phần mềm khả nghi bị thực thi qua chiếm đoạt thứ tự tìm kiếm DLL.
Cách kiểm thử (How to test)
Kiểm thử chiếm đoạt DLL sử dụng các phương pháp phát hiện tương tự, ví dụ dùng Process Explorer để lọc các .exe và .dll hiển thị trạng thái NAME NOT FOUND — đây thường là dấu hiệu chiếm đoạt. Công cụ khác như DLLSpy sử dụng ba phương pháp phát hiện: tĩnh (static), động (dynamic) và đệ quy (recursive).
-
Static testing: xác định tất cả .dll hoặc đường dẫn .dll trong tiến trình khi ứng dụng chạy.
-
Dynamic testing: quét các module để kiểm tra quyền ghi (write permissions) tại vị trí DLL, xem có bị ghi đè hay không.
-
Recursive engine: quét lại các tiến trình DLL đã phân tích trước đó để tìm thêm DLL đã được nạp và kiểm tra lỗ hổng.