What is information disclosure?

Information disclosure, hay còn gọi là lộ lọt thông tin, là lỗ hổng xảy ra khi ứng dụng web vô tình tiết lộ thông tin nhạy cảm cho người dùng. Tùy thuộc vào ngữ cảnh, trang web có thể rò rỉ tất cả các loại thông tin cho kẻ tấn công tiềm năng.

Các ví dụ:

Example

Một số ví dụ cơ bản về information disclosure như sau:

  • Tiết lộ tên các thư mục ẩn, cấu trúc và nội dung của chúng thông qua file robots.txt hoặc directory listing
  • Cung cấp quyền truy cập vào các file source code thông qua các bản backup tạm thời
  • Đề cập rõ ràng đến tên bảng hoặc cột cơ sở dữ liệu trong thông báo lỗi
  • Vô tình tiết lộ thông tin cực kỳ nhạy cảm, chẳng hạn như chi tiết thẻ tín dụng
  • Hard-code các API key, địa chỉ IP, thông tin đăng nhập cơ sở dữ liệu, v.v. trong source code
  • Gợi ý về sự tồn tại hoặc không tồn tại của tài nguyên, username, v.v. thông qua những khác biệt tinh tế trong hành vi ứng dụng

Files for web crawlers

Các file chẳng hạn như /robots.txt/sitemap.xml có thể chứa thông tin nhạy cảm:

Summary

Nhiều trang web cung cấp các file /robots.txt/sitemap.xml để giúp web crawler điều hướng trang web của họ. Trong số các thông tin khác, những file này thường liệt kê các thư mục cụ thể mà crawler nên bỏ qua, ví dụ như các thư mục có thể chứa thông tin nhạy cảm.

Directory Listing

Nếu web server được cấu hình để liệt kê nội dung của các thư mục thì chúng ta có thể dùng nó để xác định đường dẫn của các resource và thậm chí là truy cập vào các file ẩn mà không cần thực hiện directory brute-forcing:

Summary

Web server có thể được cấu hình để tự động liệt kê nội dung của các thư mục không có trang index. Điều này có thể hỗ trợ kẻ tấn công bằng cách cho phép họ nhanh chóng xác định các tài nguyên tại một đường dẫn nhất định và tiến hành phân tích và tấn công trực tiếp các tài nguyên đó. Điều này đặc biệt tăng nguy cơ lộ lọt các file nhạy cảm trong thư mục không được thiết kế để người dùng truy cập, chẳng hạn như file tạm thời và crash dump.

Đây không phải là bug do nó chỉ giúp chúng ta tìm được đường dẫn của các resource chứ không hẳn là cho phép chúng ta truy cập vào tất cả các resource:

Summary

Bản thân directory listing không nhất thiết là lỗ hổng bảo mật. Tuy nhiên, nếu trang web cũng không triển khai kiểm soát truy cập phù hợp thì việc rò rỉ sự tồn tại và vị trí của các tài nguyên nhạy cảm theo cách này rõ ràng là một vấn đề.

Developer comments

Comment của developer cũng có thể chứa những thông tin nhạy cảm:

Summary

Trong quá trình phát triển, các comment HTML in-line đôi khi được thêm vào markup. Thỉnh thoảng, những comment này chứa thông tin hữu ích cho kẻ tấn công. Ví dụ, chúng có thể gợi ý về sự tồn tại của các thư mục ẩn hoặc cung cấp manh mối về logic ứng dụng.

Error Message

Error message có thể chứa thông tin về kiểu dữ liệu:

Summary

Nội dung của thông báo lỗi có thể tiết lộ thông tin về loại dữ liệu đầu vào mong đợi từ một tham số nhất định. Điều này có thể giúp chúng ta thu hẹp phạm vi tấn công bằng cách xác định các tham số có thể khai thác.

Thông tin về công nghệ cũng như phiên bản của các công nghệ đó có thể giúp chúng ta sử dụng các lỗ hổng đã biết để khai thác:

Summary

Thông báo lỗi chi tiết cũng có thể cung cấp thông tin về các công nghệ khác nhau được trang web sử dụng. Ví dụ, chúng có thể nêu rõ tên của template engine, loại cơ sở dữ liệu hoặc server mà trang web đang sử dụng, cùng với số phiên bản. Thông tin này có thể hữu ích vì chúng ta có thể dễ dàng tìm kiếm bất kỳ exploit đã được ghi lại nào có thể tồn tại cho phiên bản này.

Trong trường hợp ứng dụng sử dụng open-source framework thì chúng ta có thể tìm hiểu mã nguồn nhằm xây dựng exploit:

Summary

Chúng ta cũng có thể phát hiện ra rằng trang web đang sử dụng một loại open-source framework nào đó. Trong trường hợp này, chúng ta có thể nghiên cứu mã nguồn công khai, đây là tài nguyên vô giá để xây dựng exploit của riêng mình.

Lab: Information Disclosure in Error Messages

Gửi request sau:

GET /product?productId=a HTTP/2
Host: 0a2d007c040aed55804b1c9e00490026.web-security-academy.net

