@Charles cực kỳ đúng!
Bạn tự đặt mình vào nguy cơ mắc nhiều loại đã biết Các cuộc tấn công SQL, bao gồm, như bạn đã đề cập
- Chèn SQL:Có! Mysql_Escape_String có thể VẪN khiến bạn dễ bị tiêm SQL, tùy thuộc vào vị trí bạn sử dụng các biến PHP trong truy vấn của mình.
Hãy xem xét điều này:
$sql = "SELECT number FROM PhoneNumbers " .
"WHERE " . mysql_real_escape_string($field) . " = " . mysql_real_escape_string($value);
Điều đó có thể được thoát một cách an toàn và chính xác theo cách đó không? KHÔNG! Tại sao? bởi vì một tin tặc rất có thể vẫn làm điều này:
Nhắc lại sau tôi:
mysql_real_escape_string()
chỉ nhằm mục đích thoát khỏi dữ liệu biến đổi, KHÔNG tên bảng, tên cột và đặc biệt không phải là LIMIT trường.
-
Khai thác LIKE:LIKE "$ data%" trong đó $ data có thể là "%" sẽ trả về TẤT CẢ các bản ghi ... mà rất có thể là khai thác bảo mật ... chỉ cần tưởng tượng một Tra cứu theo bốn chữ số cuối cùng của thẻ tín dụng ... OOP! Giờ đây, tin tặc có thể nhận được mọi số thẻ tín dụng trong hệ thống của bạn! (BTW:Lưu trữ đầy đủ thẻ tín dụng hiếm khi được khuyến khích!)
-
Khai thác bộ mã:Bất kể những kẻ thù ghét nói gì, Internet Explorer vẫn vẫn , vào năm 2011, dễ bị khai thác theo nhóm ký tự và đó là nếu bạn đã thiết kế trang HTML của mình một cách chính xác, với
<meta name="charset" value="UTF-8"/>
! Các cuộc tấn công này RẤT khó chịu vì chúng cung cấp cho tin tặc nhiều quyền kiểm soát như tiêm SQL thẳng:ví dụ:đầy.
Dưới đây là một số mã ví dụ để chứng minh tất cả những điều này:
// Contains class DBConfig; database information.
require_once('../.dbcreds');
$dblink = mysql_connect(DBConfig::$host, DBConfig::$user, DBConfig::$pass);
mysql_select_db(DBConfig::$db);
//print_r($argv);
$sql = sprintf("SELECT url FROM GrabbedURLs WHERE %s LIKE '%s%%' LIMIT %s",
mysql_real_escape_string($argv[1]),
mysql_real_escape_string($argv[2]),
mysql_real_escape_string($argv[3]));
echo "SQL: $sql\n";
$qq = mysql_query($sql);
while (($data = mysql_fetch_array($qq)))
{
print_r($data);
}
Đây là kết quả của mã này khi các đầu vào khác nhau được chuyển:
$ php sql_exploits.php url http://www.reddit.com id
SQL generated: SELECT url FROM GrabbedURLs
WHERE url LIKE 'http://www.reddit.com%'
ORDER BY id;
Returns: Just URLs beginning w/ "http://www.reddit.com"
$ php sql_exploits.php url % id
SQL generated: SELECT url FROM GrabbedURLs
WHERE url LIKE '%%'
ORDER BY id;
Results: Returns every result Not what you programmed, ergo an exploit --
$ php sql_exploits.php 1 =1 ' http://www.reddit.com 'id Kết quả:Trả về mọi cột và mọi kết quả.
Sau đó, có những lần khai thác LIMIT khó chịu:
$ php sql_exploits.php url
> 'http://www.reddit.com'
> "UNION SELECT name FROM CachedDomains"
Generated SQL: SELECT url FROM GrabbedURLs
WHERE url LIKE 'http://reddit.com%'
LIMIT 1
UNION
SELECT name FROM CachedDomains;
Returns: An entirely unexpected, potentially (probably) unauthorized query
from another, completely different table.
Bạn có hiểu SQL trong các cuộc tấn công hay không là điều không quan trọng. Điều này đã chứng minh rằng mysql_real_escape_string () rất dễ dàng bị phá bởi ngay cả những tin tặc non nớt nhất. Đó là bởi vì nó là một giáo lý phòng thủ PHẢN ỨNG. Nó chỉ sửa lỗi khai thác rất hạn chế và BIẾT trong Cơ sở dữ liệu.
Tất cả thoát sẽ KHÔNG BAO GIỜ đủ để bảo mật cơ sở dữ liệu. Trên thực tế, bạn có thể PHẢN ỨNG một cách rõ ràng với mọi hoạt động khai thác BIẾT và trong tương lai, mã của bạn rất có thể sẽ dễ bị tấn công bởi các cuộc tấn công được phát hiện trong tương lai.
Biện pháp bảo vệ thích hợp, và duy nhất (thực sự) là biện pháp CHÍNH XÁC:Sử dụng Câu lệnh Chuẩn bị. Các câu lệnh chuẩn bị sẵn được thiết kế với sự cẩn thận đặc biệt để CHỈ SQL hợp lệ và được LẬP TRÌNH được thực thi. Điều này có nghĩa là, khi được thực hiện đúng cách, tỷ lệ SQL không mong muốn có thể được thực thi sẽ giảm một cách kịch tính.
Về mặt lý thuyết, các câu lệnh đã chuẩn bị sẵn được triển khai một cách hoàn hảo sẽ không bị TẤT CẢ các cuộc tấn công, đã biết và chưa biết, vì chúng là một kỹ thuật PHÂN PHỐI MÁY CHỦ, được xử lý bởi DATABASE SERVERS THEMSELVES và các thư viện giao diện với ngôn ngữ lập trình. Do đó, bạn LUÔN LUÔN được đảm bảo sẽ được bảo vệ trước MỌI SỰ CỐ GẮNG BIẾT, ở mức tối thiểu.
Và nó ít mã hơn:
$pdo = new PDO($dsn);
$column = 'url';
$value = 'http://www.stackoverflow.com/';
$limit = 1;
$validColumns = array('url', 'last_fetched');
// Make sure to validate whether $column is a valid search parameter.
// Default to 'id' if it's an invalid column.
if (!in_array($column, $validColumns) { $column = 'id'; }
$statement = $pdo->prepare('SELECT url FROM GrabbedURLs ' .
'WHERE ' . $column . '=? ' .
'LIMIT ' . intval($limit));
$statement->execute(array($value));
while (($data = $statement->fetch())) { }
Bây giờ điều đó không quá khó phải không? Và đó là mã ít hơn bốn mươi bảy phần trăm (195 ký tự (PDO) so với 375 ký tự (mysql_). Đó là những gì tôi gọi là "toàn thắng".
CHỈNH SỬA:Để giải quyết tất cả những tranh cãi mà câu trả lời này đã gây ra, cho phép tôi nhắc lại những gì tôi đã nói:
Sử dụng các câu lệnh đã chuẩn bị cho phép người ta khai thác các biện pháp bảo vệ của chính máy chủ SQL và do đó bạn được bảo vệ khỏi những thứ mà máy chủSQL mà mọi người biết. Nhờ mức độ bảo vệ bổ sung này, bạn sẽ an toàn hơn nhiều so với việc chỉ sử dụng màn hình, bất kể kỹ lưỡng đến đâu.