SQL Injection

SQL Injection

SQL injection là gì?

SQL Injection (SQLi) là một lỗ hổng bảo mật web cho phép kẻ tấn công can thiệp vào các truy vấn mà ứng dụng thực hiện đối với cơ sở dữ liệu của nó. Nó thường cho phép kẻ tấn công xem dữ liệu mà thông thường chúng không thể truy xuất được. Điều này có thể bao gồm dữ liệu thuộc về người dùng hoặc bất kỳ dữ liệu nào khác mà bản thân ứng dụng có thể truy cập. Trong nhiều trường hợp, kẻ tấn công có thể sửa đổi hoặc xóa dữ liệu này, gây ra những thay đổi dữ liệu hoặc hành vi của ứng dụng.

Trong một số trường hợp, kẻ tấn công có thể xâm phạm máy chủ hoặc cơ sở hạ tầng phụ trợ khác hoặc thực hiện một cuộc tấn công từ chối dịch vụ.

Rủi do của SQL Injection

Việc tấn công vào lỗ hổng bảo mật bằng SQL injection thành công có thể dẫn đến việc truy cập trái phép vào dữ liệu nhạy cảm, chẳng hạn như mật khẩu, chi tiết thẻ tín dụng hoặc thông tin người dùng cá nhân. Nhiều vụ vi phạm dữ liệu nổi bật trong những năm gần đây là kết quả của các cuộc tấn công bảo mật, dẫn đến thiệt hại về mặt danh dự, tài sản ....

Cách phát hiện lỗ hổng

Phần lớn các lỗ hổng SQL injection có thể được tìm thấy nhanh chóng và đáng tin cậy bằng cách sử dụng trình quét lỗ hổng web có sẵn trên ineternet

SQL injection có thể được phát hiện theo cách thủ công bằng cách sử dụng một bộ thử nghiệm có hệ thống đối với mọi điểm vào trong ứng dụng. Điều này thường bao gồm:

  • Gửi ký tự trích dẫn đơn ' và tìm kiếm lỗi hoặc các điểm bất thường khác.
  • Gửi một số cú pháp dành riêng cho SQL để đánh giá giá trị cơ sở (gốc) của điểm nhập và một giá trị khác, đồng thời tìm kiếm sự khác biệt mang tính hệ thống trong các phản hồi của ứng dụng thu được.
  • Gửi các điều kiện Boolean như OR 1=1 và OR 1=2 và tìm kiếm sự khác biệt trong phản hồi của ứng dụng.
  • Gửi tải trọng được thiết kế để kích hoạt độ trễ thời gian khi được thực thi trong truy vấn SQL và tìm kiếm sự khác biệt về thời gian cần thiết để phản hồi.
  • Gửi tải trọng OAST được thiết kế để kích hoạt tương tác mạng ngoài băng tần khi được thực thi trong truy vấn SQL và giám sát mọi tương tác phát sinh.

Chèn SQL vào các phần khác nhau của truy vấn

Hầu hết các lỗ hổng SQL injection đều phát sinh trong mệnh đề WHERE của truy vấn SELECT.

Nhưng về nguyên tắc, các lỗ hổng SQL injection có thể xảy ra ở bất kỳ vị trí nào trong truy vấn và trong các loại truy vấn khác nhau. Các vị trí phổ biến nhất là:

  • Trong UPDATE: trong các giá trị được cập nhật hoặc WHERE.
  • Trong INSERT: trong các giá trị được chèn.
  • Trong SELECT: trong tên bảng hoặc cột.
  • Trong SELECT: trong ORDER BY.

Ví dụ về chèn SQL

Có rất nhiều lỗ hổng, cuộc tấn công và kỹ thuật SQL injection phát sinh trong các tình huống khác nhau. Một số ví dụ về SQL injection phổ biến bao gồm:

  • Truy xuất dữ liệu ẩn: nơi bạn có thể sửa đổi truy vấn SQL để trả về kết quả bổ sung.
  • Phá vỡ logic ứng dụng: trong đó bạn có thể thay đổi một truy vấn để can thiệp vào logic của ứng dụng.
  • Lấy dữ liệu từ các bảng cơ sở dữ liệu khác: nơi bạn có thể truy xuất dữ liệu từ các bảng cơ sở dữ liệu khác nhau.
  • Tính năng chèn SQL mù: trong đó kết quả của truy vấn bạn kiểm soát không được trả về trong phản hồi của ứng dụng.

