AILapTrinh.comAI Lập Trình
An toàn mã nguồn và khoá bí mật

SQL injection trong mã AI viết: nhận ra câu truy vấn ghép chuỗi và sửa bằng tham số

Cách nhận ra truy vấn ghép chuỗi mà trợ lý AI hay viết, sửa bằng truy vấn tham số trong Python, PHP, JavaScript, và những chỗ tham số không che được.

Backend developer working late at a home desk in Can Tho, laptop and second monitor both blank, desk lamp casting warm light, hands on keyboard, view from the side

SQL injection xảy ra khi dữ liệu người dùng gửi lên được ghép thẳng vào câu SQL, khiến cơ sở dữ liệu hiểu một phần dữ liệu đó là lệnh. Cách chặn gần như triệt để là truy vấn tham số hoá: câu SQL và dữ liệu đi riêng, dữ liệu không bao giờ được đọc như lệnh. Trợ lý AI vẫn hay viết kiểu ghép chuỗi, nhất là khi bạn hỏi nhanh, dùng thư viện truy vấn thô, hoặc cần câu truy vấn có điều kiện động.

Bài này chỉ cách nhận ra kiểu ghép chuỗi trong ba ngôn ngữ phổ biến, cách viết lại bằng tham số, những phần của câu SQL mà tham số không che được và phải xử lý bằng danh sách cho phép, cùng câu lệnh mẫu để AI viết đúng ngay từ đầu. Bài viết hoàn toàn ở góc phòng thủ.

Vì sao trợ lý AI vẫn viết truy vấn ghép chuỗi

Kiểu ghép chuỗi có mặt dày đặc trong mã công khai, đặc biệt trong các bài hướng dẫn cũ và ví dụ ngắn nhằm minh hoạ một tính năng khác. Nó cũng là cách viết ngắn nhất, đọc vào hiểu ngay. Khi câu hỏi của bạn không nhắc gì tới bảo mật, mô hình có xu hướng chọn đúng kiểu ngắn gọn đó, nhất là trong các đoạn mã kiểu viết nhanh để thử.

Trường hợp hay dính nhất là truy vấn có điều kiện động: trang tìm kiếm có năm ô lọc, người dùng điền ô nào thì thêm điều kiện ô đó, cộng thêm sắp xếp theo cột người dùng chọn. AI hay xử lý bằng cách nối từng mảnh chuỗi, mỗi mảnh chứa thẳng giá trị từ biểu mẫu. Mã chạy đúng, kết quả lọc đúng, nên người thử không thấy vấn đề gì.

Trường hợp thứ hai là khi dự án dùng thư viện ánh xạ đối tượng nhưng gặp một câu phức tạp, AI chuyển sang hàm chạy SQL thô của thư viện đó và nhét biến vào bằng chuỗi định dạng. Nhiều người nghĩ đã dùng thư viện ánh xạ là an toàn, nhưng hàm SQL thô trong mọi thư viện đều trả trách nhiệm tham số hoá lại cho người viết.

Nhận ra và sửa trong ba ngôn ngữ

Bảng dưới đặt cạnh nhau kiểu viết nguy hiểm và kiểu viết đúng, mô tả bằng lời để bạn đối chiếu với mã của mình. Tên hàm và cú pháp là của thư viện chuẩn hoặc phổ biến; kiểm lại tài liệu phiên bản bạn đang dùng.