Response cho biết rằng server sử dụng Apache Struts 2 2.3.31:

HTTP/2 500 Internal Server Error
Content-Length: 1674
 
Internal Server Error: java.lang.NumberFormatException: For input string: "a"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
	at java.base/java.lang.Integer.parseInt(Integer.java:661)
	at java.base/java.lang.Integer.parseInt(Integer.java:777)
	at lab.i.h.y.n.D(Unknown Source)
	at lab.h.o.b.d.u(Unknown Source)
	at lab.h.o.e.h.z.c(Unknown Source)
	at lab.h.o.e.c.lambda$handleSubRequest$0(Unknown Source)
	at f.x.f.x.lambda$null$3(Unknown Source)
	at f.x.f.x.Y(Unknown Source)
	at f.x.f.x.lambda$uncheckedFunction$4(Unknown Source)
	at java.base/java.util.Optional.map(Optional.java:260)
	at lab.h.o.e.c.F(Unknown Source)
	at lab.server.l.z.z.s(Unknown Source)
	at lab.h.o.k.F(Unknown Source)
	at lab.h.o.k.s(Unknown Source)
	at lab.server.l.z.v.j.s(Unknown Source)
	at lab.server.l.z.v.a.lambda$handle$0(Unknown Source)
	at lab.i.m.r.x.s(Unknown Source)
	at lab.server.l.z.v.a.Y(Unknown Source)
	at lab.server.l.z.n.m(Unknown Source)
	at f.x.f.x.lambda$null$3(Unknown Source)
	at f.x.f.x.Y(Unknown Source)
	at f.x.f.x.lambda$uncheckedFunction$4(Unknown Source)
	at lab.server.ph.p(Unknown Source)
	at lab.server.l.z.n.z(Unknown Source)
	at lab.server.l.b.c.W(Unknown Source)
	at lab.server.l.u.r(Unknown Source)
	at lab.server.l.s.r(Unknown Source)
	at lab.server.g.K(Unknown Source)
	at lab.server.g.j(Unknown Source)
	at lab.z.q.lambda$consume$0(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)
 
Apache Struts 2 2.3.31

Debug data

Dữ liệu debug đôi khi có thể chứa những thông tin nhạy cảm:

Summary

Thông báo debug đôi khi có thể chứa thông tin quan trọng để phát triển cuộc tấn công, bao gồm:

  • Giá trị của các biến session quan trọng có thể được thao tác thông qua input của người dùng
  • Hostname và thông tin đăng nhập cho các component back-end
  • Tên file và thư mục trên server
  • Khóa được sử dụng để mã hóa dữ liệu truyền qua client

Dữ liệu này đôi khi có thể được lưu trong một file riêng biệt mà nếu attacker truy cập được thì có thể tìm hiểu về cách thức hoạt động của ứng dụng:

Summary

Thông tin debug đôi khi có thể được ghi vào một file riêng biệt. Nếu kẻ tấn công có thể truy cập vào file này, nó có thể phục vụ như một tài liệu tham khảo hữu ích để hiểu trạng thái runtime của ứng dụng.

Lab: Information Disclosure on Debug Page

Tìm thấy đoạn comment sau ở trong trang /:

<!-- <a href=/cgi-bin/phpinfo.php>Debug</a> -->

Truy cập vào và thấy đây là trang thông tin của PHP:

Tìm được secret key ở phần Environment:

Source code disclosure via backup files

Truy cập vào source code có thể giúp attacker hiểu hơn về ứng dụng nhằm xây dựng exploit có mức độ nghiêm trọng cao. Ngoài ra, nó còn có thể tiết lộ các dữ liệu nhạy cảm được hard-code:

Summary

Việc có quyền truy cập source code khiến kẻ tấn công dễ dàng hiểu hành vi của ứng dụng và xây dựng các cuộc tấn công nghiêm trọng hơn. Dữ liệu nhạy cảm đôi khi thậm chí được hard-code trong source code. Các ví dụ điển hình bao gồm API key và thông tin đăng nhập để truy cập các component back-end.

Cách đọc source code thông qua các backup file:

Summary

Khi server xử lý các file có extension cụ thể như .php, nó thường sẽ thực thi code thay vì chỉ gửi nó đến client dưới dạng text. Tuy nhiên, trong một số trường hợp, chúng ta có thể lừa trang web trả về nội dung của file. Ví dụ, các text editor thường tạo ra các backup file tạm thời trong khi file gốc đang được chỉnh sửa. Những file tạm thời này thường được biểu thị theo cách nào đó, chẳng hạn như thêm dấu ngã (~) vào tên file hoặc thêm extension khác. Yêu cầu một code file bằng cách sử dụng backup file extension đôi khi có thể cho phép chúng ta đọc nội dung của file trong response.

Việc đọc được source code có thể dẫn đến lỗ hổng Insecure Deserialization:

Summary

Khi kẻ tấn công có quyền truy cập vào source code, đây có thể là một bước lớn hướng tới việc có thể xác định và khai thác các lỗ hổng bổ sung mà nếu không thì hầu như không thể phát hiện. Một ví dụ như vậy là insecure deserialization.

