如何抵御简单的SQL注入?

来源: 作者:阿己 发布时间:2021-01-19 14:27:58

  以下是一段普普通通的登录演示代码,该脚本需要Username和Password两个参数,其中的SQL语句没有任何过滤,注入起来非常容易


 

  针对上面的代码进行SQL注入,在表单中username的输入框中输入’or 1=1--,这样的话,SQL语句就变成了select * from users where username=''or''=' and password=''or''='' limit 1。除了这条Payload之外,还有很多其他的Payload可用。
 

  上述代码在进行查询时同时查询了Username和Password,查询时用户能操作的参数越多、不确定性就越大。可以换一种思路,查询时拼接的字符串只用到主键Username,后面在检查Password和数据库中的是否一致。即可以调整查询的结构,减少用户可控的参数拼接。

  数据库中密码明文不太好,顺便用md5处理一下,可以防止数据库被黑导致敏感信息泄漏


 

  这样做的话如果继续用username='or''='显然是不可以了,除非你知道数据库中第一个用户的密码。但是毕竟还是可以破解,因此可以在借助过滤函数来帮忙。
 

  在这个例子中,由于Username参数两侧是单引号,如果构造SQL注入一定需要加入额外的单引号来破坏原语句,所以可以直接借助addslashes()函数将Username中的单引号转义。

  $username = addslashes($_POST['username']);

  $password = md5($_POST['password']);

  在这个最简单的例子中,经过这样简单的修改似乎已经没有办法注入了。

  之前提到了过滤函数,用到的是PHP自带的转义函数,但是这个有时候是不够用的,这种情况下可以自定义过滤函数:常见的过滤手段就是限制关键字,通过正则实现。

 

  以下是节选的某CTF赛题中的一段代码,CTF中经常使用留有余地的过滤函数,让选手可以进行SQL注入。

  该段代码中限制了select、insert等很多关键字,对防止SQL注入有一定效果但有缺陷,如果考虑的不太全还是会被注入,过滤函数设置的对关键词过于敏感会让很多正常信息的查询也变得不易。

  $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';