当爆破遇到JS加密
字数 1238 2025-08-15 21:33:28
JavaScript加密密码爆破实战指南
1. 背景与概述
在渗透测试过程中,登录界面是最常见的攻击面之一。当遇到以下情况时,传统的爆破方法会遇到困难:
- 密码通过JavaScript在客户端加密
- 系统使用了验证码(但有些验证码可重复利用)
传统方法是通过审计加密算法重新计算后进行爆破,但当面对不同开发人员编写的各种加密方法时,这种方法效率低下。本指南介绍一种更高效的方法:直接利用网站的JavaScript加密文件对密码字典进行加密,然后通过Burp Suite等工具进行爆破。
2. 技术准备
2.1 所需工具
- Python环境
- PyExecJS库
- PhantomJS或其他JavaScript运行时环境
- Burp Suite
2.2 环境搭建
安装PyExecJS:
pip install PyExecJS
# 或
easy_install PyExecJS
安装PhantomJS(MacOS):
brew cask install phantomjs
3. JavaScript加密分析
3.1 常见加密模式
典型的JavaScript加密函数通常具有以下特征:
function encrypt(username, passwordOrgin) {
return hex_sha1(username+hex_sha1(passwordOrgin));
}
3.2 加密函数组成
一个完整的SHA1加密实现通常包含以下组件:
- 主加密函数(
hex_sha1) - 核心算法(
core_sha1) - 辅助函数:
sha1_ft: 根据轮次选择不同的逻辑函数sha1_kt: 根据轮次选择不同的常量safe_add: 安全的32位加法rol: 循环左移AlignSHA1: 数据填充对齐binb2hex: 二进制转十六进制
4. Python实现JavaScript加密
4.1 基本使用方法
import execjs
# 简单评估JS表达式
execjs.eval("'red yellow blue'.split(' ')")
# 编译并调用JS函数
ctx = execjs.compile("""
function add(x, y) {
return x + y;
}
""")
ctx.call("add", 1, 2)
4.2 加密单个密码
def passstring(jsfile, username, password):
print("[+] 正在进行加密,请稍后...")
with open(jsfile, 'r') as strjs:
src = strjs.read()
phantom = execjs.get('PhantomJS') # 调用JS依赖环境
getpass = phantom.compile(src) # 编译执行js脚本
mypass = getpass.call('encrypt', username, password) # 传递参数
print("\033[1;33;40m[+] 加密完成:{}".format(mypass))
4.3 批量加密密码文件
def Encode(jsfile, username, passfile):
print("[+] 正在进行加密,请稍后...")
with open(jsfile, 'r') as strjs:
src = strjs.read()
phantom = execjs.get('PhantomJS')
getpass = phantom.compile(src)
with open(passfile, 'r') as strpass:
for passwd in strpass.readlines():
passwd = passwd.strip()
mypass = getpass.call('encrypt', username, passwd)
with open("pass_encode.txt", 'a+') as p:
p.write(mypass+"\n")
print("\033[1;33;40m [+] 加密完成")
5. 完整脚本实现
#coding:utf-8
import execjs
import click
import threading
def info():
print("\033[1;33;40m [+] Python调用JS加密password文件内容 =")
print("\033[1;33;40m [+] Explain: YaunSky =")
print("\033[1;33;40m [+] https://github.com/yaunsky =")
# 对密码文件进行加密,密文在当前目录下的pass_encode.txt中
def Encode(jsfile, username, passfile):
print("[+] 正在进行加密,请稍后...")
with open(jsfile, 'r') as strjs:
src = strjs.read()
phantom = execjs.get('PhantomJS')
getpass = phantom.compile(src)
with open(passfile, 'r') as strpass:
for passwd in strpass.readlines():
passwd = passwd.strip()
mypass = getpass.call('encrypt', username, passwd)
with open("pass_encode.txt", 'a+') as p:
p.write(mypass+"\n")
print("\033[1;33;40m [+] 加密完成")
# 对单一密码进行加密
def passstring(jsfile, username, password):
print("[+] 正在进行加密,请稍后...")
with open(jsfile, 'r') as strjs:
src = strjs.read()
phantom = execjs.get('PhantomJS')
getpass = phantom.compile(src)
mypass = getpass.call('encrypt', username, password)
print("\033[1;33;40m[+] 加密完成:{}".format(mypass))
@click.command()
@click.option("-J", "--jsfile", help='JS 加密文件')
@click.option("-u", "--username", help="登陆用户名")
@click.option("-P", "--passfile", help="明文密码文件")
@click.option("-p", "--password", help="明文密码字符串")
def main(jsfile, username, passfile, password):
info()
if jsfile != None and passfile != None and username != None:
t = threading.Thread(target=Encode, args=(jsfile, username, passfile))
t.start()
elif jsfile != None and password != None and username != None:
passstring(jsfile, username, password)
else:
print("python3 encode.py --help")
if __name__ == "__main__":
main()
6. 使用说明
6.1 单一密码加密
python3 encode.py -J enpassword.js -u admin -p admin123
6.2 批量密码加密
python3 encode.py -J enpassword.js -u admin -P password.txt
6.3 参数说明
-J/--jsfile: 指定JavaScript加密文件路径-u/--username: 指定用户名-P/--passfile: 指定明文密码文件路径-p/--password: 指定单个明文密码字符串
7. 性能优化
7.1 多线程处理
对于大型密码字典,添加多线程支持:
t = threading.Thread(target=Encode, args=(jsfile, username, passfile))
t.start()
7.2 通用模板
针对不同的JS加密方法,可以使用以下模板进行适配:
def Encode(参数1, 参数2, 参数3, ...):
print("[+] 正在进行加密,请稍后...")
with open(JS加密文件,'r') as strjs:
src = strjs.read()
phantom = execjs.get('PhantomJS')
getpass = phantom.compile(src)
with open(参数, 'r') as strpass: # 参数:明文密码文件,进行遍历加密
for passwd in strpass.readlines():
passwd = passwd.strip()
mypass = getpass.call(
JS加密文件中的加密函数,
参数, 参数, 参数 # JS加密文件中加密函数所需要的参数值
)
with open("pass_encode.txt", 'a+') as p:
p.write(mypass+"\n")
print("\033[1;33;40m [+] 加密完成")
8. 实际应用流程
- 识别加密:通过浏览器开发者工具分析登录请求,确认密码是否经过JavaScript加密
- 提取JS:从网页源代码或单独JS文件中找到加密函数
- 测试加密:使用单个密码测试加密脚本是否正确工作
- 批量加密:对密码字典进行批量加密
- 爆破攻击:使用Burp Suite等工具导入加密后的密码进行爆破
9. 注意事项
- 合法性:仅在获得授权的情况下进行测试
- 验证码:虽然有些系统的验证码可重复利用,但并非全部
- 性能:JavaScript加密过程可能较慢,大型字典需要耐心等待
- 适应性:不同系统加密方法可能不同,需要调整脚本以适应具体加密逻辑
通过这种方法,可以绕过复杂的JavaScript加密审计过程,直接利用网站自身的加密逻辑进行密码爆破,大大提高渗透测试效率。