网页端运用JavaScript混淆和对用户名密码加密的手段有哪些?

  最近在处理一个登录爬虫时,遇到了在网页端运用JavaScript混淆和对用户名密码加密的手段,但不是很复杂。

  (大幅度参考%E5%BA%94%E5%AF%B9JS%E5%8A%A0%E5%AF%86.md)

  从何说起

  缘由是在准备用 Python requests 进行模拟登录一个网页,惯例通过抓包发现网页表单往后端 Post 输入的用户名和密码的时候进行了加密;

  我想大概率还是开发人员针对安全考虑,不像某些网页直接往后端明文发送一些敏感数据。但这也对爬虫登录带来了小小的麻烦。

  接下来的操作就是找到负责这一部分功能的代码,然后要么试着模拟代码用方便的语言实现相同的操作,要么是直接把该代码下载下来js 密码加密,用Python相关的工具运行。

  找到它

  在HTML代码中和抓包记录中找到该 JS 函数

  发现,这跟平常的 JS 不一样,这就涉及到一个叫做JavaScript 加密/混淆的概念:

  JavaScript 混淆/加密

  混淆:经过编码将变量和函数原命名改为毫无意义的命名(如function(a,b,c,e,g)等),以防止他人窥视和窃取 Javascript 源代码,也有一定压缩效果。

  加密:一般用eval方法加密,效果与混淆相似,也做到了压缩的效果。

  压缩:删除 Javascript 代码中所有注释、跳格符号、换行符号及无用的空格,从而压缩 JS 文件大小,优化页面加载速度。

  // 被加密混淆后的 JavaScript 代码:

  <pre class="prettyprint linenums prettyprinted" style="">eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!&#39;&#39;.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return&#39;\\w+&#39;};c=1;};while(c--)if(k[c])p=p.replace(new RegExp(&#39;\\b&#39;+e(c)+&#39;\\b&#39;,&#39;g&#39;),k[c]);return p;}(&#39;b 9="o+/=";p q(a){b e="";b 8,5,7="";b f,g,c,1="";b i=0;m{8=a.h(i++);5=a.h(i++);7=a.h(i++);f=8>>2;g=((8&3)4);c=((5&s)6);1=7&t;k(j(5)){c=1=l}v k(j(7)){1=l}e=e+9.d(f)+9.d(g)+9.d(c)+9.d(1);8=5=7="";f=g=c=1=""}u(i> 2;` enc2 = ((chr1 & 3) 4); enc3 = ((chr2 & 15) 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64 } else if (isNaN(chr3)) { enc4 = 64 } output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); chr1 = chr2 = chr3 = ""; enc1 = enc2 = enc3 = enc4 = ""`` } while (i >> import execjs

  >>> print(execjs.get().name)

  Node.js (V8)

  一切准备就绪,那么就试试能不能达到这个效果。

  把要执行的 JS 代码保存成后缀为 .js 的文件

  Python 模拟运行 JavaScript 代码的代码:

  <pre class="prettyprint linenums prettyprinted" style="">import execjsnode = execjs.get()``file = &#39;encode.js&#39;``ctx = node.compile(open(file).read())# 原 JS 函数名 为 encodeInp()user = &#39;encodeInp("{}")&#39;.format(username)pwd = 'encodeInp("{}")'.format(password)``# 网页向后端 POST 的格式result = '{}%%%{}'.format(str(ctx.eval(user)), str(ctx.eval(pwd)))`</pre>

  先通过 execjs.get() 方法声明一个运行环境,然后通过compile()方法来执行刚才保存的函数,接着构造一个字符串传递参数,最后eval()方法模拟执行返回结果。

  有了这个加密后的数据,就能直接用 requests 发送 POST 请求了:

  response = requests.post(url, data={"encoded": result})

  但一般登录后如果还要进行页面跳转选择之类的操作的话js 密码加密,还得用 requests.Session() 方法

  <pre class="prettyprint linenums prettyprinted" style="">import requests`session = requests.Session()session.get(index_url)response = session.post(login_url, data={"encoded":result})if response.status_code: ...`</pre>

文章由官网发布,如若转载,请注明出处:https://www.veimoz.com/1411
0 评论
376

发表评论

!