MySQL注入解决方案

问题描述 投票:0回答:4

我被 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'] )'; 


?>

我知道,我知道您仍然可以使用

1=1
或任何其他类型的注射进行注射... 但我认为这可以解决你一半的问题,因此执行正确的 mysql 查询。

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

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

php mysql sql-injection
4个回答
11
投票

这已经在 PHP 中正确实现了:

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


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

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

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


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*

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执行崩溃,因为如果id是一个整数,它只能与另一个整数进行比较,如果它是一个字符串,它将与字符串进行比较您提供的字符串,而不是尝试将字符串作为 SQL 的一部分执行。

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

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


1
投票

你看,你的想法是错误的。
虽然很多人都这么做。 根据 SQL 注入,有 2 个强烈的误解:

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

两者都错了。

当你遵循 SQL 语法时,就不存在“SQL 注入”这样的事情。

想想看。

如果您遵循 SQL 语法规则(并且无论如何都必须遵循它,尽管有注入!),您是安全的,只是作为副作用。

任何放入 SQL 查询的字符串数据都必须按照 2 条规则进行处理:

1.字符串中所有特殊字符都必须转义。
2. 字符串必须用引号引起来。

非文本数据也存在问题。也没什么大不了的。

但如果你觉得它太复杂,你可以随时选择准备好的陈述 - 它总是安全的并且不允许思考。

尽管查询的非数据部分仍然存在问题。这确实是最危险的部分。而唯一的问题才有资格被称为“SQL注入”。

为了避免这种情况,查询的所有动态非数据部分都必须在脚本中进行硬编码。这是唯一可行的方法。

© www.soinside.com 2019 - 2024. All rights reserved.