Mini-challenge: Phân tích Client Bundle tìm Lỗ hổng Logic
Thử thách độc lập: Sử dụng script Python và công cụ phân tích AST để trích xuất API endpoint ẩn từ file JavaScript bundle và khai thác lỗ hổng BOLA.
TL;DR: Thử thách này đặt bạn vào vai trò của một thợ săn bug độc lập đang đánh giá ứng dụng quản lý doanh nghiệp. Giao diện người dùng thông thường chỉ cho phép bạn xem thông tin tài khoản cá nhân. Bằng cách tải về và giải mã file JavaScript bundle app.min.js, bạn cần tìm kiếm các định nghĩa API route không được hiển thị trên menu, phát hiện một endpoint quản trị bí mật bị bỏ quên và gửi request hợp lệ để trích xuất cờ thành công.
1. Tình huống thử thách
Bạn được giao nhiệm vụ đánh giá an toàn cho một cổng thông tin nhân sự nội bộ chạy tại http://127.0.0.1:8080. Khi đăng nhập bằng tài khoản thử nghiệm của một nhân viên bình thường (user:user123), giao diện chỉ có duy nhất tính năng xem bảng chấm công hàng ngày. Menu quản lý lương và xuất báo cáo tài chính hoàn toàn không xuất hiện trên giao diện web.
[!TIP] Thực hành trên máy thật (Hands-on Local Lab): Bạn có thể tự khởi chạy mock portal server ngay trên máy tính bằng một file Python 35 dòng siêu nhẹ (không cần cài thêm thư viện):
Python# Lưu thành mock_portal.py và chạy: python3 mock_portal.py import http.server, json MOCK_JS_BUNDLE = b""" var app={init:function(){console.log("App loaded");}}; function getTimesheet(e){return fetch("/api/v1/user/timesheet?id="+e);} function exportPayroll(e,t,n){return fetch("/api/v2/finance/reports/export",{method:"POST",headers:{"Content-Type":"application/json","X-Debug-Role":n||"employee"},body:JSON.stringify({report_id:e,format:t||"csv",include_salary:!0})});} """ class PortalHandler(http.server.BaseHTTPRequestHandler): def do_GET(self): if self.path == "/static/js/app.bundle.js": self.send_response(200) self.send_header("Content-Type", "application/javascript; charset=utf-8") self.end_headers(); self.wfile.write(MOCK_JS_BUNDLE); return if self.path.startswith("/api/v1/user/timesheet"): self.send_response(200) self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(b'{"status":"success","data":{"hours":40,"approved":true}}'); return self.send_response(404); self.end_headers() def do_POST(self): if self.path == "/api/v2/finance/reports/export": role = self.headers.get("X-Debug-Role", "employee") content_len = int(self.headers.get("Content-Length", 0)) body = json.loads(self.rfile.read(content_len).decode("utf-8") or "{}") if role == "finance_admin" and body.get("include_salary") is True: self.send_response(200) self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(b'{"status":"unlocked","flag":"FLAG{JS_RECON_AST_MASTER_OLHUB}"}') return self.send_response(403) self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(b'{"error":"forbidden","message":"Requires finance_admin role"}') return self.send_response(404); self.end_headers() http.server.HTTPServer(("127.0.0.1", 8080), PortalHandler).serve_forever()
2. Nhiệm vụ của bạn
Hãy vận dụng toàn bộ kỹ thuật Scope Expansion, JavaScript Recon và Target Heatmapping để thực hiện ba nhiệm vụ:
- Nhiệm vụ 1 (Tải và trích xuất bundle): Truy cập vào
http://127.0.0.1:8080/static/js/app.bundle.js, sử dụng công cụ bóc tách regex hoặc đọc mã JavaScript để tìm ra endpoint API thuộc Vùng Đỏ (Tài chính / Xuất báo cáo). - Nhiệm vụ 2 (Chẩn đoán tham số ngầm): Phân tích hàm gọi API trong file JavaScript để xác định:
- Header HTTP tùy biến nào đang được sử dụng để chỉ định quyền hạn?
- Cấu trúc body JSON gửi kèm yêu cầu những trường thông tin gì?
- Nhiệm vụ 3 (Lập trình PoC nhận cờ): Viết script Python sử dụng thư viện
requestsđể bắn request trực tiếp tới endpoint ẩn với đúng header và body đã phát hiện để nhận cờ thành công.
Dưới đây là một câu hỏi dự đoán trước khi bạn xem lời giải mẫu:
Tại sao một endpoint tài chính bí mật của backend lại xuất hiện bên trong mã nguồn JavaScript tải về trình duyệt của một nhân viên bình thường?
3. Lời giải mẫu & Đối chiếu thực nghiệm
Tự mình hoàn thành thử thách trước khi đối chiếu với lời giải chi tiết dưới đây:
- Q1Phân tích file JavaScript bundle, endpoint ẩn và các tham số cần thiết là gì?
- Q2Vì sao sửa header 'X-Debug-Role: finance_admin' lại giúp vượt qua cơ chế kiểm tra quyền?
- Q3Mã nguồn Python hoàn chỉnh để tự động hóa trích xuất cờ thử thách này được viết như thế nào?
4. AI Copilot Slot: Thử thách code review an toàn cùng AI
Khi làm việc với các hệ thống frontend hiện đại, nhiều lập trình viên sử dụng AI để gợi ý cấu trúc ứng dụng. Hãy thử kiểm tra xem AI có nhận ra rủi ro khi gom chung code admin vào client bundle hay không.
[!TIP] Prompt thử nghiệm (Copy & Test trên AI của bạn): "Tôi đang xây dựng một ứng dụng React. Tôi có các hàm gọi API của Admin như
exportPayroll()và các hàm của User thường. Tôi viết chung vào một fileapi.jsvà giấu nút bấm trên giao diện nếuuser.role !== 'admin'. Cách làm này có rủi ro bảo mật nào không?"Đối chiếu thực tế: Quan sát xem AI có cảnh báo bạn về kỹ thuật JavaScript Reconnaissance không: người dùng thông thường chỉ cần mở DevTools hoặc đọc file bundle là thấy toàn bộ đường dẫn API nội bộ và tham số ẩn của admin. Giải pháp đúng là áp dụng Code Splitting (Role-based Dynamic Imports) và quan trọng nhất: phân quyền chặt chẽ tại backend API.
5. Liên hệ các bài khác
- Hệ thống hóa toàn bộ kiến thức: Chuyển sang Bài 05 — Tổng kết module Phương pháp luận Săn Bug để hoàn thành bài tự đánh giá năng lực.
- Kỹ thuật đào sâu mã nguồn backend: Ở module kế tiếp, bạn sẽ học cách lần vết dữ liệu bẩn từ API endpoint này chạm tới cơ sở dữ liệu qua Nguyên lý Taint Analysis.
- Phân loại rủi ro nghiệp vụ: Xem lại bảng xếp hạng Vùng Đỏ tại Bài 03 — Target Heatmapping.
Bài tiếp theo: Tổng kết module Phương pháp luận Săn Bug Hiện đại
Target Heatmapping: Định vị Điểm nóng Nghiệp vụ
Bài tiếpTổng kết module Phương pháp luận Săn Bug Hiện đại
Bài này có giúp bạn hiểu bản chất không?
Bài này đáng gửi cho bạn học cùng?
Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.
Thảo luận & góp ý
Hỏi đáp về bài này