Truy xuất dữ liệu ẩn (Retrieving hidden data)

Hãy xem xét một ứng dụng mua sắm hiển thị các sản phẩm theo các danh mục khác nhau. Khi người dùng nhấp vào danh mục Quà tặng, trình duyệt của họ sẽ yêu cầu URL:

https://insecure-website.com/products?category=Gifts

Điều này khiến ứng dụng tạo truy vấn SQL để truy xuất thông tin chi tiết về các sản phẩm có liên quan từ cơ sở dữ liệu:

SELECT * FROM products WHERE category = 'Gifts' AND released = 1

Truy vấn SQL này yêu cầu cơ sở dữ liệu trả về:

  • tất cả trường thông tin (*)
  • từ bảng products
  • trong đó danh mục category  là 'Gifts'
  • và phát hành là 1.

Điều kiện  released = 1 đang được sử dụng để ẩn các sản phẩm không được phát hành. Đối với các sản phẩm chưa được phát hành, có lẽ là released = 0.

Ứng dụng không triển khai bất kỳ biện pháp phòng vệ nào chống lại các cuộc tấn công SQL injection, vì vậy kẻ tấn công có thể xây dựng một cuộc tấn công như:

https://insecure-website.com/products?category=Gifts'--

Điều này tương ứng với truy vấn SQL:

SELECT * FROM products WHERE category = 'Gifts'--' AND released = 1

Điều quan trọng ở đây là chuỗi dấu gạch ngang kép – là một chỉ báo nhận xét trong SQL và có nghĩa là phần còn lại của truy vấn được hiểu là một nhận xét. Điều này sẽ loại bỏ phần điều kiện còn lại của truy vấn, do đó nó không còn bao gồm AND released = 1. Điều này có nghĩa là tất cả các sản phẩm đều được hiển thị, kể cả những sản phẩm chưa được phát hành.

Đi xa hơn, kẻ tấn công có thể khiến ứng dụng hiển thị tất cả các sản phẩm thuộc bất kỳ danh mục nào, bao gồm cả các danh mục mà chúng không biết:

https://insecure-website.com/products?category=Gifts'+OR+1=1--

Điều này tương ứng với truy vấn SQL:

SELECT * FROM products WHERE category = 'Gifts' OR 1=1--' AND released = 1

Truy vấn đã sửa đổi sẽ trả về tất cả các mục trong đó category  là 'Gifts'  hoặc 1=1. Vì 1=1 luôn đúng nên truy vấn sẽ trả về tất cả các mục.

Cảnh báo

Hãy cẩn thận khi đưa điều kiện OR 1=1vào truy vấn SQL. Mặc dù điều này có thể vô hại trong ngữ cảnh ban đầu mà bạn đưa vào, nhưng thông thường các ứng dụng sẽ sử dụng dữ liệu từ một yêu cầu trong nhiều truy vấn khác nhau. Ví dụ: nếu điều kiện của bạn đạt đến câu lệnh UPDATE hoặc DELETE, điều này có thể dẫn đến việc vô tình mất dữ liệu.

Phá vỡ logic ứng dụng (Subverting application logic)

Hãy xem xét một ứng dụng cho phép người dùng đăng nhập bằng tên người dùng và mật khẩu. Nếu người dùng gửi tên người dùng wiener và mật khẩu bluecheese, ứng dụng sẽ kiểm tra thông tin xác thực bằng cách thực hiện truy vấn SQL sau:

SELECT * FROM users WHERE username = 'wiener' AND password = 'bluecheese'

Nếu truy vấn trả về thông tin chi tiết của người dùng thì đăng nhập thành công. Nếu không, nó sẽ bị từ chối.

Tại đây, kẻ tấn công có thể đăng nhập với tư cách bất kỳ người dùng nào mà không cần mật khẩu chỉ bằng cách sử dụng chỗi comment SQL – để xóa kiểm tra mật khẩu khỏi mệnh đề WHERE của truy vấn. Ví dụ: gửi tên người dùng administrator'--và mật khẩu trống sẽ dẫn đến truy vấn sau:

SELECT * FROM users WHERE username = 'administrator'--' AND password = ''

Truy vấn này trả về người dùng có tên người dùng administrator và đăng nhập thành công kẻ tấn công với tư cách là người dùng đó.

