WorksheetsCâu hỏi trắc nghiệm về bảo mật web và SQL Injection
Total questions: 90
Worksheet time: 45mins
Đối với web nâng cao, khi thiết kế frontend an toàn, ưu tiên nào đúng?
Tính năng > bảo mật
Bảo mật tích hợp vào thiết kế từ đầu, không chắp vá sau
Tối ưu UI là đủ
Chỉ cần backend bảo mật
SQL Injection là gì?
Chèn script vào trình duyệt
Chèn lệnh SQL độc hại vào câu truy vấn
Chèn HTML vào trang
Chèn CSS vào style
Điều kiện cơ bản để xảy ra SQLi:
Truy vấn được tạo bằng cách nối chuỗi trực tiếp từ input người dùng
Câu lệnh SQL cố định
Chỉ dùng SELECT * FROM table
Không dùng DB
Câu nào dễ bị SQLi?
SELECT * FROM users WHERE id = ? (prepared statement)
SELECT * FROM users WHERE id = '1'
SELECT * FROM users WHERE id = ' + userInput + '
SELECT * FROM users WHERE id = $1 (parameterized)
Biện pháp phòng chống SQL Injection hiệu quả nhất là:
Escape thủ công ký tự '
Sử dụng prepared statements/parameterized queries
Chỉ cho phép số
Dùng HTTPS
SQLi dạng “Union-based” cho phép attacker làm gì?
Kết hợp nhiều DB lại
Ghép thêm kết quả truy vấn khác vào kết quả bình thường để lộ dữ liệu
Ghép file
Ghép HTTP request
SQLi “Blind” là khi:
Không có DB
Server không trả lỗi chi tiết hoặc kết quả trực tiếp, attacker suy đoán qua phản ứng (true/false, thời gian...)
Attacker bị mù
Không có input
Để giảm thiểu hậu quả nếu SQLi xảy ra, nên:
Cho tài khoản DB quyền tối đa
Áp dụng nguyên tắc least privilege: tài khoản DB chỉ có quyền cần thiết
Dùng tài khoản root cho tất cả
Lưu DB trên desktop
Trong ORM (Object-Relational Mapping), câu nào vẫn có thể gây SQLi nếu dùng sai?
User.objects.get(id=1)
db.raw("SELECT * FROM users WHERE email = '" + email + "'")
User.query.filter(User.email == email)
User.create(...)
Hàm nào nguy hiểm trong nhiều ngôn ngữ khi dùng với input người dùng để xây query?
format/string interpolation trên câu SQL
length()
toUpperCase()
trim()
Nếu ứng dụng chỉ dùng NoSQL (ví dụ MongoDB), SQLi:
Không thể xảy ra
Có thể có injection ở mức query NoSQL nếu build query từ input không an toàn
Không cần quan tâm
Luôn an toàn
Tại sao không nên thông báo lỗi SQL chi tiết cho client?
Người dùng không hiểu
Tiết lộ tên bảng, cột, cấu trúc DB giúp attacker tinh chỉnh payload
Làm chậm server
Không liên quan
Giới hạn độ dài input giúp giảm:
XSS
Khả năng gửi payload SQLi quá dài, giảm DoS, nhưng không đủ để chống SQLi
Cần dùng DB
HTTPS
Stored procedure có thể giúp chống SQLi nếu:
Lại build dynamic SQL bằng nối chuỗi bên trong SP
Sử dụng parameter đúng cách, không nối chuỗi
Không dùng parameter
Không có logic
Câu query nào ít nguy hiểm hơn:
"SELECT * FROM users WHERE name = '
"SELECT * FROM users WHERE name = $1" với values = [req.body.name]
"SELECT * FROM users WHERE name LIKE '%
"DELETE FROM users"
Để phát hiện SQLi, logging nên:
Không log gì
Log query với parameter & IP (nhưng không log dữ liệu nhạy cảm)
Log mật khẩu
Log cookie plaintext
Injection là một trong top lỗi OWASP bởi vì:
Khó khai thác
Dễ phòng tránh nhưng hậu quả rất nặng nếu tồn tại
Không phổ biến
Chỉ có ở DB cũ
Nguyên tắc vàng về validation:
Tin tưởng dữ liệu từ nội bộ
Không tin bất kỳ input nào, luôn validate phía server
Chỉ kiểm tra ở client
Kiểm tra một lần khi đăng ký
Kiểm tra “whitelist” nghĩa là:
Cho phép mọi thứ trừ cái cấm
Chỉ cho phép giá trị/định dạng xác định, chặn tất cả còn lại
Không kiểm tra gì
Chỉ chặn ký tự '
Validation phía client bằng JavaScript:
Đủ an toàn
Dùng để cải thiện UX, nhưng không thay thế validation phía server
Không cần thiết
Bắt buộc với mọi web
Khi nhận input “số lượng”, kiểu validation hợp lý là:
Kiểm tra là số, trong khoảng hợp lệ (>=0, < giới hạn)
Chỉ check không rỗng
Chỉ check độ dài
Việc chuẩn hóa (normalize) dữ liệu trước khi validate giúp:
Tăng kích thước
Tránh bypass bằng biến thể ký tự (ví dụ khoảng trắng, Unicode)
Giảm bảo mật
Không ảnh hưởng
Với input email, validate hợp lý là:
Chỉ check có ký tự “@”
Dùng regex hoặc thư viện để kiểm tra định dạng cơ bản
Gửi mail thử
Không cần check
Với input file upload, validation cần:
Chỉ dựa vào phần mở rộng .jpg/.png
Kiểm tra content-type, kiểm tra magic bytes, giới hạn kích thước, whitelist loại file
Không kiểm tra
Cho phép mọi định dạng
Lý do không nên tự viết regex phức tạp cho mọi thứ (như URL, email, số thẻ) nếu không cần:
Regex không an toàn
Dễ sai, khó bảo trì, có thể tạo lỗ hổng performance (ReDoS)
Không chạy trên server
Không hỗ trợ trong ngôn ngữ
Validation nên được thực hiện:
Chỉ khi insert
Khi insert, update và trước khi xử lý logic quan trọng
Chỉ khi delete
Không cần
Output encoding và input validation khác nhau ở điểm:
Input validation xử lý đầu vào, output encoding xử lý trước khi xuất ra
Cả hai giống nhau
Chỉ cần 1 trong 2
Không dùng cho bảo mật
“Server-side validation” nghĩa là:
Kiểm tra dữ liệu trên máy client
Kiểm tra dữ liệu trên server trước khi xử lý
Kiểm tra bằng tay
Kiểm tra trong DB
Một mẫu tốt khi validate JSON request là:
Parse JSON rồi dùng schema validation (ví dụ Joi, Yup...)
Dùng eval
Không parse
Chỉ check null
Validation giúp chống:
SQLi (phần nào), XSS (phần nào), dữ liệu sai logic
Mọi loại tấn công
Chỉ XSS
Chỉ SQLi
Khi có nhiều nguồn input (form, API, import file), validation nên:
Chỉ áp dụng cho form
Áp dụng cho tất cả đường vào dữ liệu
Chỉ áp dụng cho API
Không cần
Với input “ngày sinh”, validate hợp lý là:
Chấp nhận mọi chuỗi
Định dạng ngày & phạm vi hợp lý (không ở tương lai xa, không quá 150 năm trước, tuỳ yêu cầu)
Chỉ check length
Không check
“Canonicalization” trong bảo mật dữ liệu là:
Mã hóa dữ liệu
Chuyển dữ liệu về dạng chuẩn (lowercase, remove dot, normalize path...) trước khi so sánh/validate
Xóa dữ liệu
Định dạng JSON
Với input đường dẫn file từ user, tốt nhất:
Cho phép đường dẫn tuỳ ý
Không cho phép user cung cấp đường dẫn trực tiếp, sử dụng ID trỏ tới file được cấu hình sẵn
Ghép vào path
Không validate
Validation kiểu “blacklist ký tự nguy hiểm” có nhược điểm:
Dễ thiếu trường hợp, attacker tìm cách bypass
Không có nhược điểm
Khó implement
Không chạy
Tại sao dùng thư viện cũ là nguy hiểm?
Chạy chậm hơn
Có thể chứa lỗ hổng đã được công bố và dễ bị khai thác
Không chạy trên server
Làm mã xấu
Công cụ như npm audit, pip audit dùng để:
Minify code
Phát hiện dependency có lỗ hổng đã biết
Cải thiện hiệu năng
Tự viết test
Khi cập nhật thư viện, bước quan trọng là:
Cập nhật trực tiếp trên production
Test trên môi trường staging trước
Không cần test
Rollback ngay
Tại sao nên khóa version (lockfile) cho dependency?
Để mọi môi trường dùng đúng phiên bản đã test
Để khó cài hơn
Để không cần update
Để giảm dung lượng
“Transitive dependency” là:
Thư viện mà ứng dụng gọi trực tiếp
Thư viện mà thư viện khác phụ thuộc, gián tiếp được dùng
Thư viện không dùng
Hệ điều hành
Đưa thẳng script từ CDN của bên thứ ba mà không kiểm soát phiên bản có nguy cơ:
Bị thay đổi nội dung script nếu CDN bị tấn công
Không sao vì CDN an toàn tuyệt đối
Không thể tấn công
Chỉ ảnh hưởng tốc độ
Khi phát hiện thư viện có CVE nghiêm trọng, nên:
Phớt lờ
Cập nhật phiên bản vá, hoặc thay thế thư viện khác, test kỹ
Gỡ toàn bộ ứng dụng
Không dùng DB
“Security patch” là:
Bản vá bảo mật cho phần mềm/thư viện
Bản nâng cấp UI
Bản quảng cáo
Bản log
Dùng quá nhiều thư viện không cần thiết có thể:
Tăng bề mặt tấn công (nhiều lỗ hổng tiềm ẩn)
Tăng bảo mật
Không ảnh hưởng
Giảm độ phụ thuộc
Kiểm tra license của thư viện liên quan đến:
Bảo mật
Pháp lý & cách sử dụng, phân phối
Hiệu năng
Tên biến
Quá trình “hardening” một dependency nghĩa là:
Gỡ bỏ tính năng không dùng, cấu hình an toàn nhất
Viết lại
Không dùng
Đổi tên
Dùng package từ nguồn không rõ trên registry (npm, PyPI) có nguy cơ:
Không sao, ai cũng dùng
Có thể bị cài mã độc, mất an toàn
Tăng tốc
Giảm kích thước
Khi app dùng framework cũ hết hỗ trợ (end-of-life), rủi ro là:
Không nhận cập nhật bảo mật mới
Nhanh hơn
Không cần bảo mật
Được hỗ trợ tốt hơn
DoS (Denial of Service) là:
Tấn công đánh cắp dữ liệu
Tấn công làm dịch vụ không thể phục vụ người dùng hợp lệ
Tấn công XSS
Tấn công SQLi
DDoS khác DoS ở chỗ:
DDoS đến từ nhiều nguồn/tác nhân phân tán
DDoS nhẹ hơn
DDoS chỉ xảy ra trên LAN
DDoS là lỗi phần mềm
Mục tiêu phổ biến của DDoS:
Tăng bảo mật
Làm cạn tài nguyên (CPU, RAM, băng thông) của server
Sửa dữ liệu
Lấy mật khẩu
“Rate limiting” là:
Giới hạn băng thông
Giới hạn số request từ một client trong khoảng thời gian
Giới hạn dung lượng DB
Giới hạn số file log
Rate limiting giúp:
Chống mọi DDoS
Giảm tác động của tấn công brute-force, spam request, DoS ở mức ứng dụng
Một chiến lược rate limiting đơn giản là:
Cho phép vô hạn request
Cho phép tối đa N request mỗi IP trong X giây
Cấm mọi request
Chỉ cho phép GET
Lý do IP-based rate limiting có hạn chế:
IP luôn 1-1 với user
NAT, proxy, VPN khiến nhiều user chung IP hoặc attacker dùng nhiều IP
Không đo được
Chỉ dùng cho HTTPS
“Application-level DoS” tấn công vào:
Hạ tầng mạng
Logic ứng dụng, sử dụng request hợp lệ nhưng đắt tài nguyên (ví dụ truy vấn rất nặng)
Firewall
Hệ điều hành
Một ví dụ phòng chống brute-force login bằng rate limiting:
Cho login vô hạn
Sau N lần sai, tạm khóa account/thêm delay/captcha
Không log
Không hash mật khẩu
Khi thiết kế API public, rate limiting nên:
Không dùng
Dựa trên API key, user, IP... kết hợp
Dựa trên màu giao diện
Dựa trên DB
Pattern để tạm ngừng gọi service downstream đang lỗi, tránh làm lan rộng sự cố
Không liên quan
Tăng băng thông
Tắt server
Tăng băng thông
Kết hợp cache và rate limiting giúp:
Giảm tải cho backend, chống DoS tốt hơn
Không liên quan
Tăng dung lượng
Giảm bảo mật
Ở tầng network, dịch vụ chống DDoS có thể:
Lọc traffic bất thường trước khi đến server
Mã hóa DB
Chạy JS
Lọc XSS
Logging request số lượng lớn bất thường giúp:
Phát hiện sớm DoS/DDoS
Tạo DoS
Chậm
Không hữu ích
Giới hạn kích thước body request giúp:
Chống tấn công upload file/corpous quá lớn gây DoS
Chỉ ảnh hưởng UI
Không cần
Chỉ đối với GET
Backend security tập trung vào:
Bảo vệ logic xử lý server và dữ liệu
Bảo vệ browser
Bảo vệ giao diện
Bảo vệ CSS
Một hệ thống bảo mật tốt thường:
Ẩn mọi lỗi, không log
Log chi tiết nội bộ, cung cấp thông báo chung cho người dùng
In stack trace ra màn hình
Không có lỗi
Error message như “syntax error near ' OR '1'='1'” cho user là:
Rất hữu ích cho attacker
Không sao
Cần thiết
Không liên quan
Nguyên tắc “defense in depth” nghĩa là:
Chỉ dùng một lớp bảo vệ
Nhiều lớp bảo vệ: validation, encoding, auth, logging, monitoring...
Không cần backup
Không cần rate limit
Dùng HTTPS trên backend API:
Không ảnh hưởng bảo mật
Bảo vệ dữ liệu khỏi bị nghe lén và sửa đổi trên đường truyền
Chỉ để SEO
Chỉ dùng cho trang login
Đối với mật khẩu, backend nên:
Lưu plaintext
Hash kèm salt với thuật toán mạnh (bcrypt, Argon2...)
Mã hóa reversible
Gửi email chứa mật khẩu định kỳ
Lỗi “Insecure Direct Object Reference (IDOR)” là:
Cho phép người dùng truy cập tài nguyên của người khác chỉ bằng đổi ID trong URL
Cho phép XSS
Cho phép SQLi
Cho phép CSRF
Để tránh IDOR, backend phải:
Tin ID người dùng gửi
Kiểm tra quyền truy cập dựa trên user hiện tại trước khi trả dữ liệu
Chỉ mã hóa ID
Dùng GET
Khi thiết kế API REST, nên tránh gửi dữ liệu nhạy cảm qua:
Body POST
Header Authorization
URL query và path (vì có thể bị log trong nhiều nơi)
HTTPS
Sử dụng “prepared statement” liên quan chủ yếu đến:
XSS
SQL injection
CSRF
DDoS
Để bảo vệ API khỏi abuse, ngoài rate limit còn có thể dùng:
API key, OAuth, quota, monitoring
Đổi port
Tắt HTTPS
Không log
Một lý do không nên trả về toàn bộ object user (bao gồm password hash, token) cho frontend là:
Tăng băng thông
Lộ thông tin nhạy cảm
Dễ bị lỗi
Tốn CPU
“Least privilege” với account ứng dụng nghĩa là:
User nào cũng quyền admin
Mỗi thành phần chỉ có quyền tối thiểu cần thiết
Không dùng phân quyền
Tất cả quyền root
Dùng ORM giúp:
Tự động chống mọi SQLi
Giảm nguy cơ SQLi nếu dùng API ORM đúng cách, nhưng vẫn có thể injection nếu dùng raw query
Không cần DB
Không cần validate
Khi triển khai log, cần chú ý:
Log mọi thứ kể cả mật khẩu
Không log gì
Log đủ để truy vết (ai, hành động gì, lúc nào, ở đâu) nhưng tránh dữ liệu nhạy cảm
Log chỉ trên client
Một cách để phát hiện tấn công tự động (bot) là:
Phân tích pattern request (tần suất, user agent, hành vi)
Không phân tích
Dựa vào màu nền
Dựa vào favicon
“Input tampering” là:
Người dùng sửa HTML
Attacker thay đổi dữ liệu gửi lên (ví dụ giá sản phẩm trong form, role...)
Không liên quan
Tắt JS
Để chống input tampering, backend phải:
Tin dữ liệu từ hidden input
Không dựa vào giá trị client gửi, luôn tính toán lại những thứ quan trọng trên server
Lưu giá trên client
Không check
Một hệ thống production cần cấu hình:
Chế độ debug ON, stack trace hiển thị
Tắt debug, log nội bộ, error page chung
Không log
Log ra console chỉ
Tại sao nên tách database server ra khỏi web server?
Khó deploy
Tăng bảo mật & khả năng mở rộng
Giảm hiệu năng
Không liên quan
“Security by obscurity” (chỉ dựa vào che giấu) là:
Cách tiếp cận chính thống
Không nên dùng như biện pháp chính, chỉ là lớp phụ thêm
An toàn tuyệt đối
Không cần thiết
Phần mềm quét lỗ hổng (vulnerability scanner) giúp:
Tự sửa lỗi
Phát hiện lỗi tiềm ẩn (SQLi, XSS, config...) cần dev xem xét xử lý
Tăng load
Tạo lỗi
Trong mô hình 3 lớp (presentation – logic – data), backend security chủ yếu nằm ở:
A. Presentation
B. Logic và data layer
C. Browser
Một API trả về dữ liệu theo page (pagination) giúp:
Giảm băng thông, giảm khả năng DoS qua request 1 lần lấy cực nhiều dữ liệu
Không liên quan bảo mật
Tăng tải
Không cần DB
“Secure coding practices” bao gồm:
Không cần review
Review code, dùng pattern an toàn, tránh anti-pattern (nối chuỗi SQL, eval...)
Chỉ viết nhanh
Chỉ test tính năng
Đưa secret (key, password DB) vào repo Git công khai là:
Bình thường
Rất nguy hiểm, phải rotate key và xóa khỏi lịch sử
Không sao vì Git an toàn
Chỉ ảnh hưởng hiệu năng
Môi trường “staging” dùng để:
Test tính năng & bảo mật gần giống production trước khi deploy thật
Chạy bản debug
Lưu log
Không cần