Ngôn ngữKiểu nguy hiểm khi đọc thấyKiểu đúng
Python với thư viện kết nối chuẩnCâu SQL viết bằng chuỗi f có biến trong ngoặc nhọn, hoặc nối bằng dấu cộng, rồi truyền một đối số duy nhất cho hàm executeViết câu có dấu giữ chỗ theo kiểu của trình điều khiển, ví dụ dấu chấm hỏi với sqlite3 hoặc %s với nhiều trình điều khiển MySQL và PostgreSQL, rồi truyền giá trị là đối số thứ hai dạng bộ giá trị
PHP với PDOGọi query với chuỗi có biến lấy từ mảng tham số yêu cầu được nối vào giữaGọi prepare với câu có dấu giữ chỗ dạng dấu hai chấm cộng tên, ví dụ :email, rồi execute với mảng giá trị; tắt chế độ giả lập chuẩn bị câu nếu dự án yêu cầu
JavaScript với trình điều khiển cơ sở dữ liệuChuỗi mẫu dùng dấu nháy ngược có biểu thức đô la ngoặc nhọn chèn giá trị yêu cầuTruyền câu có dấu giữ chỗ, như dấu chấm hỏi với trình điều khiển MySQL hoặc $1, $2 với trình điều khiển PostgreSQL, kèm mảng giá trị riêng

Có một bẫy với chuỗi định dạng trong Python: dấu %s trong câu SQL của nhiều trình điều khiển trông giống định dạng chuỗi thông thường. Viết câu rồi dùng toán tử phần trăm để chèn giá trị là ghép chuỗi; truyền giá trị làm đối số thứ hai của execute mới là tham số. Hai cách chỉ khác nhau một dấu phẩy và một dấu phần trăm, AI và người đều hay nhầm.

Với PHP, các hàm thoát chuỗi kiểu cũ không phải cách phòng chính: chúng phụ thuộc bảng mã kết nối và dễ quên ở một chỗ. Dùng câu chuẩn bị sẵn cho mọi truy vấn có giá trị từ ngoài.

Những phần câu SQL tham số không che được

Tên cột để sắp xếp. Dấu giữ chỗ chỉ thay được giá trị, không thay được tên cột hay tên bảng. Khi người dùng chọn sắp xếp theo cột nào, cách đúng là có một danh sách cột được phép, ví dụ giả định gồm ngày tạo, tên, giá, và ánh xạ lựa chọn của người dùng sang đúng một phần tử trong danh sách đó. Không khớp thì dùng cột mặc định.

Chiều sắp xếp. Tăng hay giảm cũng chỉ có hai giá trị hợp lệ. So với hai giá trị đó, không đưa chuỗi người dùng vào câu.

Danh sách giá trị trong mệnh đề IN. Không truyền cả danh sách thành một chuỗi. Sinh đúng số dấu giữ chỗ bằng số phần tử, rồi truyền các giá trị tương ứng. Nhớ xử lý trường hợp danh sách rỗng, vì câu IN rỗng là lỗi cú pháp ở nhiều hệ quản trị.

Giới hạn và vị trí phân trang. Nhiều trình điều khiển cho phép tham số ở LIMIT và OFFSET, một số thì không hoặc có cách xử lý riêng. Chắc nhất là ép kiểu thành số nguyên và đặt giới hạn trên, ví dụ không quá một trăm dòng mỗi trang.

Tìm kiếm có ký tự đại diện. Với LIKE, dấu phần trăm và gạch dưới do người dùng gõ cũng mang nghĩa đặc biệt. Ghép ký tự đại diện vào giá trị trước khi truyền làm tham số, và cân nhắc thoát hai ký tự đó nếu không muốn người dùng tự dùng chúng.

Sửa một hàm tìm kiếm ghép chuỗi do AI viết

Ví dụ giả định: hàm tìm đơn hàng nhận từ khoá, trạng thái, cột sắp xếp và số trang, đang ghép tất cả vào chuỗi. Các bước sửa theo thứ tự ít rủi ro nhất.

  1. Viết một kiểm thử ghi lại kết quả hiện tại của hàm với vài bộ tham số bình thường, để biết khi sửa xong kết quả không đổi.
  2. Tách câu thành phần cố định và danh sách điều kiện. Mỗi điều kiện là một cặp: mảnh câu có dấu giữ chỗ và giá trị đi kèm. Chỉ thêm cặp khi người dùng có điền ô đó.
  3. Nối các mảnh câu bằng AND, gom các giá trị theo đúng thứ tự vào một danh sách tham số.
  4. Thay phần sắp xếp bằng tra danh sách cột được phép và hai chiều tăng giảm như mục trên.
  5. Ép số trang và kích thước trang về số nguyên, đặt giới hạn trên.
  6. Chạy lại kiểm thử ở bước đầu, rồi thêm ca kiểm với từ khoá chứa dấu nháy đơn, dấu chấm phẩy và chữ có dấu tiếng Việt để chắc hàm xử lý như dữ liệu bình thường.
  7. Rà lại xem còn chỗ nào trong tệp dùng ghép chuỗi với dữ liệu từ ngoài, kể cả trong hàm phụ.