Lab: Source Code Disclosure via Backup Files

Nội dung của /robots.txt để tìm thư mục ẩn1:

User-agent: *
Disallow: /backup

Truy cập vào /backup thì thấy web server liệt kê thư mục như đã đề cập ở Directory Listing:

Tìm thấy password của database trong dòng code sau:

 ConnectionBuilder connectionBuilder = ConnectionBuilder.from(
		"org.postgresql.Driver",
		"postgresql",
		"localhost",
		5432,
		"postgres",
		"postgres",
		"j1h7pr0sb5hw5xzz14e8s8sqm76m9hd9"
).withAutoCommit();

Information disclosure due to insecure configuration

Việc sử dụng các thư viện thứ 3 mà không hiểu rõ các tùy chọn và cấu hình sai cũng có thể gây ra lộ lọt thông tin:

Summary

Các trang web đôi khi dễ bị tấn công do cấu hình không đúng. Điều này đặc biệt phổ biến do việc sử dụng rộng rãi các công nghệ của bên thứ ba, mà lượng lớn các tùy chọn cấu hình của chúng không nhất thiết được những người triển khai hiểu rõ.

Ví dụ:

Example

Ví dụ, HTTP method TRACE được thiết kế cho mục đích chẩn đoán. Nếu được bật, web server sẽ phản hồi các request sử dụng method TRACE bằng cách echo lại trong response chính xác request đã nhận được. Hành vi này thường vô hại, nhưng đôi khi dẫn đến lộ lọt thông tin, chẳng hạn như tên của các internal authentication header có thể được reverse proxy thêm vào request.

Lab: Authentication Bypass via Information Disclosure

Khi truy cập trang /admin thì nhận được thông báo lỗi như sau:

Admin interface only available to local users

Sử dụng request có method là TRACE:

TRACE /admin HTTP/2
Host: 0a8100e6047fdb1881486b15009a0071.web-security-academy.net
Cookie: session=2DYbY8WivseEjKMS80TzuuqSUG7yt4TR
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0

Response có chứa một internal header:

TRACE /admin HTTP/1.1
Host: localhost
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0
accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
accept-language: en-US,en;q=0.8,vi-VN;q=0.5,vi;q=0.3
accept-encoding: gzip, deflate, br
dnt: 1
upgrade-insecure-requests: 1
sec-fetch-dest: document
sec-fetch-mode: navigate
sec-fetch-site: same-origin
sec-fetch-user: ?1
priority: u=0, i
te: trailers
cookie: session=2DYbY8WivseEjKMS80TzuuqSUG7yt4TR
Content-Length: 0
X-Custom-IP-Authorization: 58.186.47.102

Kiểm tra thì thấy đây chính là IP của chúng ta: IP Address Lookup - Check Location of Your Public IP. Thử thay giá trị này thành 127.0.0.1 thì truy cập được trang /admin.

Version control history

Nếu trang web để lộ thư mục .git thì chúng ta có thể dùng nó để đọc các đoạn diff của source code nhằm tìm ra các thông tin nhạy cảm:

Summary

Có nhiều phương pháp khác nhau để tải về toàn bộ thư mục .git. Sau đó chúng ta có thể mở nó bằng cách cài đặt Git local để truy cập vào lịch sử version control của trang web. Điều này có thể bao gồm các log chứa các thay đổi đã commit và thông tin thú vị khác. Điều này có thể không cung cấp quyền truy cập vào toàn bộ source code, nhưng việc so sánh diff sẽ cho phép chúng ta đọc các đoạn code nhỏ. Như với bất kỳ source code nào, chúng ta cũng có thể tìm thấy dữ liệu nhạy cảm được hard-code trong một số dòng đã thay đổi.

Lab: Information Disclosure in Version Control History

Truy cập .git thì thấy cây thư mục như sau:

Sử dụng tool git-dumper để tải về thư mục .git.

Cấu trúc thư mục:

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           4/22/2025  9:44 PM                .git
-a---           4/22/2025  9:42 PM             88 admin_panel.php
-a---           4/22/2025  9:44 PM             37 admin.conf

Sử dụng lệnh git log thì thấy có 2 commit:

> git log
commit df2d2da9d64d65b73580870e2fb3b4089f5e53ba (HEAD -> master)
Author: Carlos Montoya <carlos@carlos-montoya.net>
Date:   Tue Jun 23 14:05:07 2020 +0000
 
    Remove admin password from config
 
commit f06fbbfeb511afea2f5e0c5046b31a2de3bc5de1
Author: Carlos Montoya <carlos@carlos-montoya.net>
Date:   Mon Jun 22 16:23:42 2020 +0000
 
    Add skeleton admin panel

Checkout đến commit f06fbbfeb511afea2f5e0c5046b31a2de3bc5de1 và xem file admin.conf thì thấy có password:

> cat admin.conf
ADMIN_PASSWORD=zh8wbu8ke4cdcvnk3e29

Đăng nhập bằng administrator:zh8wbu8ke4cdcvnk3e29 và xóa user carlos để hoàn thành lab.

Resources

Footnotes

  1. xem thêm File Dành Cho Web Crawler