Ngôn ngữ truy vấn có cấu trúc (SQL) là ngôn ngữ được thiết kế để thao tác và quản lý dữ liệu trong cơ sở dữ liệu. Kể từ khi thành lập, SQL đã dần dần thâm nhập vào nhiều cơ sở dữ liệu mã nguồn mở và thương mại. SQL injection (SQLi) một dạng tấn công an ninh mạng với mục tiêu vào database này bằng cách sử dụng các truy vấn SQL đặc biệt để khai thác hệ thống làm những công việc đặc biệt.
Các bài viết liên quan:
Nếu bạn có ít hơn năm phút, hãy tìm hiểu về các cuộc tấn công SQL Injection trong video này:
Các hành động mà kẻ tấn công thành công có thể thực hiện nhằm vào một mục tiêu bị xâm nhập bao gồm:
- Bypassing authentication
- Exfiltrating/stealing data
- Modifying or corrupting data
- Deleting data
- Running arbitrary code
- Gaining root access to the system itself
SQL injection nguy hiểm như thế nào?
Nếu hoàn tất thành công, việc tiêm SQL có khả năng gây bất lợi cho bất kỳ doanh nghiệp hoặc cá nhân nào. Một khi dữ liệu nhạy cảm bị xâm phạm trong một cuộc tấn công, rất khó để khôi phục hoàn toàn.
Cơ sở dữ liệu thường được nhắm mục tiêu để đưa vào thông qua một ứng dụng (chẳng hạn như trang web, yêu cầu đầu vào của người dùng và sau đó thực hiện tra cứu trong cơ sở dữ liệu dựa trên đầu vào đó), nhưng chúng cũng có thể được nhắm mục tiêu trực tiếp. Các cuộc tấn công SQL injection là trong top 10 OWASP, lỗ hổng bảo mật hàng đầu.
Các kiểu tấn công SQL injection
Các cuộc tấn công SQL injection có thể được thực hiện theo một số cách. Những kẻ tấn công có thể quan sát hành vi của hệ thống trước khi chọn một vectơ / phương thức tấn công cụ thể.
- Xử lý dữ liệu đầu vào
Đầu vào không được vệ sinh là một kiểu tấn công SQLi phổ biến trong đó kẻ tấn công cung cấp thông tin đầu vào của người dùng không được khử trùng đúng cách cho các ký tự cần được thoát và / hoặc đầu vào không được xác thực là loại chính xác / mong đợi.
Ví dụ: một trang web được sử dụng để thanh toán hóa đơn trực tuyến có thể yêu cầu số tài khoản của người dùng trong một biểu mẫu web, sau đó gửi số đó đến cơ sở dữ liệu để lấy thông tin tài khoản được liên kết. Nếu ứng dụng web đang tạo một chuỗi truy vấn SQL động với số tài khoản mà người dùng đã cung cấp, nó có thể trông giống như sau:
“SELECT * FROM customers WHERE account = ‘“+ userProvidedAccountNumber +”’;”
Mặc dù điều này hoạt động đối với những người dùng nhập đúng số tài khoản của họ, nhưng nó vẫn mở ra cánh cửa cho những kẻ tấn công. Ví dụ: nếu ai đó quyết định cung cấp số tài khoản là “‘ hoặc ‘1’ = ‘1”, điều đó sẽ dẫn đến một chuỗi truy vấn là:
“SELECT * FROM customers WHERE account = ‘’ or ‘1’ = ‘1’;”
Do ‘1’ = ‘1’ luôn đánh giá là ĐÚNG, việc gửi câu lệnh này đến cơ sở dữ liệu sẽ dẫn đến việc dữ liệu của tất cả khách hàng được trả về thay vì chỉ một khách hàng duy nhất.
- Blind SQL Injection
Còn được gọi là Injection SQL Inferential, một cuộc tấn công Blind SQL injection không tiết lộ dữ liệu trực tiếp từ cơ sở dữ liệu đang được nhắm mục tiêu. Đúng hơn, kẻ tấn công kiểm tra chặt chẽ các manh mối gián tiếp trong hành vi. Thông tin chi tiết về phản hồi HTTP, các trang web trống cho một số thông tin nhập của người dùng nhất định và cơ sở dữ liệu mất bao lâu để phản hồi một số thông tin nhập của người dùng là tất cả những thứ có thể là manh mối tùy thuộc vào mục tiêu của kẻ tấn công. Họ cũng có thể trỏ đến một đại lộ tấn công SQLi khác để kẻ tấn công thử.
- Out-of-Band Injection
Cuộc tấn công này phức tạp hơn một chút và có thể được kẻ tấn công sử dụng khi chúng không thể đạt được mục tiêu của mình trong một cuộc tấn công phản hồi truy vấn trực tiếp, duy nhất. Thông thường, kẻ tấn công sẽ tạo ra các câu lệnh SQL, khi được trình bày với cơ sở dữ liệu, sẽ kích hoạt hệ thống cơ sở dữ liệu để tạo kết nối với một máy chủ bên ngoài mà kẻ tấn công kiểm soát. Theo cách này, kẻ tấn công có thể thu thập dữ liệu hoặc có khả năng kiểm soát hành vi của cơ sở dữ liệu.
Lệnh injection thứ 2 là một kiểu tấn công Out-of-Band Injection attack. Trong trường hợp này, kẻ tấn công sẽ cung cấp một SQL injection sẽ được lưu trữ và thực thi bởi một hành vi riêng biệt của hệ thống cơ sở dữ liệu. Khi hành vi của hệ thống thứ cấp xảy ra (nó có thể là công việc dựa trên thời gian hoặc thứ gì đó được kích hoạt bởi quản trị viên hoặc người dùng thông thường khác sử dụng cơ sở dữ liệu) và việc tiêm SQL của kẻ tấn công được thực thi, đó là khi “tiếp cận” với hệ thống điều khiển kẻ tấn công xảy ra.
Ví dụ về SQL Injection
Đối với ví dụ chèn SQL này, hãy sử dụng hai bảng cơ sở dữ liệu, Người dùng và Danh bạ. Bảng Người dùng có thể đơn giản như chỉ có ba trường: ID, tên người dùng và mật khẩu. Bảng Danh bạ có thêm thông tin về người dùng, chẳng hạn như UserID, FirstName, LastName, Address1, Email, số thẻ tín dụng và mã bảo mật.
Bảng Người dùng có thông tin được sử dụng cho đăng nhập như:
- jsmith, P @ $$ w0rd
- sbrown, WinterIsComing!
- kcharles, Sup3rSecur3Password $
Lưu ý: Mật khẩu phải luôn được băm và ướp muối khi được lưu trữ trong cơ sở dữ liệu và không bao giờ ở dạng văn bản rõ ràng.
Khi ai đó muốn đăng nhập, họ sẽ truy cập trang đăng nhập và nhập tên người dùng và mật khẩu của họ. Thông tin này sau đó được gửi đến máy chủ web, máy chủ này sẽ tạo một truy vấn SQL và gửi truy vấn đó đến máy chủ cơ sở dữ liệu. Ví dụ về truy vấn đó trông như thế nào có thể là:
Select ID from Users where username=’jsmith’ and password=’P@$$w0rd’
Cách thức hoạt động của SQL là sau đó nó sẽ thực hiện so sánh đúng hoặc sai cho mỗi hàng mà truy vấn yêu cầu. Trong ví dụ của chúng tôi, truy vấn cho biết hãy kiểm tra bảng Người dùng và trả lại giá trị ID cho mọi hàng có tên người dùng là jsmith và mật khẩu là P @ $$ w0rd. Thông thường, máy chủ web sau đó sẽ xem những gì được máy chủ cơ sở dữ liệu trả về và nó có phải là một số hay không. Trong trường hợp của chúng tôi, máy chủ web sẽ nhận lại 1 và cho phép người dùng qua trang đăng nhập.
Nhưng, nếu chúng ta muốn có ác ý với điều này thì sao? Bởi vì máy chủ cơ sở dữ liệu thực hiện kiểm tra đúng-sai đó, chúng tôi có thể đánh lừa nó tin rằng chúng tôi đã xác thực thành công. Chúng tôi có thể làm điều này bằng cách thêm HOẶC vào mật khẩu. Nếu chúng tôi đăng nhập
với x ’hoặc 1 = 1 làm mật khẩu của chúng tôi, điều đó sẽ tạo ra một truy vấn SQL mới trông giống như sau:
Chọn ID từ Người dùng có tên người dùng = ’jsmith’ và password= ’x’ hoặc 1 = 1
Điều này sẽ hiệu quả với chúng tôi, bởi vì trong khi x không phải là mật khẩu của jsmith, thì máy chủ cơ sở dữ liệu sẽ kiểm tra điều kiện thứ hai. Nếu x không phải là mật khẩu của jsmith, thì 1 có bằng 1 không? Nó có! ID sẽ được gửi trở lại ứng dụng và người dùng sẽ được xác thực thành công.
Đây không nhất thiết phải là điều kiện 1 = 1. Hai giá trị bằng nhau bất kỳ sẽ hoạt động, 2 = 2, 4726 = 4726 hoặc thậm chí a = a.
Nếu một trang web có khả năng hiển thị dữ liệu, nó cũng có thể in thêm dữ liệu ra màn hình. Để truy cập dữ liệu, chúng ta có thể cố gắng xâu chuỗi hai yêu cầu SQL lại với nhau. Ngoài ‘hoặc 1 = 1 của chúng tôi, chúng tôi có thể thêm vào đó một câu lệnh thứ hai như UNION SELECT LastName, số thẻ tín dụng, mã bảo mật từ Danh bạ. Các mệnh đề bổ sung như thế này có thể mất thêm một số công việc, nhưng có được quyền truy cập vào dữ liệu là mục tiêu cuối cùng của một cuộc tấn công SQL injection.
Một kỹ thuật khác mà chúng ta có thể sử dụng để tiêm SQL mù, một kỹ thuật mà không có dữ liệu nào được gửi trở lại màn hình là đưa các gợi ý khác vào. Tương tự như điều kiện ‘hoặc 1 = 1 của chúng tôi, chúng tôi có thể yêu cầu máy chủ chuyển sang chế độ ngủ. Chúng ta có thể thêm: “‘ or sleep (10) ”và điều này sẽ thực hiện những gì có vẻ như. Nó sẽ yêu cầu máy chủ cơ sở dữ liệu chợp mắt 10 giây và tất cả các phản hồi sẽ bị trì hoãn.
Cách ngăn chặn các cuộc tấn công đưa vào SQL
Các đề xuất sau có thể giúp ngăn chặn tấn công SQL injection thành công:
- Không sử dụng SQL động
- Tránh đặt đầu vào do người dùng cung cấp trực tiếp vào các câu lệnh SQL.
- Ưu tiên các câu lệnh được chuẩn bị sẵn và các truy vấn được tham số hóa, an toàn hơn nhiều.
- Các thủ tục được lưu trữ cũng thường an toàn hơn so với SQL động.
- Vệ sinh đầu vào do người dùng cung cấp
- Lọc các ký tự không phù hợp.
- Xác minh rằng loại dữ liệu được gửi phù hợp với loại dự kiến.
- Đừng để dữ liệu nhạy cảm ở dạng bản rõ
- Mã hóa dữ liệu riêng tư / bí mật đang được lưu trữ trong cơ sở dữ liệu.
- Muối các băm được mã hóa.
- Điều này cũng cung cấp một mức độ bảo vệ khác trong trường hợp kẻ tấn công lấy cắp dữ liệu nhạy cảm thành công.
- Giới hạn quyền và đặc quyền cơ sở dữ liệu
Đặt khả năng của người dùng cơ sở dữ liệu ở mức tối thiểu cần thiết.
Điều này sẽ hạn chế những gì kẻ tấn công có thể làm nếu chúng có được quyền truy cập.
- Tránh hiển thị lỗi cơ sở dữ liệu trực tiếp cho người dùng
Những kẻ tấn công có thể sử dụng các thông báo lỗi này để lấy thông tin về cơ sở dữ liệu.
- Sử dụng Tường lửa Ứng dụng Web (WAF) cho các ứng dụng web truy cập cơ sở dữ liệu
Điều này cung cấp sự bảo vệ cho các ứng dụng chạy trên web.
Nó có thể giúp xác định các nỗ lực chèn SQL.
Dựa trên thiết lập, nó cũng có thể giúp ngăn chặn các nỗ lực chèn SQL vào ứng dụng (và do đó, cơ sở dữ liệu).
- Sử dụng giải pháp kiểm tra bảo mật ứng dụng web để kiểm tra thường xuyên các ứng dụng web tương tác với cơ sở dữ liệu
Làm như vậy có thể giúp bắt lỗi hoặc hồi quy mới có thể cho phép đưa vào SQL.
- Luôn cập nhật cơ sở dữ liệu lên các bản vá mới nhất hiện có
Điều này ngăn những kẻ tấn công khai thác các điểm yếu / lỗi đã biết có trong các phiên bản cũ hơn.
SQL injection là một phương pháp tấn công phổ biến đối với kẻ thù, nhưng bằng cách thực hiện các biện pháp phòng ngừa thích hợp như đảm bảo dữ liệu được mã hóa, bạn bảo vệ và kiểm tra các ứng dụng web của mình và cập nhật các bản vá lỗi, bạn có thể thực hiện các bước có ý nghĩa để duy trì dữ liệu của bạn an toàn.
Cách kiểm tra SQL injection
- Kiểm tra lỗ hổng bảo mật SQL Injection
- Kiểm tra lỗ hổng bảo mật SQL injection trong SQL Server
- Kiểm tra lỗ hổng bảo mật SQL injection cho MS Access
- Kiểm tra lỗ hổng bảo mật SQL injection trong PostgreSQL
- Kiểm tra lỗ hổng SQL injection trong MySQL
- Kiểm tra lỗ hổng SQL injection cho Oracle database
- Kiểm tra lỗ hổng bảo mật ORM Injection
- Kiểm tra lỗ hổng bảo mật SQL injection Client-side