Điểm mấu chốt của bước hai: mảnh câu chỉ chứa chữ do lập trình viên viết, giá trị luôn đi đường riêng. Nếu ở bất kỳ đâu một chuỗi đến từ người dùng chạm vào mảnh câu, cấu trúc đó đã hỏng.

Câu lệnh mẫu để AI viết đúng ngay từ đầu

Thay vì sửa sau, bạn đặt ràng buộc ngay trong yêu cầu. Câu lệnh mẫu: “Viết hàm Python dùng trình điều khiển PostgreSQL đang có trong dự án để tìm đơn hàng theo từ khoá, trạng thái và khoảng ngày, mỗi điều kiện là tuỳ chọn. Bắt buộc dùng truy vấn tham số cho mọi giá trị, không dùng chuỗi f hay toán tử phần trăm để chèn giá trị. Cột sắp xếp chỉ nhận một trong ba giá trị cho trước, không khớp thì dùng ngày tạo. Viết kèm ba ca kiểm thử, trong đó có một ca từ khoá chứa dấu nháy đơn.”

Câu lệnh trên làm ba việc: nêu thư viện cụ thể để AI không đổi sang thư viện khác, cấm rõ kiểu viết nguy hiểm, và yêu cầu kiểm thử có ca dữ liệu đặc biệt. Ca dấu nháy đơn là ca thử đơn giản mà hiệu quả: hàm ghép chuỗi sẽ lỗi cú pháp ngay, hàm tham số hoá thì chạy bình thường.

Khi nhận mã về, đừng chỉ tin câu “đã dùng truy vấn tham số” trong lời giải thích của AI. Mở mã ra, tìm mọi lời gọi thực thi câu SQL, xem đối số thứ hai có phải danh sách giá trị hay không. Lời giải thích và mã thật đôi khi không khớp nhau.

Lớp phòng thủ thêm ngoài truy vấn tham số

Truy vấn tham số là lớp chính. Các lớp dưới không thay được nó nhưng giảm thiệt hại nếu có chỗ sót.

  • Tài khoản cơ sở dữ liệu của ứng dụng chỉ có quyền cần thiết: ứng dụng chỉ đọc báo cáo thì không cần quyền xoá bảng.
  • Tắt hiển thị lỗi SQL chi tiết cho người dùng; ghi vào nhật ký nội bộ để lập trình viên đọc.
  • Kiểm đầu vào theo kiểu và khoảng giá trị trước khi tới tầng truy vấn: mã đơn là số nguyên dương, ngày đúng định dạng, trạng thái thuộc danh sách.
  • Thêm quy tắc vào công cụ quét tĩnh hoặc bộ kiểm tra mã của dự án để báo khi thấy chuỗi định dạng đi vào hàm thực thi truy vấn.
  • Ghi quy ước “mọi giá trị đi vào SQL phải qua tham số” vào tệp hướng dẫn dự án cho AI và vào danh sách rà yêu cầu gộp mã.

Với cơ sở dữ liệu có dữ liệu khách hàng, khi đưa câu truy vấn hay lược đồ bảng cho AI xem, chỉ đưa cấu trúc và dữ liệu mẫu giả. Không dán bản sao dữ liệu thật, dù chỉ vài dòng.

Thư viện ánh xạ đối tượng có tự động an toàn không

