1. 房天下登录RSA加密逆向全解析
最近在研究房天下网站的登录流程时,发现其采用了RSA加密算法对密码进行加密传输。作为爬虫工程师,我们需要对这种加密机制进行逆向分析,才能实现自动化登录。下面我将详细记录整个逆向过程,包括接口定位、加密参数分析、代码扣取和复现逻辑。
2. 接口分析与加密参数定位
2.1 登录接口识别
房天下的登录页面位于https://passport.fang.com/。在分析过程中,我发现一个有趣的现象:当密码长度过短时,不会产生任何接口请求;只有当密码长度达到一定要求时,才会触发真正的登录请求。
这里有个关键点需要注意:登录接口和滑块验证接口使用了相同的接口名称。通过对比可以发现:
- 滑块验证请求:请求体较小,不包含账号密码信息
- 登录请求:包含完整的账号密码等登录信息
提示:在实际操作中,建议使用至少8位密码进行测试,这样才能确保触发真正的登录请求。
2.2 XHR断点设置技巧
为了准确定位加密位置,我采用了XHR断点的方式:
- 刷新网页清除之前的请求记录
- 重新输入账号密码
- 在开发者工具的Sources面板中,添加XHR断点
- 点击登录按钮触发断点
这种方法相比普通的断点设置更加精准,能直接拦截到登录请求的发出时刻。
2.3 调用栈分析
在断点触发后,观察调用栈(Call Stack)可以快速定位关键代码。在房天下的案例中,栈中出现了明显的"Login"相关函数名,这通常就是我们要找的加密入口。
通过逐步执行,最终定位到加密函数的位置。这里有两个关键参数:
- 参数1:经过分析是RSA的公钥
- 参数2:待加密的原始密码
3. RSA加密实现解析
3.1 密钥获取
通过全局搜索,我找到了公钥赋值的位置。在JavaScript代码中,公钥通常以字符串形式存储,格式如下:
code复制-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8ybn7...
-----END PUBLIC KEY-----
在房天下的实现中,公钥被赋值给了一个变量,我们需要在扣代码时确保这个变量值正确传递。
3.2 加密函数分析
初看加密函数时,发现它并不是标准的RSA实现形式。但深入函数内部后,可以发现它最终调用了底层的加密算法。这种封装方式在网站开发中很常见,目的是增加逆向难度。
关键点在于:
- 函数内部有多个相互调用的子函数
- 最终会调用到核心的RSA加密算法
- 需要完整扣取所有相关函数才能保证功能正常
3.3 代码扣取策略
面对这种相互调用的函数结构,我的扣取策略是:
- 从最外层的加密函数开始
- 逐步向内追踪所有被调用的函数
- 确保不遗漏任何依赖关系
- 特别注意全局变量的处理
在实际操作中,可以使用浏览器的调试工具逐个函数查看,并使用"Copy function"功能获取完整代码。
4. Python复现实战
4.1 环境准备
要实现Python版的RSA加密,需要安装以下库:
python复制pip install pycryptodome
4.2 核心代码实现
基于扣取的JavaScript代码,我实现了Python版本的加密函数:
python复制from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64
def rsa_encrypt(password, public_key):
# 处理公钥格式
public_key = public_key.replace("-----BEGIN PUBLIC KEY-----", "")
public_key = public_key.replace("-----END PUBLIC KEY-----", "")
public_key = public_key.replace("\n", "")
# 解码公钥
key_bytes = base64.b64decode(public_key)
rsa_key = RSA.importKey(key_bytes)
# 创建加密器
cipher = PKCS1_v1_5.new(rsa_key)
# 加密密码
encrypted = cipher.encrypt(password.encode())
# Base64编码结果
return base64.b64encode(encrypted).decode()
4.3 完整登录流程
结合加密函数,完整的登录流程如下:
python复制import requests
def fang_login(username, password):
# 1. 获取公钥(可以从网页源码或固定值获取)
public_key = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8ybn7...
-----END PUBLIC KEY-----"""
# 2. 加密密码
encrypted_pwd = rsa_encrypt(password, public_key)
# 3. 准备登录数据
data = {
'uid': username,
'pwd': encrypted_pwd,
# 其他必要参数...
}
# 4. 发送登录请求
session = requests.Session()
response = session.post('https://passport.fang.com/login.api', data=data)
return response.json()
5. 常见问题与解决方案
5.1 加密结果长度不一致
问题现象:Python实现的加密结果长度与网页端不一致。
解决方案:
- 检查公钥是否完全相同
- 确认加密前的密码编码一致(通常使用UTF-8)
- 验证Base64编码方式是否相同
5.2 滑块验证码干扰
问题现象:登录时需要先通过滑块验证。
解决方案:
- 在发送登录请求前,先处理滑块验证
- 可以尝试复用已有cookie
- 考虑使用自动化工具如Selenium处理滑块
5.3 请求频率限制
问题现象:频繁请求后被封IP。
解决方案:
- 合理控制请求频率
- 使用代理IP池
- 添加随机延迟
6. 加密算法优化建议
在实际项目中,我总结了几点优化建议:
- 缓存公钥:公钥通常不会频繁变更,可以缓存减少请求
- 错误处理:添加完善的异常捕获和重试机制
- 性能监控:记录加密耗时,及时发现性能问题
- 代码复用:将加密模块抽象为独立服务,方便多处调用
7. 安全注意事项
在进行此类逆向工程时,需要注意:
- 遵守网站的使用条款,不要进行恶意爬取
- 控制请求频率,避免对目标服务器造成过大压力
- 妥善保管账号信息,不要在代码中硬编码敏感数据
- 定期检查加密逻辑是否变更,及时更新代码
通过这次逆向分析,我不仅成功实现了房天下的自动化登录,还深入理解了RSA加密在前端安全中的应用。这种经验对于处理其他网站的加密机制也很有帮助。在实际项目中,关键是要有耐心逐步分析,并确保代码的完整性和准确性。