近期公司新上了疫苗预约功能,由于目前九价、四价疫苗的火爆程度,很快就吸引了各路牛马扫描爆破接口。因为缺乏防控措施,导致了这些爬虫、脚本对疫苗资源的抢占挤压,更有些不讲武德完全不做频率限制的爬虫脚本,一秒中查询调用11次,给服务产生了不良影响。
因此,需要设计一套方案来避免黄牛抢占资源,为广大群众创造出更加公平可靠的疫苗预约平台🎉。
方案设计
一、请求响应加密
对报文使用加密可以避免被抓包,让攻击者抓包窃取到密文也无法理解。虽然目前小程序都是使用的 HTTPS 协议,但是攻击者依旧可以通过证书劫持的方法进行抓包,因此即使应用层已加密,报文本身是明文的依旧会有风险。
在使用加密时,存在一个问题就是密钥交换。在密钥交换的时候无法确保密钥被安全、无误的传输。如果密钥写到前端代码中,攻击者获取到前端代码后可以轻松窃取到密钥。在浏览微信小程序文档的时候,发现了微信小程序有一个获取加密密钥的API:UserCryptoManager.getLatestUserKey。
const userCryptoManager = wx.getUserCryptoManager()
userCryptoManager.getLatestUserKey({
success: res => {
const {encryptKey, iv, version, expireTime} = res
console.log(encryptKey, iv, version, expireTime)
}
})
对报文请求进行加密,并在接口参数中加上时间戳参数,可以有效的避免被抓包和重放攻击,并且这个过程对于正常用户而言是无感的,完全不会影响使用体验。这个方案的缺点是,无法避免自动化UI脚本在真实的小程序运行环境下模拟操作,使用自动化UI脚本刷号源。
二、请求频率限制
正常用户使用程序,会存在一定的行为特征,和机器的一个典型区别就是请求频率。在应用此方案的过程中,需要先统计出用户的使用频率,取一个阈值作为机器人的判断标准,当超出阈值后直接返回错误,一定时间后恢复。
为了最大程度的避免对正常用户的影响,在统计用户使用频率和阈值选取这块需要多加注意,并且可以结合多种频率限制规则,如一秒中允许请求多少3次,一分钟允许请求100次,一小时允许请求3000次。具体的频率限制规则需要按照具体业务来制定,具体的实现可以使用 Nginx 的 ngx_http_limit_req_module 轻松完成。
三、来源限制
目前注意到,脚本刷号的主要来源是PC端,即使用 Windows 端微信打开小程序,结合 Windows 上丰富的自动化UI工具刷号源。对于这种情况可以在代码中直接封死PC端,只允许在移动端操作,这块的选择需要自己权衡影响。
四、验证码
是的,这种最传统的、最影响用户使用体验的方案还是来了,为了区分正常用户和自动化UI脚本,需要使用验证码来区分开这类用户,验证码无疑是针对这个场景最有效的方案了。
当然,不一定非要使用最传统的字母数字验证码,甚至可以使用人脸识别,结合请求频率等规则使用。当用户请求频率到一定程度,需要人脸识别来判断是本人操作。
验证码的具体实现有很多种,这里不展开阐述。
五、机器学习风控系统(猜想原型)
这一步目前还在猜想阶段,因为最近在学习机器学习,意识到这是具有一定可行性的。黄牛党的刷号、预约、取消号源具有特定的行为模式,我们可以通过数据分析出特征,使用机器学习的方式识别出异常行为。
但是机器学习得出结果过程是一个黑盒,当出现用户投诉情况的话,不好核实处理。且存在成本相对较高的问题,所以此方案搁置。
发表回复