小编典典

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

sql

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

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

这里有几个占位符?在使用占位符输入准备好的语句之前,需要正确解析此语句,对吗?还是我完全想念小船?


主要事实:

  • 没有 实际编写参数准备语句的SQL子句解析器
  • __编写 保证无害的SQL子句清除程序不切实际

解决方案:

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

最佳实践: 四个 数据库用户访问

  1. developer,做所有事情( 切勿 在网络应用中用作连接)
  2. dml -可以在几乎所有内容上选择/ dml(必须用于dml)
  3. read -可以选择(用于所有选择,无论是准备好的还是文本的)
  4. login -只能执行登录/密码功能(在登录过程中使用)

密码保护:

  • dml并且read可能无法通过select或dml访问密码数据
  • login 只能 通过受保护的功能访问密码数据,例如,

     函数登录名(用户名,密码)-返回user_id
     函数set_password(usr_id,password)-设置密码
    
  • 只能login运行login()set_password()功能

  • 根据您的数据库,login 可能 需要对密码列的sql访问
  • 根据您的数据库,该password列可能会受到保护;如果不是,则应将user其从表中移出到其自己的安全表中

mysql使用管理员工具在中进行设置大约需要30分钟,其中包括编写登录功能和拆分密码列的时间。


阅读 188

收藏
2021-04-22

共1个答案

小编典典

知道了!通过仅被授予数据库SELECT特权的数据库用户(连接)路由所有这些查询!

尝试的DML将阻塞。这不能防止DoS攻击(多种方法!),但是可以保护数据。诸如登录之类的安全查询也不会进行。但是对于客户端生成的WHERE和ORDER,以防止DML为目标,这应该可以正常工作。

十/十五年前, 总是 为不同的角色设置不同的用户,但是使用应用程序层等时已经不习惯了。对这些原则进行重新投资可能是个好主意。

除非听到不同的声音将其标记为正确答案-它满足所有标准,但是它回避了编写消毒剂的理论上不可能的挑战。

2021-04-22