MySQL注入解决方案

发布于 2024-08-31 20:26:24 字数 1050 浏览 6 评论 0原文

我被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 查询。

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

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

I have been bothered for so long by the MySQL injections and was thinking of a way to eliminate this problem all together. I have came up with something below hope that many people will find this useful.

The only Draw back I can think of this is the partial search:
Jo =>returns "John" by using the like %% statement.

Here is a php solution:

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


?>

I know, I know that you still could inject using 1=1 or any other type of injections...
but this I think could solve half of your problem so the right mysql query is executed.

So my question is if anyone can find any draw backs on this then please feel free to comment here.

PLEASE GIVE AN ANSWER only if you think that this is a very useful solution and no major drawbacks are found OR you think is a bad idea all together...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

微暖i 2024-09-07 20:26:24

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

但是,您应该首先阅读 PHP手动录入关于SQL注入


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

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

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

This has already been implemented correctly in PHP:

However, you should start by reading the PHP manual entry on SQL injection.


To answer your actual question, the primary drawbacks of your approach are:

  1. It doesn't work
  2. Just to be clear, it doesn't work, and will leave you wide open to SQL injection.
  3. It also prevents you entering any data which clashes with a MySQL keyword.

If you're going to reinvent the wheel, I would recommend looking at pre-existing wheels.

要走干脆点 2024-09-07 20:26:24

重新发明轮子并以错误的方式重新发明它(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*

Reinventing the wheel and reinventing it the Wrong Way (TM).

  • First of all, there are parametrized queries (available for PHP in MySQLi extension); if that's not an option, there's mysql_real_escape_string. This is the main issue - check for already available options before deciding to implement them on your own.
  • Second, you are trying to call PHP functions in SQL, what you wanted was probably something like 'SELECT * FROM ' . safeQ($_GET['query'])
  • Third, you've broken all indexing and search on data containing your "evil words", say hello to performance problems and crazy workarounds.

Edit: To address the example you're giving in comments:

$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*
剩一世无双 2024-09-07 20:26:24

这是一个坏主意。

对于每种语言、平台、运行时、引擎、库,无论你可能拥有什么,都已经有一个适当的、正确的、有效的 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 的常量硬编码到代码中,并让用户选择指导代码添加哪些常量、添加顺序以及添加位置。

It is a bad idea.

There is already a proper, correct, and working, solution to SQL injection in every language, platform, runtime, engine, library, whateveryoumighthave.

It's called parameters.

Instead of placing the value into the SQL as a literal constant, you add a parameter placeholder, and then provide the paramter value alongside the query, and not using any formatting tricks to get it back into the SQL either.

Every other solution which tries to "fix" the problem by looking at the SQL or pieces of it and attempting to determine if it is correct is sub-par and most of them has other bugs and problems that you can't see, don't know about, and don't really want to have.

So stop beating around the bush, and do it the right way to begin with. Switch to using parameters.

In PHP, talking to MySQL, there are multiple ways, but using the mysqli library:

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

If the $id variable here contains unsafe code, it will make the SQL Execution crash, because if id is an integer, it cannot be compared to anything but another integer, and if it is a string, it will be compared against the string you provide, not trying to execute the string as part of the SQL.

Now, the comment brings out a point, sometimes you have to change the SQL anyway, because you will provide dynamic ordering (ie. ordering picked by the user), or dynamic filtering (ie. which filters to apply are picked by the user).

In this case, the solution is simple: Do not take any user-provided text and place it into the SQL. Instead, you hard-code the constants to add to your SQL into your code, and let the users choices guide the code in which of those constants to add, in which order, and where.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文