Yakit热加载

admin 2026-06-15 04:55:20 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文介绍Yakit中热加载技术的应用,该功能允许在WebFuzzer过程中动态加载Yak函数实现自定义fuzztag。作者通过实战案例演示如何利用热加载绕过RSA加密时间戳防重放机制:分析前端加密逻辑后编写热加载函数处理时间戳加密,最终成功实现字典爆破。文档包含具体函数定义、调用格式及注意事项。 综合评分: 87 文章分类: 渗透测试,WEB安全,安全工具,红队,实战经验


cover_image

Yakit热加载

原创

白夜 白夜

Quest安全团队

2026年6月12日 19:20 北京

在小说阅读器读本章

去阅读

官方定义:

什么是热加载?

广义上来说,热加载是一种允许在不停止或重启应用程序的情况下,动态加载或更新特定组件或模块的功能。这种技术常用于开发过程中,提高开发效率和用户体验。

在Yakit 的Web Fuzzer中,热加载是一种高级技术,让 Yak 成为 Web Fuzzer 和用户自定a义代码中的桥梁,它允许我们编写一段 Yak 函数,在 Web Fuzzer 过程中使用,从而实现自定义 fuzztag 或更多功能。

我的理解:

热加载类似于面向切面编程,就是在渗透的过程中,在原本的某个环节上增加一个功能(一段代码),从而增强渗透的能力。可能也比较抽象,但是学过Java的同学应该比较好理解。

热加载里面会涉及到Yaklang的编程,这里提供一下对应的官方文档地址:

https://www.yaklang.com/docs/yak-basic/intro

调用热加载 fuzztag来插入热加载

实际上,我们调用热加载中编写的函数也使用 fuzztag 。我们也可以理解为热加载是一种特殊的 fuzztag ,它的格式为:

{{yak(funcname)}}

当我们需要传入参数时,则格式为

{{yak(funcname|param)}}

需要注意的是,我们传入的参数可以是 fuzztag ,也就是可以编写形如:

{{yak(funcname|{{x(pass_top25)}})}}

热加载函数定义来提供功能

我们可以在热加载页面中编写热加载函数,其函数定义如下:

// 函数名为funcname,参数只有一个,为param,类型是字符串
funcname = func(param) {
    // 返回值可以是字符串或数组
    return param
}

来到靶场,抓包

发现对方有防止重放的功能,没办法修改其中的数据,看前端js代码

发现他会进入一个叫generateRequestData的函数

然后分析代码

function generateRequestData() {

    // 获取用户名和密码
    const username = document.getElementById("username").value;
    const password = document.getElementById("password").value;

    // 生成13位毫秒时间戳,用于防重放校验
    const timestamp = Date.now();

    // RSA公钥(服务端对应保存私钥)
    const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRvA7giwinEkaTYllDYCkzujvi
NH+up0XAKXQot8RixKGpB7nr8AdidEvuo+wVCxZwDK3hlcRGrrqt0Gxqwc11btlM
DSj92Mr3xSaJcshZU8kfj325L8DRh9jpruphHBfh955ihvbednGAvOHOrz3Qy3Cb
ocDbsNeCwNpRxwjIdQIDAQAB
-----END PUBLIC KEY-----`;

    // RSA加密函数
    function rsaEncrypt(data, publicKey) {

        // 创建JSEncrypt对象
        const jsEncrypt = new JSEncrypt();

        // 导入RSA公钥
        jsEncrypt.setPublicKey(publicKey);

        // 对时间戳进行RSA加密
        // JSEncrypt返回值已经是Base64编码后的密文
        const encrypted = jsEncrypt.encrypt(data.toString());

        if (!encrypted) {
            throw new Error("RSA encryption failed.");
        }

        return encrypted;
    }

    // 加密时间戳
    // 实际加密内容:
    // 1780985189238
    // ↓
    // RSA(PKCS#1 v1.5)
    // ↓
    // Base64密文
    let encryptedTimestamp;

    try {
        encryptedTimestamp = rsaEncrypt(timestamp, publicKey);
    } catch (error) {
        console.error("Encryption error:", error);
        return null;
    }

    // 构造请求数据
    // 注意:
    // random字段实际存放的是RSA加密后的时间戳
    const dataToSend = {
        username: username,
        password: password,
        random: encryptedTimestamp
    };

    return dataToSend;
}

function sendLoginRequest(url) {

    // 获取最终请求数据
    const dataToSend = generateRequestData();

    // 发送JSON请求
    fetch(url, {
        method: "POST",
        headers: {
            "Content-Type": "application/json; charset=utf-8"
        },
        body: JSON.stringify(dataToSend)
    })
    .then(response => response.json())
    .then(data => {

        // 服务端处理流程推测:
        // random
        // ↓
        // RSA私钥解密
        // ↓
        // 得到时间戳
        // ↓
        // 判断是否超出时间窗口
        // ↓
        // 验证账号密码

        if (data.success) {
            alert("登录成功");
            window.location.href = "success.html";
        } else {
            alert(data.error || "用户名或密码错误");
        }
    })
    .catch(error => console.error("请求错误:", error));

    closeModal();
}

function closeModal() {
    document.getElementById("modal").style.display = "none";
}

发现他是通过返回一个使用rsa加密的13位的时间戳来验证是否超时,那么写一个热加载

handle = func(ms) {
    pubKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRvA7giwinEkaTYllDYCkzujvi
NH+up0XAKXQot8RixKGpB7nr8AdidEvuo+wVCxZwDK3hlcRGrrqt0Gxqwc11btlM
DSj92Mr3xSaJcshZU8kfj325L8DRh9jpruphHBfh955ihvbednGAvOHOrz3Qy3Cb
ocDbsNeCwNpRxwjIdQIDAQAB
-----END PUBLIC KEY-----`

    enc, _ = codec.RSAEncryptWithPKCS1v15(pubKey, ms)
    return codec.EncodeBase64(enc)
}

调用{{yak(handle|{{timestamp(ms)}})}}

!!!注意千万别写成{{yak(handle|timestamp(ms))}},会导致Yakit把
timestamp(ms) 当成了一个普通字符串参数传给 handle

然后就可以成功添加字典爆破啦


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:Quest安全团队 白夜 白夜《Yakit热加载》

Yakit热加载 网络安全文章

Yakit热加载

文章总结: 本文介绍Yakit中热加载技术的应用,该功能允许在WebFuzzer过程中动态加载Yak函数实现自定义fuzztag。作者通过实战案例演示如何利用热
评论:0   参与:  0