写在前
最近在写一个模拟登陆腾讯企业邮箱的东西,但是发现在POST的数据中有一个p字段的内容是一个加密的字符串。经过查看源码发现p字段的值原来是由表单中pp和ts两个字段的值拼接并进行RSA加密的结果经过base64编码后得来的,其中pp字段是用户输入的密码,而ts字段是一个时间戳(在页面源码中已经给出)。最初的想法比较偷懒,想去直接调JS代码算出个结果返回回来,但是发现调这个JS太麻烦了,还不如直接用Python代码重新实现一遍这个加密算法呢……于是乎,折腾起来吧~
实现
首先,获取RSA算法的公钥和ts值很简单,直接从页面源码中按字符串处理的方式即可提取出公钥(当然,这里上个正则秀个操作也是可以的~),而ts的值从form表单中即可获取。
1 2 3 4 |
# 提取RSA算法的公钥 def get_key(content): base_pos = content.find('"', content.find('var PublicKey = ')) + 1 return content[base_pos: base_pos + 256] |
RSA算法的实现可以直接使用第三方库rsa,将加密后结果(十六进制)做base64编码即为所求的p值。
1 2 3 4 |
def get_p(public_key_str, password, ts): public_key = rsa.PublicKey(int(public_key_str, 16), 65537) res_tmp = rsa.encrypt('{password}\n{ts}\n'.format(password = password, ts = ts), public_key) return base64.b64encode(res_tmp) |
如果有细心的人验证结果是否正确时可能会发现我们算出来的p值和抓包抓到的提交的p值完全不同,但是不要慌,因为RSA算法在进行加密时会进行一个随机填充(而不是填充固定值,如全0),所以由于填充的值不同,我们算出来的结果与抓包看到的p值不同是正常的,不影响正常登录。
在提交完登录表单后会得到一个“重定向”的页面,这个页面里就包含了登陆进邮箱的地址targetUrl,并通过window.location.replace的方法将窗口“重定向”到了targetUrl。
好了,任务完成~
前端加密在安全上的用途
了解安全的人都知道,明文传输登录表单是件很不安全的事情,因为我们无法保证数据在传输过程中的安全性,如果表单内容被嗅探,攻击者便可轻松直接拿到我们的帐号密码。对于这个问题一个比较好的解决办法就是启用HTTPS,使用HTTPS的安全性固然很高,但是由于其在经济、性能等方面都需要花费较大的成本,所以这种方案的应用并不十分普遍,而前端加密则是一种比较常见的替代方案,它通过前端JS对敏感数据加密然后再进行传输,可以很大程度上的减少资源的消耗。
下面以登录为例,我们来看一下通过前端加密传输密码的过程。
首先在我们请求登录页面的时候,服务器会将一个公钥(PublicKey)和一段用于加密的JS代码一起发给用户,在提交表单时浏览器会先执行这段JS代码对密码进行加密,然后将加密后的密码密文连通表单其他数据一起提交到服务器。这样数据包即使在传输过程中被嗅探到,但是由于没有私钥,攻击者仍然无法拿到真正的密码。
在此基础上,为了防止重放攻击等问题,服务器通常还会在用户请求登录页面的时候给用户发送一个盐值(salt),JS在进行加密时会将盐值和密码的明文一起加密。这样,由于每次的盐值不同所以每次加密后的密文也会不同,这样可以有效的避免重放攻击。
对于上面所提到的“用于加密的JS代码”的加密算要求是公钥加密算法,这样可以有效的防止攻击者解出密码的明文,一般多为RSA算法。
最后
虽然前端通过JS加密表单敏感数据的方法新浪微博、人人网等一些网站都在使用,但是目前网上关于这种方案的相关介绍还不是很多,所以如果您有这方面的资料或者经验可以分享的欢迎随时Email我,非常感激~
点击数:4589
版主,最近模拟登录某网站的时候,也是RSA加密。由于一个数字变量每次刷新页面都发生变化,导致我取数去生成密码的时候,再post,产生困难。查阅RSA资料的时候发现你有这方面的经验,能否指导一下。谢谢!
看了一下你提供的网站,里面tp参数目测是个时间戳(同文章中的ts参数),应该是为了避免相同的明文产生相同的密文而加的一个“随机数”,所以如果这样的话获取这个值你都不需要去从页面提取了对吧。