Vượt qua xác thực AWS API Gateway chỉ bằng dấu gạch chéo, nhận thưởng 12.000 USD

Cloud & DevOps26 tháng 5, 2026·4 phút đọc

Một lỗi cấu hình trong AWS HTTP API đã cho phép kẻ tấn công truy cập dữ liệu tài khoản ngân hàng và thực hiện chuyển tiền mà không cần token xác thực hợp lệ. Lỗ hổng này nằm ở cách API Gateway xử lý đường dẫn và ngữ cảnh bảo mật, dẫn đến việc bỏ qua kiểm tra quyền truy cập.

Vượt qua xác thực AWS API Gateway chỉ bằng dấu gạch chéo, nhận thưởng 12.000 USD

Trong quá trình kiểm tra bảo mật API di động của một công ty fintech, tôi đã phát hiện một điều kỳ lạ: yêu cầu GET /v1/accounts trả về mã lỗi 401 (Unauthorized), nhưng GET /v1/accounts/ lại trả về mã 200 OK kèm theo toàn bộ dữ liệu tài khoản. Chỉ một ký tự duy nhất là dấu gạch chéo ("/"), nhưng nó đã tạo ra sự khác biệt hoàn toàn về mặt bảo mật.

Minh họa bảo mậtMinh họa bảo mật%20(1).png)

Phân tích kỹ thuật vấn đề

API này chạy trên AWS HTTP API — phiên bản mới hơn và rẻ hơn so với REST API. Nó sử dụng Lambda authorizer để kiểm tra JWT (JSON Web Token) đối với Cognito và trả về một chính sách IAM. Đây là một kiến trúc khá tiêu chuẩn.

Tuy nhiên, vấn đề nằm ở sự không đồng bộ giữa hai lớp quyết định của HTTP API: lớp định tuyến (route) và lớp ủy quyền (authorizer). HTTP API thực hiện khớp đường dẫn theo kiểu "greedy" (tham lam) theo mặc định. Điều này có nghĩa là đường dẫn /v1/accounts/ được coi là khớp với tiền tố /v1/accounts.

Quy trình xử lý diễn ra như sau:

  1. Authorizer chạy trên đường dẫn gốc /v1/accounts/ và trả về kết quả Allow.
  2. Sau đó, tích hợp (integration) được thực thi, nhưng quá trình ánh xạ đường dẫn đã diễn ra một cách "mơ hồ".
  3. Đường dẫn được viết lại (rewrite), dấu gạch chéo bị cắt bỏ, nhưng ngữ cảnh bảo mật (auth context) lại bị đánh rơi trong quá trình này.

Cơ chế bypass hoạt động như thế nào?

Tôi đã sử dụng công cụ ffuf để quét các đường dẫn và nhận thấy các kết quả nhất quán. Bất kỳ đường dẫn nào khớp một phần với tiền tố tuyến đường đều kích hoạt authorizer, sau đó "rơi" vào tích hợp mà không kiểm tra lại xác thực.

Minh họa lỗi bảo mậtMinh họa lỗi bảo mật%20(1).png)

Tuyến đường $default trong HTTP API hoạt động như một bộ lọc bắt-all (catch-all). Công ty fintech đã đặt nó để trả về 404, nhưng họ cũng đã gắn một tích hợp giả (mock integration) cho kiểm tra sức khỏe (health check) tại một thời điểm nào đó. Tích hợp giả này không kiểm tra xác thực.

Khi truy cập /v1/accounts/, nó không trúng vào tích hợp giả mà trúng vào backend thực. API Gateway đã viết lại đường dẫn có dấu gạch chéo, loại bỏ dấu gạch chéo đó và chuyển tiếp tới tích hợp /v1/accounts. Kiểm tra xác thực xảy ra trên đường dẫn gốc, nhưng tích hợp chạy trên đường dẫn đã được viết lại. Quá trình viết lại này đã loại bỏ ngữ cảnh bảo mật.

Tôi đã xác nhận điều này bằng một tiêu đề tùy chỉnh. Authorizer đặt context.authorizer.userId, và tích hợp đọc giá trị này. Khi tôi truy cập /v1/accounts/, tích hợp nhận được userId: undefined. Backend không xác thực userId mà chỉ trả về tất cả các tài khoản cho API key — vốn thậm chí không được yêu cầu ở đây vì xác thực được cho là JWT.

Hậu quả thực tế

Cùng một lỗi bypass này hoạt động trên POST /v1/transfers/. Tôi có thể khởi tạo chuyển tiền dây mà không cần JWT hợp lệ.

Backend kiểm tra xem fromAccount có thuộc về người dùng hay không. Nhưng vì userIdundefined, nó mặc định về một tài khoản hệ thống. Tôi đã dừng lại sau một lần chuyển tiền thử nghiệm 0,01 USD. Giao dịch đã thành công.

Khắc phục và phần thưởng

Tôi đã báo cáo chi tiết vấn đề, bao gồm ảnh chụp màn hình về sự khác biệt giữa 401 và 200, đầu ra của ffuf và hành vi viết lại đường dẫn chính xác. Họ đã khắc phục vào ngày hôm sau.

Các biện pháp khắc phục bao gồm:

  • Chuyển từ HTTP API sang REST API (có khớp đường dẫn nghiêm ngặt hơn).
  • Thêm xác thực userId trong mọi hàm Lambda, không chỉ dựa vào authorizer.

Để công trình này, tôi đã nhận được phần thưởng 12.000 USD và đang có kế hoạch đi du lịch Dubai.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