-7

我已经被 MySQL 注入困扰了很长时间,并且正在考虑一种方法来一起消除这个问题。我在下面想出了一些东西,希望很多人会发现这很有用。

我能想到的唯一缺点是部分搜索:Jo => 通过使用 like %% 语句返回“John”。

这是一个php解决方案:

<?php
function safeQ(){
   $search= array('delete','select');//and every keyword...
   $replace= array(base64_encode('delete'),base64_encode('select'));
   foreach($_REQUEST as $k=>$v){
      str_replace($search, $replace, $v);
   }
}
safeQ();

function html($str){
   $search= array(base64_encode('delete'),base64_encode('select'));
   $replace= array('delete','select');//and every keyword...
   str_replace($search, $replace, $str);
}

//example 1
...
...
$result = mysql_fetch_array($query);
echo html($result[0]['field_name']);

//example 2
$select = 'SELECT * FROM $_GET['query'] '; 

//example 3
$insert = 'INSERT INTO .... value( $_GET['query'] )'; 


?>

我知道,我知道您仍然可以注入 using1=1或任何其他类型的注入...但是我认为这可以解决您的一半问题,因此执行正确的 mysql 查询。

所以我的问题是,如果有人能找到任何缺点,请随时在这里发表评论。

请仅在您认为这是一个非常有用的解决方案并且没有发现主要缺点或您认为这是一个坏主意时才给出答案......

4

4 回答 4

11

这已经在 PHP 中正确实现:

但是,您应该首先阅读有关 SQL 注入的 PHP 手册条目


要回答您的实际问题,您的方法的主要缺点是:

  1. 它不起作用
  2. 需要明确的是,它不起作用,并且会让您对 SQL 注入敞开心扉。
  3. 它还可以防止您输入任何与 MySQL 关键字冲突的数据。

如果您要重新发明轮子,我建议您查看已有的轮子。

于 2010-05-07T10:01:00.483 回答
6

重新发明轮子并以错误的方式重新发明它 (TM)。

  • 首先,有参数化查询(可用于MySQLi扩展中的 PHP);如果这不是一个选项,那么有mysql_real_escape_string。这是主要问题 - 在决定自己实施之前检查已经可用的选项。
  • 其次,您试图在 SQL 中调用 PHP 函数,您想要的可能类似于'SELECT * FROM ' . safeQ($_GET['query'])
  • 第三,你破坏了所有包含你的“邪恶词”的数据的索引和搜索,向性能问题和疯狂的解决方法问好。

编辑:要解决您在评论中给出的示例:

$v="1; DROP tbl;\";DROP tbl" // oh look, an SQL injection attempt!
$s = 'SELECT * FROM tbl WHERE ID='.$v; // SQL injection, no doubt

// if ID is an integer field, make it an integer. Simple, secure, and fast.
$s = 'SELECT * FROM tbl WHERE ID='.(int)$v; 
// $s == 'SELECT * FROM tbl WHERE ID=1' // see PHP manual for explanation of type casting

// if ID is a string field, escape it. Simple, secure, and still plenty fast.
$s = 'SELECT * FROM tbl WHERE ID="'.mysql_real_escape_string($v) . '"';
// $s == 'SELECT * FROM tbl WHERE ID="1; DROP tbl;\";DROP tbl"'; 
// See? No injection, as the quote is *escaped*
于 2010-05-07T10:12:56.950 回答
2

这是个坏主意。

每种语言、平台、运行时、引擎、库,无论你可能拥有什么,都已经有一个适当的、正确的、有效的 SQL 注入解决方案。

它被称为参数。

不是将值作为文字常量放入 SQL 中,而是添加参数占位符,然后在查询旁边提供参数值,并且也不使用任何格式化技巧将其重新放入 SQL 中。

通过查看 SQL 或其片段并尝试确定它是否正确来尝试“修复”问题的所有其他解决方案都是低于标准的,并且其中大多数都有其他你看不到的错误和问题,不要不知道,也不想拥有。

所以不要拐弯抹角,从正确的方式开始。切换到使用参数。

在 PHP 中,与 MySQL 对话有多种方式,但使用 mysqli 库:

$stmt = $db->prepare('SELECT * FROM products WHERE id = ?');
$stmt->bind_param('i', $id);
$stmt->execute();
.. bind for results
$stmt->fetch();

如果这里的 $id 变量包含不安全的代码,会导致 SQL Execution 崩溃,因为如果 id 是一个整数,它不能与其他任何整数进行比较,如果是字符串,它将与你的字符串进行比较提供,而不是尝试将字符串作为 SQL 的一部分执行。

现在,评论指出了一点,有时您无论如何都必须更改 SQL,因为您将提供动态排序(即用户选择的排序)或动态过滤(即应用哪些过滤器由用户选择) .

在这种情况下,解决方案很简单:不要将任何用户提供的文本放入 SQL中。相反,您将要添加到 SQL 的常量硬编码到代码中,并让用户选择指导代码添加哪些常量、添加顺序和位置。

于 2010-05-07T10:25:47.337 回答
1

看,你是从错误的角度考虑的。
虽然很多人都这样。根据 SQL 注入,有两种强烈的误解:

  1. 有一种特殊的攻击方式,称为“SQL 注入”。
  2. 为了防止它,输入数据必须以某种特殊的方式受到威胁。

两人都错了。

当您遵循 SQL 语法时,没有“SQL 注入”之类的东西。

去搞清楚。

如果你遵循 SQL 语法规则(无论如何你必须遵循它,尽管有注入!)你是安全的,就像副作用一样。

任何放入 SQL 查询的字符串数据都必须按照 2 条规则处理:
1. 字符串中的所有特殊字符都必须转义。
2. 字符串必须用引号括起来。

非文本数据也存在问题。也没什么大不了的。
但是如果你觉得它太复杂了,你总是可以选择准备好的语句——它总是安全的,不需要思考。

尽管查询的非数据部分仍然存在问题。这确实是最危险的部分。并且唯一的问题有权被称为“SQL注入”。
为避免这种情况,查询的所有动态非数据部分都必须在脚本中进行硬编码。这是唯一可能的方法。

于 2010-05-07T10:15:14.350 回答