wormclaude 1.0.181 → 1.0.182
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/pentest.js +26 -5
- package/dist/theme.js +1 -1
- package/dist/tools.js +16 -7
- package/package.json +1 -1
package/dist/pentest.js
CHANGED
|
@@ -41,8 +41,27 @@ function hostOf(u) {
|
|
|
41
41
|
return '';
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
+
// İstek başlıklarına kullanıcı oturumunu (auth) birleştir. Sunucunun spec'i temel; auth ÜSTE biner
|
|
45
|
+
// (Cookie + Authorization), böylece her istek login-arkası koşar. Sunucu zaten Cookie/Authorization
|
|
46
|
+
// koyduysa kullanıcınınki kazanır (gerçek oturum). allowed-host SSRF guard'ı değişmez.
|
|
47
|
+
export function _mergeAuth(reqHeaders, auth) {
|
|
48
|
+
if (!auth || (!auth.cookie && !auth.authHeader && !auth.headers))
|
|
49
|
+
return reqHeaders;
|
|
50
|
+
const h = { ...(reqHeaders || {}) };
|
|
51
|
+
if (auth.cookie) {
|
|
52
|
+
const existing = h['Cookie'] || h['cookie'];
|
|
53
|
+
h['Cookie'] = existing ? `${existing}; ${auth.cookie}` : auth.cookie;
|
|
54
|
+
delete h['cookie'];
|
|
55
|
+
}
|
|
56
|
+
if (auth.authHeader)
|
|
57
|
+
h['Authorization'] = auth.authHeader;
|
|
58
|
+
if (auth.headers)
|
|
59
|
+
for (const [k, v] of Object.entries(auth.headers))
|
|
60
|
+
h[k] = v;
|
|
61
|
+
return h;
|
|
62
|
+
}
|
|
44
63
|
// Tek bir istek-spec'ini yerelde çalıştır. allowed dışı host → atlanır (SSRF koruması).
|
|
45
|
-
async function execReq(req, allowed) {
|
|
64
|
+
async function execReq(req, allowed, auth) {
|
|
46
65
|
const t0 = Date.now();
|
|
47
66
|
const h = hostOf(req.url);
|
|
48
67
|
if (!allowed.has(h)) {
|
|
@@ -51,7 +70,7 @@ async function execReq(req, allowed) {
|
|
|
51
70
|
try {
|
|
52
71
|
const r = await fetch(req.url, {
|
|
53
72
|
method: req.method || 'GET',
|
|
54
|
-
headers: req.headers,
|
|
73
|
+
headers: _mergeAuth(req.headers, auth),
|
|
55
74
|
body: req.body,
|
|
56
75
|
redirect: req.follow === false ? 'manual' : 'follow', // open-redirect vb. için Location'ı görmek
|
|
57
76
|
signal: AbortSignal.timeout(Math.max(3, req.timeout || 20) * 1000),
|
|
@@ -71,8 +90,10 @@ async function execReq(req, allowed) {
|
|
|
71
90
|
}
|
|
72
91
|
}
|
|
73
92
|
// Tam akış: plan al → her round'da istekleri yerelde at → /exec ile analiz ettir → done'a dek döngü.
|
|
74
|
-
export async function runPentest(config, tool, target, scopeAck, log) {
|
|
75
|
-
const
|
|
93
|
+
export async function runPentest(config, tool, target, scopeAck, log, auth) {
|
|
94
|
+
const _authed = !!(auth && (auth.cookie || auth.authHeader || auth.headers));
|
|
95
|
+
// authenticated: SUNUCUYA SADECE BAYRAK gider (login-arkası crawl/POST planlasın diye) — sır/cookie DEĞİL.
|
|
96
|
+
const plan = await postJson(config, '/pentest/plan', { tool, target, scope_ack: scopeAck, authenticated: _authed }, 15000);
|
|
76
97
|
if (!plan.ok)
|
|
77
98
|
return { ok: false, reason: plan.reason, plan };
|
|
78
99
|
const allowed = new Set((plan.allowed_hosts || [plan.host || '']).map((x) => x.toLowerCase()));
|
|
@@ -86,7 +107,7 @@ export async function runPentest(config, tool, target, scopeAck, log) {
|
|
|
86
107
|
const CONC = 6;
|
|
87
108
|
for (let i = 0; i < requests.length; i += CONC) {
|
|
88
109
|
const batch = requests.slice(i, i + CONC);
|
|
89
|
-
const rs = await Promise.all(batch.map((req) => execReq(req, allowed)));
|
|
110
|
+
const rs = await Promise.all(batch.map((req) => execReq(req, allowed, auth)));
|
|
90
111
|
responses.push(...rs);
|
|
91
112
|
}
|
|
92
113
|
report = await postJson(config, '/pentest/exec', { job_id: plan.job_id, responses }, 30000);
|
package/dist/theme.js
CHANGED
package/dist/tools.js
CHANGED
|
@@ -226,12 +226,14 @@ export const toolSchemas = [
|
|
|
226
226
|
type: 'function',
|
|
227
227
|
function: {
|
|
228
228
|
name: 'SecurityScan',
|
|
229
|
-
description: "Run an AUTHORIZED security scan with WormClaude's own server-side engine (no external tools, no manual payloads). Use THIS — never shell/curl/Invoke-WebRequest — whenever the user asks to scan/test a target (\"tara\", \"scan\", \"xss tara\", \"sqli\", \"recon\", \"açık bul\", \"zafiyet tara\", \"tam kapsamlı tara\"). For a FULL/comprehensive scan use tool='full' ONCE — it deterministically runs recon+XSS+SQLi in code and returns ONE consolidated report (do NOT chain recon/xss/sqli yourself, that loops). For a single check use recon/xss/sqli. For xss/sqli give a PARAMETERIZED url; for recon/full give a domain. Requires authorized-researcher level (3+); traffic exits the user's IP — only authorized targets.",
|
|
229
|
+
description: "Run an AUTHORIZED security scan with WormClaude's own server-side engine (no external tools, no manual payloads). Use THIS — never shell/curl/Invoke-WebRequest — whenever the user asks to scan/test a target (\"tara\", \"scan\", \"xss tara\", \"sqli\", \"recon\", \"açık bul\", \"zafiyet tara\", \"tam kapsamlı tara\"). For a FULL/comprehensive scan use tool='full' ONCE — it deterministically runs recon+XSS+SQLi in code and returns ONE consolidated report (do NOT chain recon/xss/sqli yourself, that loops). For a single check use recon/xss/sqli. For xss/sqli give a PARAMETERIZED url; for recon/full give a domain. For AUTHENTICATED / behind-login scanning, pass the user's session via `cookie` (and/or `auth_header`) — every request is then sent logged-in, so pages and parameters behind the login are reached. Requires authorized-researcher level (3+); traffic exits the user's IP — only authorized targets.",
|
|
230
230
|
parameters: {
|
|
231
231
|
type: 'object',
|
|
232
232
|
properties: {
|
|
233
233
|
tool: { type: 'string', enum: ['full', 'recon', 'scan', 'xss', 'sqli', 'dirscan'], description: 'full → tam kapsamlı (recon+xss+sqli tek seferde, kapsamlı tarama için BUNU kullan); recon/scan/dirscan → domain; xss/sqli → parameterized URL' },
|
|
234
234
|
target: { type: 'string', description: 'Domain for recon/scan/dirscan (example.com) OR parameterized URL for xss/sqli (https://example.com/p?id=1)' },
|
|
235
|
+
cookie: { type: 'string', description: 'Optional. Session cookie for AUTHENTICATED / behind-login scanning, e.g. "sessionid=abc123; csrftoken=xyz". The user copies it from their logged-in browser (DevTools → Application → Cookies, or the Cookie request header). Sent only to the target from the user IP — never stored on the server. Provide it whenever the user wants to scan pages behind a login.' },
|
|
236
|
+
auth_header: { type: 'string', description: 'Optional. Authorization header value for token-based authenticated scanning, e.g. "Bearer eyJhbGci..." or "Basic dXNlcjpwYXNz". Use instead of / together with cookie when the site authenticates via a token header.' },
|
|
235
237
|
},
|
|
236
238
|
required: ['tool', 'target'],
|
|
237
239
|
},
|
|
@@ -737,10 +739,17 @@ async function execOne(call, hooks) {
|
|
|
737
739
|
}
|
|
738
740
|
if (tool === 'scan')
|
|
739
741
|
tool = 'recon'; // "scan" genel tarama → motorun bildiği "recon" (slash ile aynı)
|
|
742
|
+
// AUTHENTICATED / login-arkası: kullanıcı session cookie / auth header verdiyse her isteğe enjekte
|
|
743
|
+
// edilir (sır SUNUCUYA gitmez, sadece hedefe kullanıcı IP'sinden). Cache key'e auth-parmakizi ekle ki
|
|
744
|
+
// anonim tarama sonucu authenticated tarama için (veya tersi) yeniden kullanılmasın.
|
|
745
|
+
const _cookie = String(args?.cookie || '').trim();
|
|
746
|
+
const _authHeader = String(args?.auth_header || '').trim();
|
|
747
|
+
const _auth = (_cookie || _authHeader) ? { cookie: _cookie || undefined, authHeader: _authHeader || undefined } : undefined;
|
|
748
|
+
const _authTag = _auth ? '|auth' : '';
|
|
740
749
|
// FULL: tam kapsamlı tarama TEK ÇAĞRIDA — model orkestrasyona girmesin (döngü olur). Kod
|
|
741
750
|
// deterministik olarak recon → xss → sqli koşar, TEK konsolide rapor döner.
|
|
742
751
|
if (tool === 'full' || tool === 'fullscan') {
|
|
743
|
-
const _fk = 'full|' + target.toLowerCase();
|
|
752
|
+
const _fk = 'full|' + target.toLowerCase() + _authTag;
|
|
744
753
|
const _fc = _scanCache.get(_fk);
|
|
745
754
|
if (_fc && Date.now() - _fc.t < 120000) {
|
|
746
755
|
return { ok: false, args, output: `[ALREADY-SCANNED] full scan "${target}" already ran — findings are above. Do NOT call SecurityScan again; summarize the results in text.` };
|
|
@@ -748,14 +757,14 @@ async function execOne(call, hooks) {
|
|
|
748
757
|
try {
|
|
749
758
|
const { runPentest } = await import('./pentest.js');
|
|
750
759
|
const all = [];
|
|
751
|
-
let rpt = `Tam kapsamlı tarama — ${target}\n`;
|
|
760
|
+
let rpt = `Tam kapsamlı tarama — ${target}${_auth ? ' (authenticated / login-arkası — oturum enjekte edildi)' : ''}\n`;
|
|
752
761
|
for (const _t of ['recon', 'xss', 'sqli']) {
|
|
753
762
|
if (hooks?.signal?.aborted) {
|
|
754
763
|
rpt += `\n[STOPPED] kullanıcı durdurdu (Esc) — kalan taramalar atlandı.`;
|
|
755
764
|
break;
|
|
756
765
|
}
|
|
757
766
|
try {
|
|
758
|
-
const o = await runPentest(cfg(), _t, target, true, () => { });
|
|
767
|
+
const o = await runPentest(cfg(), _t, target, true, () => { }, _auth);
|
|
759
768
|
if (o?.ok) {
|
|
760
769
|
const ff = o.report?.findings || [];
|
|
761
770
|
all.push(...ff.map((x) => ({ ...x, scan: _t })));
|
|
@@ -782,7 +791,7 @@ async function execOne(call, hooks) {
|
|
|
782
791
|
_scanCache.set(_fk, { out: rpt, t: _now });
|
|
783
792
|
// Alt tarama tiplerini de cache'le → full sonrası model tek tek recon/xss/sqli çağıramaz (gereksiz tekrar).
|
|
784
793
|
for (const _t of ['recon', 'xss', 'sqli'])
|
|
785
|
-
_scanCache.set(_t + '|' + target.toLowerCase(), { out: rpt, t: _now });
|
|
794
|
+
_scanCache.set(_t + '|' + target.toLowerCase() + _authTag, { out: rpt, t: _now });
|
|
786
795
|
return { ok: true, output: rpt, args };
|
|
787
796
|
}
|
|
788
797
|
catch (e) {
|
|
@@ -790,7 +799,7 @@ async function execOne(call, hooks) {
|
|
|
790
799
|
}
|
|
791
800
|
}
|
|
792
801
|
// DÖNGÜ-KIRICI: aynı tarama 2 dk içinde tekrar → yeniden koşma, önceki sonuç + "yeniden tarama" notu.
|
|
793
|
-
const _ck = tool + '|' + target.toLowerCase();
|
|
802
|
+
const _ck = tool + '|' + target.toLowerCase() + _authTag;
|
|
794
803
|
const _cached = _scanCache.get(_ck);
|
|
795
804
|
if (_cached && Date.now() - _cached.t < 120000) {
|
|
796
805
|
// SADECE kısa DUR notu — bulguları TEKRAR verme (yoksa model onları yeniden yazıp tekrar çağırır).
|
|
@@ -798,7 +807,7 @@ async function execOne(call, hooks) {
|
|
|
798
807
|
}
|
|
799
808
|
try {
|
|
800
809
|
const { runPentest } = await import('./pentest.js');
|
|
801
|
-
const out = await runPentest(cfg(), tool, target, true, () => { });
|
|
810
|
+
const out = await runPentest(cfg(), tool, target, true, () => { }, _auth);
|
|
802
811
|
if (!out?.ok) {
|
|
803
812
|
const reason = out?.reason || out?.plan?.reason || 'error';
|
|
804
813
|
const tip = reason === 'trust_required' ? ' (Doğrulanmış Araştırmacı / seviye 3+ gerekir: /dogrula)'
|