在一个风和日丽的上午,领导安排我对某公众号平台开展渗透测试。两天的测试结束后,撰写了本文。本文的重点将放在该公众号前端的AES加密算法的解密上,不足之处敬请包涵,谢谢!
一、信息搜集确定加密算法
(一)在电脑端访问微信公众号
首先打开测试网址,看看长啥样,我提示需要用微信登陆,意料之中,毕竟这是个公众号平台。
一般而言在电脑上搞渗透测试比用模拟器去模拟手机环境方便很多,因此我考虑尽可能在电脑端去测试。那么这种情况一般用两种办法:第一是尝试修改UA请求头,另一种是查看前端代码看看获取了什么信息,是根据什么来判断客户端不是手机微信用户的。这里采用第二种,按F12查看前端代码,全局搜索
Useragent
:
看到前端代码中使用了该字段来获取客户端的信息,因此考虑用浏览器插件来伪造客户端的UA。打开插件,找到相应的选项,粘贴安卓客户端微信UA头部信息:
然后激活该选项:
这里我使用的UA内容是:
Mozilla/5.0 (Linux; Android 10; ELE-AL00 Build/HUAWEIELE-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.62 XWEB/2691 MMWEBSDK/200901 Mobile Safari/537.36 MMWEBID/215 MicroMessenger/7.0.19.1760(0x2700133F) Process/toolsmp WeChat/arm64 NetType/WIFI Language/zh_CN ABI/arm64
该UA可用于模拟安卓手机用户。如果目标要求使用苹果客户端,可以使用以下UA:
Mozilla/5.0 (iPhone; CPU iPhone OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B176 MicroMessenger/4.3.2
本人使用的浏览器插件为UserAgent Switcher
,网络上可以搜一下。另外我会同步上传到本博客,大家有需要的可以去下载。
(二)前端加密算法分析
通过刚才的操作,已经成功用电脑的浏览器访问公众号了:
随便输入了一下账号密码,发现需要保证账号是系统中已注册的才可以(看到这里小伙伴们是不是已经有了一下挖低危漏洞的想法了?没错,尝试进行用户名爆破!看看都有谁注册了账号!),所以去注册一个账号,然后尝试登陆并抓取数据包查看内容:
发现数据包的实体内容疑似泄露了服务器的加密算法:
字段内容显示,加密类型为AES,同时末尾的字段是加密后的数据。因此只要尝试对其进行解密就可以获取明文的账号密码。
从网址中可以看出,此页面没有使用SSL协议对数据进行加密,因此该加密的过程必然是在前端进行。按F12查看前端代码:
看到login文件中,input标签将获取到的内容传给了name参数:
JS文件中一定有变量去获取这个参数,因此全局搜索password:
打开login.js文件,看到与账号密码加密相关的关键代码:
根据代码的内容,判断前端肯定是使用了crypto-js库进行AES加密,ECB、Pkcs7。
二、本地环境AES算法加密、解密测试
下载crypto-js.min.js文件,查看内容,发现代码写的非常复杂,没有任何注释:
考虑直接在本地使用该文件,了解加密逻辑和各参数的值。使用HBuilder工具,将crypto-js.min.js文件加载到JS目录下。经过测试,发现还缺少一个aes.js文件,于是继续在网站中寻找信息。后来发现,有时访问是没有aes.js文件的,但是只要登陆失败一次或者刷新一下页面,plugins/cryptoJs文件夹下就会多出一个aes.js文件:
于是下载aes.js文件,加载到js目录:
注意文件名要跟目标网站上的文件名一致,以免函数调用的时候出错。
接下来复制前端代码中的加密代码,输入一些参数并进行适当简化:
运行结果如下:
实际测试我使用注册的账号来测试的,这里我就简单用随便一些数字来代替了,嘿嘿,个人信息还是要保密的。
然后根据加密算法在脚本上加上解密算法,完整代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>AES加解密测试</title>
<!--引入目标网站crypto-js框架的aes和crypto-js文件-->
<script src="js/aes.js"></script>
<script src="js/crypto-js.min.js"></script>
<script>
var phone ="12300006789";
var pass ="123456";
//对账号密码进行加密
var tmpParams = '{"phone":"'+phone+'","password":"'+pass+'"}';
console.log("加密前的数据:"+tmpParams);
var key = CryptoJS.enc.Utf8.parse("1B4I7NI8B0016E0A0A0A0000A3EEAF2C");
console.log("key的值为:"+key);
var enc = CryptoJS.AES.encrypt(tmpParams ,key,{mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
var encryptData = enc.ciphertext.toString();
console.log("加密后的结果为:"+encryptData);
//对加密后的数据进行解密
var encryptedHexStr = CryptoJS.enc.Hex.parse(encryptData);
var encryptedBase64Str = CryptoJS.enc.Base64.stringify(encryptedHexStr);
var decryptedData = CryptoJS.AES.decrypt(encryptedBase64Str, key, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
var decryptedStr = decryptedData.toString(CryptoJS.enc.Utf8);
console.log("解密后的数据为:"+decryptedStr);
</script>
</head>
<body>
</body>
</html>
运行结果如下:
看到解密后的结果和加密前的结果一模一样,解密成功!
三、小结
本文分享了一个在电脑端访问公众号的方法,一般而言,简单修改UA请求头即可“骗过”前端代码,实现页面的访问,但如果目标增加了其他参数来判断,则需要找出具体是哪些参数在起作用,最好的办法就是查看前端源码,往往会有收获。
其次,本文介绍了crypto-js框架中,AES加密算法的解密方法,虽然网上也有一些文章介绍相关内容,但是读者如果仔细看,会发现,他们往往需要在本地搭建环境,建立相应的目录。这样的话,搭建环境本身就已经很费力了,还需要理解代码。因此本文推荐,简单的事情简单做,直接利用浏览器当运行环境,在本地使用HBuilder工具编写代码进行测试,然后通过浏览器去访问,简单方便。