SQL注入漏洞
漏洞原理分析
分析漏洞
通过分析sqli靶场第一关的后台的php文件:
通过GET方式获取参数id
,并将获取的参数id
直接拼接到sql语句中进行数据库查询操作。而$row
就是一条记录的数组,通过mysql_fetch_array($result);
来获取sql查询的结果并存入数组中,$row['username']
,获取username参数的值,并echo输出。
然而如果我们通过?字符=参数
的形式传入id
,让传入的参数末尾带上单引号、SQL语句、--+
,就可以悄无声息地将自己想做的sql操作实现。
防御措施
过滤特殊字符(函数可见文末
相关资料
)- 利用str_replace()函数定义select和union特殊字符为黑名单,当检测到有这些特殊字符时,会将其替换成空格,或者小数点。(若替换空格,可能会有大小写,双写绕过;小数点的话,则会避免这些绕过);
- 将特殊字符 ‘ ’‘ (单引号/双引号)利用preg_replace()函数替换为空,不使特殊字符打乱原sql语句。使用mysqli_real_escape_string函数进行参数化查询,转义字符。
采用参数查询
数据库服务器不会将参数的内容视为SQL指令的一部份来处理,而是在数据库完成 SQL 指令的编译后,才套用参数运行,因此就算参数中含有恶意的指令,由于已经编译完成,就不会被数据库所运行。
常见注入类型
Example,sqli靶场less-1是字符型注入,less-2是数字型注入。
判断依据:参数是否可以进行运算
当id=11
:
数字型:
字符型:
数字型注入
参数两边没有单引号
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
字符型注入
参数两边有单引号
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
常见注入手法
union查询
联合查询可以跨库,跨表查询,在mysql数据库5.0.1版本开始添加了information_schema数据库,在这个数据库中存储了所有其他数据库的信息,利用information_schema数据库,可以获取到许多信息,比如数据库的表名,字段名等。
1 | 表名: |
其中,group_concat()函数作用:将数据中的字符串进行拼接后,以一条数据(字符串)的形式展现出来。
以此类推:
1 | 库名: |
1 | 首要步骤: |
布尔盲注
&运算只有当两边同时为真,结果才为真,等号右边的数字等于数据库长度,页面才会有回显,这样可以来判断数据库名的字符长度:
1 | ?id=1' and length(database())=8 --+ |
通过ascii和subctr来判断数据库名的一个个字母,最终得到当前数据库名称:
1 | ?id=1' and ascii(substr(database(),1,1))=115 --+ |
时间盲注(延迟注入)
通过sleep函数使页面加载产生延迟来判断语句是否生效
1 | 如果数据库的长度等于8,则休眠5秒: |
报错注入
1 | 1、通过floor报错,注入语句如下: |
常见绕过方式
首先是上面提到过的大小写绕过和双写绕过:
大小写绕过
如果程序中设置了关键字进行过滤,但是过滤过程中并没有对关键字深入的过滤。比如对and进行过滤,只设置了and
关键字,但是SQL并不区分大小写,于是此时通过修改关键字内字母大小写来绕过过滤,我们将and
替换为AnD
,就能将过滤绕过。
比如:select * from users where id=1 AnD 1=1;
双写绕过
如果设置出现关键字之后替换为空,来避免SQL注入攻击。但是这样的过滤策略可以使用双写绕过。因为在过滤过程中只对这一部分替换。就是将关键字替换为对应的空。
但是比如使用union时,可以使用uniunionon来替换,当系统检测到中的union时,会将其替换为空,然后前后又可以拼接在一起,成功绕过。
编码绕过
URL编码
将URL编码上传到WEB服务器,会自动被解析,但同时也能绕过部分过滤规则,但是比较有局限性。
十六进制绕过 hex()
select * from xxx where name = 0x73747564656e74
ASCII编码绕过 ascii()
test --> CHAR(116)+CHAR(101)+CHAR(115)+CHAR(116)
注释符绕过
1.通过注释符来构造闭合
1 | -- 注释内容 |
2.内联注释绕过
原因:mysql为了保持兼容,它把一些特有的仅在mysql上用的语句放在 /*! */
中,这样这些语句如果在其他数据库中是不会被执行,但在mysql中它会执行。
比如:
union /*!select*/ 1,2,3;
空格过滤绕过
1 | /**/ |
过滤 or and xor not = 的绕过
用符号绕过
and = && or = || xor = | not = ! = --> like
其中:
select '123' like '1%';
like 的通配符有两种:
%(百分号):代表零个、一个或者多个字符。
_(下划线):代表一个数字或者字符。
脚本编写
明天再写…
1 | 相关资料: |
1 | 参考资料: |
本文链接: https://bolerat.github.io/posts/12105/
版权声明: 本博客所有文章除特别声明外,均采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!