SQL注入-如何清理程序生成的SQL子句

sql injection - how to sanitize program generated sql clause?

本文关键字:SQL 子句 程序生成 注入 何清理      更新时间:2023-09-26

在标准Ajax中,whereorder by SQL子句是由程序(而不是用户)提供的,例如

var url = ".select?dd=emp&where="+escape("emp_tp='abc' and hire_dt<current_date-'2 years' and super_emp_id is distinct from emp_id")

在服务器上被

应答
$where = (isset($_GET['where'])) ? pureClause($_GET['where']) : null;
$order = (isset($_GET['order'])) ? pureClause($_GET['order']) : null;
...
$query = $query.(($where)?" where $where":'').(($order)?" order by $order":'');

问题是pureClause函数应该是什么样的?

现在pureClause只是抛出错误,如果有以下任何一个存在:

; select insert update delete drop create truncate

如果其他注入导致查询失败,没关系,只要数据未损坏

对我来说这似乎足够了,但在我心里,我知道我错了。

澄清:

    Postgres中的
  • 预处理语句虽然非常快,但设置和维护起来很麻烦——它们适用于使用良好的查询,但不适用于自定义查询。
  • 为每个事务创建一个准备好的语句是一个巨大的数据库冲击。如果可以在应用程序级别获得安全性,则更可取。
最后,考虑where子句
emp_tp='abc' and hire_dt=current_dt-'2 years' and super_emp_id is distinct from emp_id

这里有多少占位符?在将其输入到带有占位符的预处理语句之前,需要对其进行正确解析,对吗?还是我完全错过了机会?


主要事实:

  • not为参数化准备语句编写SQL子句解析器
  • not编写一个SQL子句清理程序来保证没有危害

解决方案:

用于select,其中随机SQL可能是一个问题:因为保护数据库太难了,让数据库保护自己吧!不同的用户具有不同的角色/权限。使用只读用户进行选择。对于普通SQL,这保证了这些语句中没有DML。

最佳实践:四个 db用户访问

  1. developer,做一切(绝不使用作为web应用程序的连接)
  2. dml -可以选择/dml在几乎所有(必须使用dml)
  3. read -可以选择(用于所有选择,无论是准备的还是文本)
  4. login -只能执行登录/密码功能(在登录过程中使用)

密码保护:

  • dmlread不能访问密码数据,通过select或dml
  • login只能通过受保护的函数(例如
  • )访问密码数据
<>之前函数login(username, password) -返回user_id命令功能set_password(usr_id, password) -设置密码之前
  • 只有login可以运行login()set_password()函数
  • 根据您的数据库,login 可能需要sql访问密码列
  • 根据你的数据库,password列可以保护自己;如果没有,那么应该从user表移到它自己的安全表
  • 中。

mysql中使用管理员工具进行设置,花费了大约30分钟,包括编写登录函数和拆分密码列的时间。

您正在做的是sql注入的定义,不能被清理。您不能以安全的方式传入WHERE子句句号。您必须在服务器端构建查询的这一部分。事实上,你没有认识到这意味着你必须阅读更多关于sql注入,显然问StackOverflow是一个不安全的方法来解决这个问题。担心的是,您可能永远不会了解这个漏洞的基本原理。

$order可以通过白名单安全完成。例如:

if(in_array($_GET['order'],$list_of_rows)){
   $order=$_GET['order'];
}

如果您正在传递表名或列名,请确保将其与白名单进行检查,否则这将是sql注入。

明白了!通过数据库用户(连接)路由所有这些查询,该用户在数据库上只被授予SELECT权限!

尝试DML将阻塞。这并不能防止DoS攻击(有很多方法可以做到这一点!),但确实可以保护数据。也不能保证安全查询,比如登录。但是对于客户端生成的WHERE和ORDER,以防止DML为目标,这应该工作得很好。

10/15年前总是为不同的角色设置不同的用户,但随着应用程序层等的出现,这种习惯已经过时了。重新投资这些原则可能是个好主意。

除非hear different将其标记为正确答案-它满足所有标准,但它避开了理论上不可能的挑战,即编写消毒程序。

始终使用预处理语句。它将处理输入转义并避免sql注入。不需要像pureClause这样的黑客。查看mysqli_stmt::prepare()

正如@Stephen建议的那样,提供WHERE作为对象,然后解析该对象并生成安全的SQLVar where = {emp_tp: {条件:平等价值:"abc"}Var order = {emp_tp:"ASC"}

发送json:

var params = {
  w: where,
  o: order
}
$.post(url,params,function(result){...}, 'json');

在PHP中

$where = isset($_POST['w']) ? json_decode($_POST['w') : array();
if (!empty($where)) {
  foreach ($where as $field => $data) {
     // validate that field exists
     // validate that operator is valid
     $sql .= sprintf('%s %s "%s"', $field, $data->operator, mysql_escape_string($data->value));
  }
}