Bài 25. Lỗ hổng web: SQL injection, XSS, CSRF, directory traversal
Khóa học CompTIA Security+ SY0-801 · Phần 2: Mối đe dọa, lỗ hổng và tấn công · Bài 25 · 🎯 Objective 2.4 · ⏱️ Đọc khoảng 14 phút · 🧪 Không cần lab · 📝 5 câu bài tập cuối bài
🎯 Mục tiêu bài học
- Xác định bốn lỗ hổng web phổ biến nằm ở đâu trong luồng giữa trình duyệt, máy chủ và dữ liệu.
- Giải thích SQL injection và vì sao truy vấn tham số hóa ngăn được nó.
- Phân biệt XSS với CSRF, và các dạng XSS (reflected, stored, DOM).
- Hiểu directory traversal và cách giới hạn đường dẫn tệp.
- Biết các lớp phòng thủ bổ sung: WAF, mã hóa đầu ra, CSP, token chống CSRF.
📎 Vị trí trong đề thi: Bài 24 giới thiệu lỗi ứng dụng nói chung. Bài này đi vào ứng dụng web, nơi bốn lỗ hổng trên là kinh điển trong đề. Đề thường mô tả một hiện tượng và hỏi tên lỗ hổng hoặc biện pháp phòng chống phù hợp nhất.
💡 Liên hệ thực tế: kiểm tra cổng khách hàng trên môi trường thử
Thứ Sáu, 10:00. Công ty chị Lan có một cổng thông tin cho khách hàng xem hóa đơn. Chị Lan đồng ý bằng văn bản cho Nam kiểm tra trên môi trường thử, không phải hệ thống thật. Đây là tình huống minh họa, không phải vụ việc có thật.
| Thử nghiệm | Kết quả | Loại lỗ hổng |
|---|---|---|
| Nhập một dấu nháy đơn vào ô tìm hóa đơn | Trang báo lỗi cơ sở dữ liệu và hiện cả câu truy vấn | SQL injection |
| Gửi nhận xét có chứa thẻ HTML, rồi nhân viên mở trang nhận xét | Thẻ HTML được trình duyệt thực thi thay vì hiển thị như chữ | XSS (dạng lưu trữ) |
| Nút "Xóa hóa đơn" chỉ là một đường dẫn đơn giản, không có mã xác nhận | Một trang khác có thể khiến trình duyệt đã đăng nhập gửi yêu cầu xóa | CSRF |
Đổi tên tệp trong đường dẫn tải hóa đơn thành chuỗi có ../ |
Đọc được tệp nằm ngoài thư mục hóa đơn | Directory traversal |
Chị Lan hỏi: "Bốn lỗi khác nhau, nhưng em bảo cùng một gốc?" Nam trả lời: gốc chung là ứng dụng tin dữ liệu từ trình duyệt (nội dung nhập, đường dẫn, yêu cầu) mà không kiểm tra hay giới hạn. Còn khác nhau ở chỗ nào bị lợi dụng: trình duyệt của người dùng, hay máy chủ, cơ sở dữ liệu, hệ thống tệp.
🗺️ Hình 25a. XSS và CSRF nhắm vào trình duyệt người dùng, SQL injection và directory traversal nhắm vào phía máy chủ.
📘 Kiến thức cốt lõi
🌐 Luồng của một ứng dụng web
Khi bạn dùng một trang web, trình duyệt gửi yêu cầu tới máy chủ web. Máy chủ chạy ứng dụng, truy vấn cơ sở dữ liệu hoặc đọc tệp, rồi trả phản hồi về trình duyệt. Mọi thứ đi qua đường này (nội dung nhập, đường dẫn, cookie) đều do phía người dùng kiểm soát được, nên đều có thể bị kẻ tấn công thay đổi.
Hai nhóm lỗ hổng:
- Phía máy chủ: kẻ tấn công lừa máy chủ làm điều không nên (SQL injection, directory traversal).
- Phía người dùng: kẻ tấn công lợi dụng trình duyệt của nạn nhân (XSS, CSRF).
💉 SQL injection
SQL injection là một dạng injection (Bài 24) nhắm vào cơ sở dữ liệu. Ứng dụng ghép dữ liệu người dùng vào câu truy vấn SQL. Nếu dữ liệu chứa ký tự đặc biệt, nó thay đổi cấu trúc câu truy vấn.
Ví dụ minh họa: ứng dụng tạo câu truy vấn bằng cách ghép tên khách hàng vào chuỗi. Nếu người dùng nhập ' OR '1'='1, điều kiện trở thành luôn đúng và truy vấn trả về toàn bộ bảng thay vì một khách hàng.
💉 Hình 25b. Cùng một đầu vào, hai cách viết truy vấn cho hai kết quả khác nhau.
Hậu quả có thể gồm đọc dữ liệu trái phép, sửa hoặc xóa dữ liệu, vượt qua đăng nhập, và trong một số hệ thống còn chạy lệnh trên máy chủ.
Cách phòng chống:
- Truy vấn tham số hóa (parameterized query, prepared statement): lệnh được cố định sẵn, dữ liệu người dùng được truyền riêng như một giá trị, không bao giờ được hiểu là lệnh. Đây là biện pháp chính.
- Kiểm tra đầu vào theo danh sách cho phép (định dạng, độ dài).
- Quyền tối thiểu cho tài khoản cơ sở dữ liệu mà ứng dụng dùng, ví dụ chỉ đọc nếu chỉ cần đọc.
- Không hiển thị lỗi chi tiết cho người dùng cuối, vì thông báo lỗi giúp kẻ tấn công hiểu cấu trúc truy vấn.
- WAF (Web Application Firewall) là lớp lọc bổ sung, không thay thế việc sửa mã.
📜 XSS (Cross-Site Scripting)
XSS xảy ra khi ứng dụng đưa dữ liệu người dùng vào trang web mà không mã hóa đúng, nên đoạn mã (thường là JavaScript) do kẻ tấn công chèn vào được chạy trong trình duyệt của nạn nhân, với đặc quyền như chính trang web đó.
Ba dạng thường gặp:
| Dạng | Cách hoạt động |
|---|---|
| Reflected (phản xạ) | Mã nằm trong một đường dẫn hoặc yêu cầu, máy chủ trả ngược lại trong trang. Nạn nhân phải bấm vào liên kết đó |
| Stored (lưu trữ) | Mã được lưu vào cơ sở dữ liệu (như bình luận, hồ sơ), rồi hiển thị cho mọi người xem trang |
| DOM-based | Lỗi nằm ở mã JavaScript phía trình duyệt xử lý dữ liệu không an toàn, không cần máy chủ phản hồi mã độc |
Hậu quả: đánh cắp cookie phiên hay thông tin hiển thị trên trang, thực hiện hành động thay nạn nhân, chuyển hướng tới trang giả, hiển thị biểu mẫu giả để lấy mật khẩu.
Cách phòng chống:
- Mã hóa đầu ra (output encoding): khi hiển thị dữ liệu, chuyển ký tự đặc biệt thành dạng không được hiểu như mã. Đây là biện pháp chính.
- Kiểm tra đầu vào và làm sạch nội dung HTML cho phép.
- Content Security Policy (CSP): quy định trình duyệt chỉ được chạy mã từ nguồn đáng tin.
- Cookie có cờ HttpOnly để mã JavaScript không đọc được cookie phiên.
- Dùng khung phát triển (framework) có sẵn cơ chế mã hóa đầu ra.
🎭 CSRF (Cross-Site Request Forgery)
CSRF là việc khiến trình duyệt của người dùng đã đăng nhập gửi một yêu cầu ngoài ý muốn tới một trang web. Trình duyệt tự động đính kèm cookie đăng nhập, nên trang web tưởng đó là yêu cầu hợp lệ của người dùng.
Ví dụ: người dùng đang đăng nhập vào cổng hóa đơn, rồi bấm vào một liên kết hay trang khác chứa yêu cầu "xóa hóa đơn". Trình duyệt gửi yêu cầu kèm cookie, và máy chủ thực hiện.
Cách phòng chống:
- Token chống CSRF: mỗi biểu mẫu hoặc yêu cầu thay đổi dữ liệu kèm một mã ngẫu nhiên, khó đoán, do máy chủ kiểm tra.
- Cookie có thuộc tính SameSite để hạn chế gửi cookie trong yêu cầu từ trang khác.
- Yêu cầu xác nhận lại (mật khẩu hoặc MFA) với thao tác nhạy cảm.
- Không dùng yêu cầu GET để thay đổi dữ liệu.
Phân biệt XSS và CSRF:
| XSS | CSRF | |
|---|---|---|
| Lợi dụng | Lòng tin của người dùng vào trang web | Lòng tin của trang web vào trình duyệt đã đăng nhập |
| Mã độc chạy ở đâu | Trong trang web, trên trình duyệt nạn nhân | Không cần chạy mã, chỉ cần gửi yêu cầu giả |
| Điều kiện | Ứng dụng không mã hóa đầu ra | Nạn nhân đang đăng nhập và ứng dụng không kiểm tra token |
📂 Directory traversal
Directory traversal (còn gọi là path traversal) xảy ra khi ứng dụng dùng đường dẫn tệp do người dùng cung cấp mà không giới hạn. Kẻ tấn công chèn các ký hiệu quay về thư mục cha (như ../) để đọc hoặc ghi tệp ngoài thư mục được phép, ví dụ tệp cấu hình chứa mật khẩu.
- Có thể xuất hiện ở dạng mã hóa trong đường dẫn URL, nên kiểm tra đơn giản dễ bị qua mặt.
- Đây là lý do mật khẩu trong tệp cấu hình (Bài 24) càng nguy hiểm: một lỗ hổng traversal đủ để lấy chúng.
Cách phòng chống:
- Không dùng trực tiếp đường dẫn từ người dùng. Cho người dùng chọn một mã định danh, còn máy chủ tự tra ra tệp tương ứng.
- Chuẩn hóa đường dẫn (canonicalize) rồi kiểm tra kết quả vẫn nằm trong thư mục cho phép.
- Quyền tối thiểu: tài khoản chạy máy chủ web không có quyền đọc các tệp nhạy cảm.
- Chạy ứng dụng trong môi trường cô lập (container) để giới hạn phạm vi.
🧭 Một số lỗ hổng web khác
| Lỗ hổng | Ý nghĩa |
|---|---|
| Kiểm soát truy cập yếu (như IDOR) | Đổi một mã số trong đường dẫn là xem được dữ liệu của người khác |
| SSRF | Lừa máy chủ gửi yêu cầu tới địa chỉ khác, như hệ thống nội bộ |
| Tải tệp lên không kiểm soát | Cho phép tải lên tệp độc hại và chạy trên máy chủ |
| Quản lý phiên yếu | Mã phiên dễ đoán hoặc bị đánh cắp nên bị chiếm phiên đăng nhập |
Tổ chức phi lợi nhuận OWASP công bố danh sách các rủi ro ứng dụng web phổ biến (OWASP Top 10) và là nguồn tham khảo tốt khi viết hoặc kiểm tra ứng dụng web.
🎯 Mẹo làm bài: nhìn chỗ bị lợi dụng. "Dữ liệu nhập bị hiểu thành câu truy vấn, trả về cả bảng" là SQL injection. "Mã chạy trong trình duyệt của người xem" là XSS, lưu trong cơ sở dữ liệu thì là stored. "Người dùng đang đăng nhập bị khiến gửi yêu cầu ngoài ý muốn" là CSRF. "
../để đọc tệp ngoài thư mục" là directory traversal. Chọn biện pháp theo cặp: SQL injection với truy vấn tham số hóa, XSS với mã hóa đầu ra, CSRF với token chống CSRF, traversal với chuẩn hóa và giới hạn đường dẫn.
🧠 Áp vào câu chuyện của Nam
| Câu hỏi của chị Lan | Khái niệm trả lời |
|---|---|
| "Vì sao một dấu nháy đơn lại làm lộ câu truy vấn?" | SQL injection, kèm việc hiển thị lỗi chi tiết. Cần truy vấn tham số hóa |
| "Thẻ HTML trong nhận xét chạy được là sao?" | XSS dạng lưu trữ. Cần mã hóa đầu ra và CSP |
| "Nút xóa không có mã xác nhận thì sao?" | CSRF. Cần token chống CSRF và không dùng GET để xóa |
| "Đổi tên tệp mà đọc được tệp khác?" | Directory traversal. Cần chuẩn hóa và giới hạn đường dẫn |
| "WAF có đủ không?" | Chỉ là lớp bổ sung, vẫn phải sửa mã |
📖 Thuật ngữ cần nhớ
| Thuật ngữ | Nghĩa |
|---|---|
| SQL injection | Chèn dữ liệu để thay đổi câu truy vấn cơ sở dữ liệu. |
| Parameterized query | Truy vấn tham số hóa, tách dữ liệu khỏi lệnh. |
| XSS | Chèn mã chạy trong trình duyệt của người xem trang. |
| Reflected / Stored / DOM-based | Ba dạng của XSS. |
| Output encoding | Mã hóa dữ liệu khi hiển thị để không bị hiểu thành mã. |
| CSP | Chính sách giới hạn nguồn mã mà trình duyệt được chạy. |
| CSRF | Khiến trình duyệt đã đăng nhập gửi yêu cầu giả. |
| Anti-CSRF token | Mã ngẫu nhiên kèm yêu cầu để xác thực nguồn. |
| Directory traversal | Dùng ../ để truy cập tệp ngoài thư mục cho phép. |
| WAF | Tường lửa ứng dụng web. |
📌 Tóm tắt nhanh
- Gốc chung: ứng dụng tin dữ liệu từ trình duyệt. SQL injection và directory traversal nhắm vào máy chủ. XSS và CSRF nhắm vào trình duyệt.
- SQL injection: chống bằng truy vấn tham số hóa, quyền tối thiểu, ẩn lỗi chi tiết.
- XSS: chống bằng mã hóa đầu ra, CSP, cờ HttpOnly. Có ba dạng: reflected, stored, DOM-based.
- CSRF: chống bằng token chống CSRF, SameSite, xác nhận lại. XSS lợi dụng lòng tin vào trang web, CSRF lợi dụng lòng tin của trang web vào trình duyệt.
- Directory traversal: không dùng đường dẫn từ người dùng, chuẩn hóa đường dẫn, giới hạn quyền. WAF chỉ là lớp bổ sung.
💬 Hỏi & Đáp nhanh
❓ Dùng WAF thì có cần sửa mã nữa không? Vẫn cần. WAF giúp chặn nhiều mẫu tấn công đã biết và là lớp bảo vệ tạm khi chưa kịp sửa mã, nhưng có thể bị né. Cách bền vững là sửa gốc: truy vấn tham số hóa, mã hóa đầu ra, kiểm tra đường dẫn.
❓ HTTPS có chặn được XSS hay SQL injection không? Không. HTTPS mã hóa đường truyền giữa trình duyệt và máy chủ để chống nghe lén. Dữ liệu độc hại vẫn đi qua đường truyền được mã hóa đó và vẫn bị ứng dụng xử lý sai.
❓ Tự thử các lỗi này lên một trang web thật có được không? Chỉ khi bạn sở hữu hệ thống hoặc có văn bản cho phép. Thử trên hệ thống của người khác khi chưa được phép có thể vi phạm pháp luật, giống ranh giới ethical ở Bài 17. Cách luyện tập an toàn là dùng ứng dụng thử nghiệm cài trong phòng lab riêng.
📝 Bài tập đánh giá
Tự chọn đáp án cho từng câu, rồi đối chiếu với phần đáp án ở cuối bài.
Câu 1. Biện pháp chính để ngăn SQL injection là gì?
- A. Tăng độ dài mật khẩu quản trị
- B. Dùng truy vấn tham số hóa để tách dữ liệu khỏi lệnh
- C. Dùng nhiều màu sắc hơn trong giao diện
- D. Chỉ cho phép người dùng nhập chữ thường
Câu 2. Một kẻ tấn công đăng một bình luận chứa mã JavaScript, và mã đó chạy trên trình duyệt của mọi người xem bình luận. Đây là kiểu tấn công nào?
- A. CSRF
- B. Directory traversal
- C. XSS dạng lưu trữ (stored)
- D. Buffer overflow
Câu 3. Điều nào mô tả đúng nhất CSRF?
- A. Khiến trình duyệt của người dùng đã đăng nhập gửi một yêu cầu ngoài ý muốn tới trang web
- B. Đọc tệp ngoài thư mục cho phép bằng
../ - C. Chèn câu lệnh vào truy vấn cơ sở dữ liệu
- D. Làm tràn bộ đệm của máy chủ
Câu 4. Một ứng dụng cho phép tải tệp qua tham số tên tệp, và kẻ tấn công dùng ../ để đọc tệp cấu hình. Biện pháp nào phù hợp nhất?
- A. Chuẩn hóa đường dẫn, kiểm tra nằm trong thư mục cho phép và không dùng trực tiếp đường dẫn người dùng nhập
- B. Tăng dung lượng đĩa
- C. Đổi màu trang tải tệp
- D. Tắt tường lửa
Câu 5. Biện pháp nào là cách chính để chống XSS?
- A. Mã hóa đầu ra khi hiển thị dữ liệu người dùng, kèm kiểm tra đầu vào
- B. Dùng truy vấn tham số hóa
- C. Tăng số lần thử đăng nhập
- D. Mở thêm cổng trên tường lửa
👉 Đáp án
Câu 1: B — Truy vấn tham số hóa giữ dữ liệu người dùng chỉ là giá trị, không bao giờ được hiểu thành lệnh.
Câu 2: C — Mã được lưu và hiển thị cho mọi người xem là XSS dạng lưu trữ (stored).
Câu 3: A — CSRF khiến trình duyệt đã đăng nhập gửi yêu cầu giả. B là directory traversal, C là SQL injection, D là buffer overflow.
Câu 4: A — Chuẩn hóa đường dẫn, kiểm tra nằm trong thư mục cho phép và tránh dùng trực tiếp đường dẫn từ người dùng.
Câu 5: A — Mã hóa đầu ra, kèm kiểm tra đầu vào, ngăn dữ liệu người dùng bị hiểu thành mã. Truy vấn tham số hóa là biện pháp cho SQL injection.
📚 Bài viết thuộc khóa học CompTIA Security+ của VNExperts
🧭 Điều hướng
| ⬅️ Bài trước | 🏠 Mục lục khóa học | Bài kế tiếp ➡️ |
|---|---|---|
| Bài 24: Lỗ hổng ứng dụng: injection, buffer overflow, race condition, hardcoded secrets | Mục lục khóa học CompTIA Security+ | Bài 26: Lỗ hổng phần cứng, ảo hóa, cloud và thiết bị di động |