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

cc *_*ung 6 javascript sql security sql-injection

在标准的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")
Run Code Online (Sandbox Code Playgroud)

在服务器上回答

$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":'');
Run Code Online (Sandbox Code Playgroud)

问题是功能应该是什么pureClause样的?

pureClause如果存在以下任何一种情况,现在只会引发错误:

; select insert update delete drop create truncate
Run Code Online (Sandbox Code Playgroud)

如果其他注入导致查询失败,那就没问题,只要数据没有损坏.

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

澄清:

  • Postgres中准备好的语句,虽然速度很快,但是设置和维护都很痛苦 - 它们对于使用得很好的查询是好的,但不适用于自定义查询.
  • 为每个事务创建一个准备好的语句是一个巨大的 db命中.如果可以在应用程序级别获得安全性,则更受欢迎.

最后,考虑where子句

emp_tp='abc' and hire_dt=current_dt-'2 years' and super_emp_id is distinct from emp_id
Run Code Online (Sandbox Code Playgroud)

这里有多少占位符?这需要在被放入带有占位符的预准备语句之前正确解析,对吧?还是我完全错过了船?


主要事实:

  • 为参数化的预准备语句编写SQL子句解析器是实际的
  • 没有实际编写SQL子句消毒,保证不伤害

解:

对于SELECTS,随机SQL可能是一个问题:因为保护数据库太难了,让数据库保护自己!让不同的用户拥有不同的角色/权限.使用只读用户进行选择.对于普通的SQL,这可以保证这些语句不会出现DML.

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

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

密码保护:

  • dml并且read可能无法通过select或dml访问密码数据
  • login通过受保护的功能访问密码数据,例如,
     function login( username, password ) - returns user_id
     function set_password( usr_id, password ) - sets password
  • 只有login可以运行login()set_password()功能
  • 根据您的数据库,login 可能需要sql访问密码列
  • 根据您的数据库,password列可能会受到保护; 如果没有,那么应该从user表中移出到自己的安全表中

在设置此功能mysql,使用管理员工具,花了约30分钟,包括时间写的登录功能,并拆分出密码列.

roo*_*ook 5

你正在做的是sql注入的定义,无法清理.你不能WHERE在一个安全的时尚期末传递一个条款.您必须在服务器端构建此部分查询.你没有意识到这一点的事实意味着你必须阅读更多有关sql注入的信息,显然要求StackOverflow是一个不安全的方法来解决这个问题.担心的是,您可能永远无法了解此漏洞的基本原理.

$order可以使用白名单以安全的方式完成.例如:

if(in_array($_GET['order'],$list_of_rows)){
   $order=$_GET['order'];
}
Run Code Online (Sandbox Code Playgroud)

如果您传入的是表名或列名,请确保根据白名单进行检查,否则这将是sql注入.


cc *_*ung 2

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

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

十年/十五年前,总是为不同的角色设置不同的用户,但随着应用程序层等的出现,人们就不再习惯了。重新投资于这些原则可能是个好主意。

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