SQL injection là lỗ hổng khi input của user được nối chuỗi thẳng vào câu SQL, khiến dữ liệu bị thực thi như code:
-- Code ghép chuỗi: query = "SELECT * FROM users WHERE name = '" + input + "'"
-- Input: ' OR '1'='1
SELECT * FROM users WHERE name = '' OR '1'='1'; -- trả về mọi user
-- Input: '; DROP TABLE users; -- → chạy lệnh phá hoạiHậu quả: lộ dữ liệu (bypass đăng nhập, đọc bảng khác qua UNION SELECT), sửa/xóa dữ liệu, có khi chiếm cả server.
Parameterized query (prepared statement) chặn được vì tách cấu trúc SQL khỏi dữ liệu: câu lệnh với placeholder được gửi và parse trước, giá trị được gửi riêng như dữ liệu thuần — DB không bao giờ parse lại giá trị thành SQL. Chuỗi ' OR '1'='1 chỉ là một chuỗi tên kỳ lạ, không phải điều kiện:
SELECT * FROM users WHERE name = $1; -- $1 truyền riêng, luôn là dữ liệuLưu ý thêm:
- Escape thủ công không đủ tin cậy — dễ sót case (encoding, kiểu số); OWASP xếp parameterized query là phòng thủ số 1.
- ORM/query builder (Prisma, TypeORM...) mặc định parameterize — nhưng raw query nối chuỗi vẫn dính ($queryRawUnsafe với template tự ghép).
- Tên bảng/cột không parameterize được — nếu phải động, dùng allowlist.
- Phòng thủ bổ sung: least privilege cho DB user, validate input, không lộ lỗi SQL ra response.