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
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.

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ậ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:
- Authorizer chạy trên đường dẫn gốc
/v1/accounts/và trả về kết quảAllow. - 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ồ".
- Đườ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ậ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ì userId là undefined, 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
userIdtrong 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.
Bài viết liên quan

AI & ML
Alibaba ra mắt Qwen3.7-Max: Mô hình AI tự chủ chạy liên tục 35 giờ, hỗ trợ Claude Code
21 tháng 5, 2026

AI & ML
Nguy cơ bảo mật từ "Vibe-Coding": Hàng nghìn ứng dụng AI để lộ dữ liệu nhạy cảm trên mạng
07 tháng 5, 2026

Phần mềm
Tấn công Cache Poisoning biến các gói npm TanStack thành mối đe dọa nguy hiểm
12 tháng 5, 2026