Phần lớn thư viện ánh xạ đối tượng và bộ dựng truy vấn tham số hoá giá trị khi bạn dùng các phương thức lọc chuẩn của chúng. Đó là lý do nhiều nhóm khuyên dùng chúng cho mã thông thường. Nhưng mỗi thư viện đều có lối thoát để chạy SQL thô, đặt điều kiện bằng chuỗi, hoặc truyền tên cột từ biến. Ở những lối thoát đó, trách nhiệm quay về người viết.

Khi rà mã AI viết có dùng thư viện ánh xạ, tìm các chữ như raw, query thô, hay các hàm nhận một chuỗi điều kiện. Nhìn xem chuỗi đó có chứa giá trị từ ngoài được chèn vào không. Một đoạn mã dùng thư viện ánh xạ chín mươi phần trăm và SQL thô mười phần trăm thì mười phần trăm đó cần được đọc kỹ nhất.

Thêm một chỗ hay bị bỏ qua: tham số sắp xếp hoặc chọn trường trả về trong các giao diện lập trình tự động sinh từ mô hình dữ liệu. Nếu người dùng truyền được tên trường tuỳ ý, hãy giới hạn bằng danh sách cho phép giống như với SQL viết tay.

Câu hỏi thường gặp

Đã kiểm đầu vào rồi thì có cần truy vấn tham số nữa không?

Vẫn cần. Kiểm đầu vào giúp loại dữ liệu sai kiểu, nhưng rất khó liệt kê hết ký tự nguy hiểm, và chỉ cần một chỗ quên kiểm là hở. Truy vấn tham số tách hẳn dữ liệu khỏi lệnh nên không phụ thuộc vào việc bạn đoán đúng ký tự nào nguy hiểm.

Thủ tục lưu sẵn trong cơ sở dữ liệu có chống được SQL injection không?

Chỉ khi gọi thủ tục bằng tham số và bên trong thủ tục không tự ghép chuỗi rồi thực thi động. Thủ tục có câu SQL động ghép từ đối số vẫn mắc đúng lỗi này, chỉ là chuyển chỗ từ ứng dụng sang cơ sở dữ liệu.

Ứng dụng nội bộ chỉ nhân viên dùng thì có cần lo không?

Có. Tài khoản nhân viên có thể bị chiếm, đường dẫn nội bộ có thể vô tình mở ra ngoài, và lỗi ghép chuỗi còn làm hỏng dữ liệu khi ai đó nhập tên có dấu nháy đơn. Sửa bằng tham số không tốn thêm công so với viết đúng từ đầu.

Làm sao kiểm nhanh cả dự án còn chỗ ghép chuỗi SQL không?

Tìm toàn bộ lời gọi hàm thực thi truy vấn rồi xem đối số đầu có chứa chuỗi định dạng, phép nối hay chuỗi mẫu có biến không. Công cụ quét tĩnh có quy tắc cho việc này ở nhiều ngôn ngữ. Có thể nhờ AI liệt kê các chỗ nghi vấn, nhưng tự mở từng chỗ để xác nhận.

Truy vấn tham số có làm chậm ứng dụng không?

Với ứng dụng thông thường, khác biệt hiệu năng không đáng kể, và có trường hợp còn nhanh hơn vì cơ sở dữ liệu dùng lại kế hoạch thực thi. Nếu nghi ngờ, đo trên dữ liệu của bạn thay vì đoán.

AI nói mã đã an toàn, có tin được không?

Không nên tin lời tự nhận. Mở mã và tự kiểm lời gọi thực thi truy vấn, thêm ca kiểm thử với dấu nháy đơn trong dữ liệu. Lời giải thích của AI và mã nó viết đôi khi không khớp nhau.

Cần tư vấn cụ thể cho trường hợp của bạn?

Chúng tôi sẽ liên hệ trong vòng 24 giờ.

Đăng ký tư vấn ngay

Bài viết liên quan

Bạn cần hỗ trợ thêm?

Để lại thông tin, chúng tôi sẽ liên hệ trong 24 giờ.

hoặc
Gọi ngay 0926 138 138