Lấy dữ liệu từ các bảng cơ sở dữ liệu khác (Retrieving data from other database tables)

Trong trường hợp kết quả của truy vấn SQL được trả về trong phản hồi của ứng dụng, kẻ tấn công có thể lợi dụng lỗ hổng chèn SQL để lấy dữ liệu từ các bảng khác trong cơ sở dữ liệu. Điều này được thực hiện bằng cách sử dụng từ khóa UNION, cho phép bạn thực hiện một truy vấn SELECT bổ sung và nối các kết quả vào truy vấn ban đầu.

Ví dụ: nếu một ứng dụng thực hiện truy vấn sau có chứa "Gifts" do người dùng nhập:

SELECT name, description FROM products WHERE category = 'Gifts'

sau đó kẻ tấn công có thể gửi đầu vào:

' UNION SELECT username, password FROM users--

Điều này sẽ khiến ứng dụng trả về tất cả tên người dùng và mật khẩu cùng với tên và mô tả sản phẩm.

Blind SQL injection

Nhiều trường hợp SQL injection là những lỗ hổng mù quáng. Điều này có nghĩa là ứng dụng không trả về kết quả của truy vấn SQL hoặc chi tiết về bất kỳ lỗi cơ sở dữ liệu nào trong các phản hồi của nó. Các lỗ hổng ẩn vẫn có thể bị khai thác để truy cập dữ liệu trái phép, nhưng các kỹ thuật liên quan thường phức tạp và khó thực hiện hơn.

Tùy thuộc vào bản chất của lỗ hổng bảo mật và cơ sở dữ liệu liên quan, các kỹ thuật sau có thể được sử dụng để khai thác lỗ hổng chèn SQL mù:

  • Bạn có thể thay đổi logic của truy vấn để kích hoạt sự khác biệt có thể phát hiện được trong phản hồi của ứng dụng tùy thuộc vào mức độ thực tế của một điều kiện. Điều này có thể liên quan đến việc đưa một điều kiện mới vào logic Boolean nào đó hoặc gây ra một lỗi có điều kiện, chẳng hạn như lỗi chia cho 0.
  • Bạn có thể kích hoạt một cách có điều kiện độ trễ thời gian trong quá trình xử lý truy vấn, cho phép bạn suy ra tính chân thực của điều kiện dựa trên thời gian mà ứng dụng cần để phản hồi.
  • Bạn có thể kích hoạt tương tác mạng ngoài băng tần bằng cách sử dụng kỹ thuật OAST. Kỹ thuật này cực kỳ mạnh mẽ và hoạt động trong những tình huống mà các kỹ thuật khác không làm được. Thông thường, bạn có thể lọc trực tiếp dữ liệu qua kênh ngoài băng tần, chẳng hạn như bằng cách đặt dữ liệu vào tra cứu DNS cho miền mà bạn kiểm soát.

SQL injection bậc hai (Second-order SQL injection)

Việc chèn SQL bậc nhất phát sinh khi ứng dụng lấy đầu vào của người dùng từ một yêu cầu HTTP và trong quá trình xử lý yêu cầu đó, kết hợp đầu vào đó vào truy vấn SQL theo cách không an toàn.

Trong SQL injection bậc hai, ứng dụng lấy đầu vào của người dùng từ một yêu cầu HTTP và lưu trữ nó để sử dụng trong tương lai. Điều này thường được thực hiện bằng cách đặt dữ liệu đầu vào vào cơ sở dữ liệu, nhưng không có lỗ hổng nào phát sinh tại điểm lưu trữ dữ liệu. Sau đó, khi xử lý một yêu cầu HTTP khác, ứng dụng sẽ truy xuất dữ liệu được lưu trữ và kết hợp nó vào truy vấn SQL theo cách không an toàn.

Việc chèn SQL bậc hai thường phát sinh trong các tình huống mà các nhà phát triển nhận thức được các lỗ hổng chèn SQL và do đó xử lý một cách an toàn vị trí đầu vào ban đầu vào cơ sở dữ liệu. Khi dữ liệu được xử lý sau đó, nó được coi là an toàn vì trước đó nó đã được đưa vào cơ sở dữ liệu một cách an toàn. Tại thời điểm này, dữ liệu được xử lý theo cách không an toàn vì nhà phát triển đã nhầm tưởng rằng nó đáng tin cậy.