前言
三天赶了两场比赛
黄鹤杯体验极佳 ,比某500空间好到不知哪里去了
web就两个题,一开始就打穿了
于是本菜鸡就开始了划水运动hhhhh
web1
web1是个thinkphp5
扫一下目录有个www.zip
打开后看到源码
有注册 有登录按钮,然后看源码的意思是让你成为admin用户,然后可以得到一个hint来进行下一步
Userinfo.php
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use think\Request;
use think\Validate;
class Userinfo extends Controller
{
public function user(Request $request)
{
$session = $request->session('username');
if($session === 'admin')
{
return view('user',['info'=>'welcome admin!!','flag'=>'This is your hint: <br>hint{xxxxxxxxxx}']);
}
else{
return view('user',['info'=>"hello {$session}",'flag'=>'This is your hint: <br>flag{}<br>maybe the admin have some hints:)']);
}
}
public function change()
{
return view();
}
public function changeinfo(Request $request)
{
$dbuser ='*****';
$dbpass ='*****';
$dbname ="study";
$host = 'localhost';
@error_reporting(0);
@$con = mysqli_connect($host,$dbuser,$dbpass,$con);
// Check connection
if (!$con)
{
echo "Failed to connect to MySQL: " . mysqli_error();
}
@mysqli_select_db($con,$dbname) or die ( "Unable to connect to the database: $dbname");
$post = $request->post();
$username = $request->session('username');
$pass = $post['password'];
$curr_pass = $post['current_password'];
$validate = Validate::make(['password'=>'min:3|confirm']);
$status = $validate->check($post);
if($status){
if (preg_match("/select|update|delete|insert|into|set|;|between|regexp|like|rlike|=|substr|mid|ascii|join|char|order|count|rand|floor|group|extractvalue|updatexml|exp|concat|outfile|\(|\)/i", $curr_pass) || preg_match("/select|update|delete|insert|into|set|;|between|regexp|like|rlike|=|substr|mid|ascii|join|char|order|count|rand|floor|group|extractvalue|updatexml|exp|concat|outfile|\(|\)/i", $pass)) {
$this->success('go out!! hacker','/xinan/public/index/index/index');
} else {
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
$res = mysqli_query($con,$sql) or die('You tried to be smart, Try harder!!!! :( ');
$row = mysqli_affected_rows();
if($row = 1){
$this->success('修改成功啦','/xinan/public/index/login/index');
}else {
$this->error('修改失败,请联系管理员');
}
$this->error($validate->getError());
}
}
}
但是过滤了一大堆关键字,防止注入
然后翻翻目录发现两个有意思的地方
- 根目录下有个shell.php
- 出题人的log没删。。。
shell.php
<?php
echo "这个是内网的操作页面,只允许内网人员使用,get_cmd";
echo "<br />";
if($_SERVER["REMOTE_ADDR"] === "127.0.0.1")
{
@eval(system($_GET["cmd"]));
}
else
{
echo "您的ip是".$_SERVER["REMOTE_ADDR"]."<hr/>"."不是我们的内网机器"."<hr/>"."这是一台内网机器,只接受本机请求"."<hr/>";
return false;
}
是个cmd一句话,但是必须127.0.0.1访问
猜想可能hint就是个ssrf
然后看log
翻翻里面有没有什么有意思的东西
想起了国赛决赛直接把payload放log里了hhhh
前面的都没啥意义,就是出题人调试的过程
然后看到了这个
印证猜想,就是给你一个可以ssrf的地址让你去打shell.php
访问了一下100e8a82eea1ef8416e585433fd8462e.php结果是404
说明可能实际题目中改了名字,这时候就必须要拿到hint才可以得到真实地址
然后正在看他是怎么才能成admin的时候,平台发了一个公告
猜想是怕有些战队扫不到源码备份故意放的水
下载下来后还真是
但是!!!
主办方直接把真实环境的源码给发出来了
阿伟死了
直接找到55ceedfbc97b0a81277a55506c34af36.php
<?php
echo 'please get $url';
$url = $_GET['url'] ?? false;
if($url)
{
$a = preg_match("/gopher/i", $url);
if ($a==0)
{
echo "<br />";
echo "操作错误,你是我们的内网人员吗";
exit();
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET["url"]);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
}
?>
果然是个ssrf,直接跳过了成为admin这一步
payload中还必须有gopher这个单词,这是明晃晃的暗示啊hhhh
然后就是生成gopher二进制流来打
然而实际中被坑的不轻。。。
开始一直是400,不知道为什么
心里想着woc这tm还有幺蛾子
被坑了好久。。。然后没办法让队友看,给他说了思路后队友直接一个payload打过去flag出来了
喵喵喵??? 为毛我一直400
最后才发现一个坑人的地方
就是你在编码payload的时候要用burp的右键send to decoder
而不能用复制粘贴,否则格式会乱,阿帕奇就400
但是我一直都是这么打的啊。。。不知道为什么今天会出错
结果拿了四血,菜鸡大哭.jpg
web2
web2是个smarty的模版注入
这是拿到shell后看的源码
就是两个接口 一个获取ip,一个获取xff
ip不可控,xff可控,带入到模版文件里,就形成了模版注入
看下版本号
因为比赛中允许联网(好评),所以查查对应的版本有没有0day
找到这两篇
第一篇是发现他必须自定义一个注册模版的类才可以插入payload,然而这个题里直接是sha1了一遍路径,所以打不了
第二篇是过滤了php标签,所以无法直接命令执行
翻翻smarty手册
发现可以用include看源码
然而不能跨目录看,就很鸡肋
继续翻手册看到一个eval标签
就rce了。。。
本来想直接system 来cat flag 结果是500没回显
猜想可能有函数禁用
找了一下确实是的,还有open basedir
写个shell
蚁剑连接
无法切换到根目录,需要bypass open basedir
蚁剑大法好,直接上大表哥的bypass disable function插件
拿到flag
手速慢,只拿了个三血
最后
嘲讽的是队友把我一直在看的这个ssrf做了,我把队友一直在看的smarty做了hhhh(队友tql企图当场挖框架0day)
这次比赛水的成绩还不错,见到了一堆巨佬
零食跟自助餐是真的好吃
可惜赶飞机没赶上比赛前一晚上的游艇观光,感觉损失一个亿