Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 4 — Phát hiện XSS và IDOR: hai bài toán ngữ cảnh khác nhau

Đã đọc 0/7 mục · còn khoảng 3 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

SQLi là bài toán taht theo dấu dữ liệu. XSS cũng là taint nhưng ở đầu ra HTML. IDOR thì không phải taint — nó là bài toán thiếu kiểm tra quyền, cần LLM hiểu logic nghiệp vụ. Hai loại đòi hai cách tiếp cận.

A. XSS — dữ liệu bẩn ra HTML mà không escape

XSS (Cross-Site Scripting) xảy ra khi input người dùng được render vào trang mà không escape, cho phép chèn <script>.

$name = $_GET['name'];
echo "<h1>Xin chào $name</h1>";   // XSS: name = <script>...</script>

Điểm tinh tế: ngữ cảnh output quyết định cách escape đúng.

  • Trong HTML body → htmlspecialchars.
  • Trong thuộc tính HTML → escape + đóng ngoặc kép.
  • Trong <script> / JSON → JS/JSON encode.
  • Trong URL → urlencode.
Một htmlspecialchars đặt sai chỗ (ví dụ bên trong <script>) vẫn dính XSS. Prompt XSS phải hỏi: dữ liệu ra ở ngữ cảnh nào, và escape có khớp ngữ cảnh đó không?

Tìm XSS. Với mỗi nơi in dữ liệu người dùng ra response:
1. Xác định NGỮ CẢNH output: html_body | html_attr | js | url | css.
2. Xác định escape đang dùng (nếu có).
3. Báo XSS nếu escape THIẾU hoặc SAI ngữ cảnh.
Chú ý framework: template auto-escape (Blade {{ }}, Twig) là AN TOÀN,
nhưng {!! !!} hoặc |raw thì KHÔNG.

Mẹo framework: Blade {{ $x }} tự escape (an toàn), {!! $x !!} thì không. Agent phải biết dấu hiệu này để tránh báo nhầm.

B. IDOR — thiếu kiểm tra quyền sở hữu

IDOR (Insecure Direct Object Reference) xảy ra khi người dùng truy cập tài nguyên của người khác bằng cách đổi ID, vì server không kiểm tra quyền sở hữu.

// GET /invoice?id=123
$id = (int) $_GET['id'];                 // đã ép kiểu -> KHÔNG phải SQLi
$inv = Invoice::find($id);
return $inv->toJson();                    // IDOR: không kiểm invoice thuộc user!

Chú ý: ép kiểu (int) loại bỏ SQLi nhưng không giải quyết IDOR. Đây là điểm nhiều tool bỏ sót vì chúng chỉ nghĩ về taint.

Bản vá đúng:

$inv = Invoice::find($id);
if ($inv->user_id !== auth()->id()) abort(403);

Khung tư duy IDOR

Với mỗi handler nhận một ID tài nguyên từ request, hỏi 3 câu:

  • Tài nguyên này có chủ sở hữu (user_id, tenant_id) không?
  • Trước khi trả/sửa/xóa, code có so khớp chủ sở hữu với người đang đăng nhập không?
  • Nếu là hành động quản trị, có kiểm tra role không?
Thiếu bước 2 hoặc 3 → IDOR / broken access control.

Tìm IDOR. Với mỗi route nhận ID tài nguyên:
- Tài nguyên có cột owner (user_id/tenant_id/account_id)?
- Có so khớp owner == người dùng hiện tại TRƯỚC khi trả dữ liệu?
- Có kiểm role cho hành động nhạy cảm?
Báo IDOR nếu thiếu kiểm tra quyền. Ghi rõ dòng NÊN có check.

IDOR cần LLM đọc ý định: model có cột user_id nghĩa là tài nguyên có chủ → phải kiểm. Đây chính là chỗ LLM vượt trội so với rule tĩnh.

Các bước triển khai

  • Tách hai prompt riêng: xss.md và idor.md (bản chất khác nhau).
  • Với XSS: cấp thông tin template engine để biết auto-escape.
  • Với IDOR: cấp schema bảng (cột owner) qua tool tra DB.
  • Chạy song song, gộp finding.
  • Đưa tất cả qua bước phản biện (bài 5).

Checklist

  • [ ] XSS: đã xét đúng ngữ cảnh output (body/attr/js/url)?
  • [ ] XSS: nhận biết auto-escape của template engine?
  • [ ] IDOR: đã tra schema để biết tài nguyên có owner?
  • [ ] IDOR: phân biệt rõ với SQLi (ép kiểu ≠ chống IDOR)?

Sai lầm thường gặp

  • Dùng chung một prompt cho cả 3 loại: XSS/SQLi là taint, IDOR là access-control — trộn lẫn làm giảm độ chính xác.
  • Báo XSS với template auto-escape: false positive kinh điển.
  • Bỏ sót IDOR vì đã thấy ép kiểu: ép kiểu chỉ chống injection, không chống truy cập trái phép.
  • Không cấp schema cho IDOR: agent không biết tài nguyên có chủ, đoán mò.
Bài sau: trái tim của khóa học — xác thực đối kháng để giảm false positive.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi