Files
waf-platform/EdgeNode/internal/nodes/http_request_loader.go
2026-02-04 20:27:13 +08:00

212 lines
7.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
package nodes
import (
"net/http"
)
// serveWAFLoader 提供 WAF Loader JavaScript 文件
func (this *HTTPRequest) serveWAFLoader() {
loaderJS := `(function() {
'use strict';
// 全局队列与执行器
window.__WAF_Q__ = window.__WAF_Q__ || [];
if (!window.__WAF_LOADER__) {
window.__WAF_LOADER__ = {
executing: false,
execute: function() {
if (this.executing) {
return;
}
this.executing = true;
var self = this;
var queue = window.__WAF_Q__ || [];
var runNext = function() {
if (!queue.length) {
self.executing = false;
return;
}
var item = queue.shift();
executeDecryptedCode(item.p, item.m, runNext);
};
runNext();
}
};
}
// 1. XOR 解码为字符串(不压缩,避免顺序问题)
function xorDecodeToString(b64, key) {
try {
var bin = atob(b64);
var out = new Uint8Array(bin.length);
for (var i = 0; i < bin.length; i++) {
out[i] = bin.charCodeAt(i) ^ key.charCodeAt(i % key.length);
}
if (typeof TextDecoder !== 'undefined') {
return new TextDecoder().decode(out);
}
var s = '';
for (var j = 0; j < out.length; j++) {
s += String.fromCharCode(out[j]);
}
return s;
} catch (e) {
console.error('WAF Loader: xor decode failed', e);
return '';
}
}
// 2. XOR 解密
function decryptXOR(payload, key) {
try {
var binary = atob(payload);
var output = [];
var keyLen = key.length;
if (keyLen === 0) {
return '';
}
for (var i = 0; i < binary.length; i++) {
var charCode = binary.charCodeAt(i) ^ key.charCodeAt(i % keyLen);
output.push(String.fromCharCode(charCode));
}
return output.join('');
} catch (e) {
console.error('WAF Loader: Decrypt failed', e);
return '';
}
}
// 3. 执行解密后的代码
function executeDecryptedCode(cipher, meta, done) {
var finish = function() {
if (typeof done === 'function') {
done();
}
};
try {
if (!cipher || !meta || !meta.key) {
console.error('WAF Loader: Missing cipher or meta.key');
finish();
return;
}
if (meta.alg !== 'xor') {
console.error('WAF Loader: Unsupported alg', meta.alg);
finish();
return;
}
// 1. XOR 解码为字符串
var plainJS = xorDecodeToString(cipher, meta.key);
if (!plainJS) {
console.error('WAF Loader: XOR decode failed');
finish();
return;
}
// 2. 执行解密后的代码(同步)
try {
// 使用全局 eval尽量保持和 <script> 一致的作用域
window.eval(plainJS);
// 3. 计算 Token 并握手
calculateAndHandshake(plainJS);
} catch (e) {
console.error('WAF Loader: Execute failed', e);
}
finish();
} catch (e) {
console.error('WAF Loader: Security check failed', e);
finish();
}
}
// 7. Token 计算和握手
function base64EncodeUtf8(str) {
try {
return btoa(unescape(encodeURIComponent(str)));
} catch (e) {
console.error('WAF Loader: base64 encode failed', e);
return '';
}
}
function calculateAndHandshake(decryptedJS) {
try {
// 计算 Token简化示例
var tokenData = decryptedJS.substring(0, Math.min(100, decryptedJS.length)) + Date.now();
var token = base64EncodeUtf8(tokenData).substring(0, 64); // 限制长度
// 发送握手请求
fetch('/waf/handshake', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ token: token })
}).then(function(resp) {
if (resp.ok) {
// 握手成功,设置全局 Token
window.__WAF_TOKEN__ = token;
// 为后续请求设置 Header
if (window.XMLHttpRequest) {
var originalOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
originalOpen.apply(this, arguments);
if (window.__WAF_TOKEN__) {
this.setRequestHeader('X-WAF-TOKEN', window.__WAF_TOKEN__);
}
};
}
// 为 fetch 设置 Header
var originalFetch = window.fetch;
window.fetch = function() {
var args = Array.prototype.slice.call(arguments);
if (args.length > 1 && typeof args[1] === 'object') {
if (!args[1].headers) {
args[1].headers = {};
}
if (window.__WAF_TOKEN__) {
args[1].headers['X-WAF-TOKEN'] = window.__WAF_TOKEN__;
}
} else {
args[1] = {
headers: {
'X-WAF-TOKEN': window.__WAF_TOKEN__ || ''
}
};
}
return originalFetch.apply(this, args);
};
}
}).catch(function(err) {
console.error('WAF Loader: Handshake failed', err);
});
} catch (e) {
console.error('WAF Loader: Calculate token failed', e);
}
}
// 8. 主逻辑
if (window.__WAF_Q__ && window.__WAF_Q__.length) {
window.__WAF_LOADER__.execute();
} else {
// 如果没有加密内容,等待一下再检查(可能是异步加载)
setTimeout(function() {
if (window.__WAF_Q__ && window.__WAF_Q__.length) {
window.__WAF_LOADER__.execute();
}
}, 100);
}
})();`
this.writer.Header().Set("Content-Type", "application/javascript; charset=utf-8")
this.writer.Header().Set("Cache-Control", "public, max-age=3600")
this.writer.WriteHeader(http.StatusOK)
_, _ = this.writer.WriteString(loaderJS)
this.writer.SetOk()
}