wormclaude 1.0.192 → 1.0.194

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/commands.js CHANGED
@@ -61,6 +61,9 @@ export const COMMANDS = [
61
61
  { name: '/report', desc: 'son taramadan profesyonel pentest raporu üret (CVSS/etki/çözüm, dosyaya yazar)' },
62
62
  { name: '/fullscan', desc: '[seviye 3+] tam kapsamlı DETERMİNİSTİK tarama: recon+XSS+SQLi tek komutta: /fullscan <hedef>' },
63
63
  { name: '/audit', desc: 'kaynak kod güvenlik denetimi (SAST — sır/açık/CVE, yerel): /audit [klasör]' },
64
+ { name: '/jwt', desc: 'JWT token güvenlik analizi (alg=none/zayıf-secret/expiry/claim, yerel): /jwt <token>' },
65
+ { name: '/spray', desc: 'login formuna parola-spray (yetkili test, trust 3+): /spray <login-url> [kullanıcı]' },
66
+ { name: '/defaultcreds', desc: 'login\'e varsayılan kimlik denemesi (admin/admin vb, trust 3+): /defaultcreds <login-url>' },
64
67
  { name: '/exploit', desc: 'yetkili testte doğrulanmış PoC üret: /exploit <cve|açıklama>' },
65
68
  { name: '/harden', desc: 'savunma çıktısı üret (YARA/Sigma + yama önerisi): /harden <hedef|tehdit>' },
66
69
  { name: '/phish', desc: '[yetkili] phishing simülasyonu: pretext + e-posta şablonu: /phish <hedef|senaryo>' },
package/dist/jwt.js ADDED
@@ -0,0 +1,102 @@
1
+ // JWT güvenlik analizi — token decode + zafiyet tespiti. YEREL (ağ yok, deterministik).
2
+ // alg=none bypass, zayıf HMAC secret (sözlük denemesi), expiry, hassas claim, alg-confusion.
3
+ import crypto from 'node:crypto';
4
+ // Yaygın/varsayılan JWT secret'ları (zayıf imza tespiti için — gerçek kırma değil, hızlı kontrol)
5
+ const COMMON_SECRETS = [
6
+ 'secret', 'password', '123456', 'changeme', 'jwt_secret', 'jwtsecret', 'your-256-bit-secret',
7
+ 'your_jwt_secret', 'key', 'admin', 'test', 'supersecret', 'super_secret', 'secretkey', 'secret_key',
8
+ 'privatekey', 'private_key', 'token', 'qwerty', 'letmein', 'mysecret', 'mysecretkey', 's3cr3t',
9
+ 'P@ssw0rd', 'default', 'dev', 'development', 'prod', 'production', 'shhhh', 'access_secret',
10
+ 'refresh_secret', 'auth_secret', 'app_secret', 'jwtkey', 'HS256', 'null', '0', 'password123',
11
+ ];
12
+ function _b64urlToBuf(s) {
13
+ s = s.replace(/-/g, '+').replace(/_/g, '/');
14
+ while (s.length % 4)
15
+ s += '=';
16
+ return Buffer.from(s, 'base64');
17
+ }
18
+ function _b64urlJson(s) { return JSON.parse(_b64urlToBuf(s).toString('utf8')); }
19
+ const HMAC_ALG = { HS256: 'sha256', HS384: 'sha384', HS512: 'sha512' };
20
+ function _tryCrack(alg, signingInput, sigB64url) {
21
+ const h = HMAC_ALG[alg.toUpperCase()];
22
+ if (!h)
23
+ return null;
24
+ for (const sec of COMMON_SECRETS) {
25
+ const mac = crypto.createHmac(h, sec).update(signingInput).digest('base64')
26
+ .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
27
+ if (mac === sigB64url)
28
+ return sec;
29
+ }
30
+ return null;
31
+ }
32
+ const SENSITIVE_CLAIM = /(pass|pwd|şifre|sifre|secret|ssn|credit|card|cvv|api[_-]?key|private)/i;
33
+ export function analyzeJwt(token) {
34
+ const findings = [];
35
+ const t = (token || '').trim().replace(/^Bearer\s+/i, '');
36
+ const parts = t.split('.');
37
+ if (parts.length < 2)
38
+ return { ok: false, findings: [], error: 'Geçerli bir JWT değil (nokta-ayrımlı 2-3 parça bekleniyor).' };
39
+ let header, payload;
40
+ try {
41
+ header = _b64urlJson(parts[0]);
42
+ }
43
+ catch {
44
+ return { ok: false, findings: [], error: 'JWT header decode edilemedi.' };
45
+ }
46
+ try {
47
+ payload = _b64urlJson(parts[1]);
48
+ }
49
+ catch {
50
+ return { ok: false, findings: [], error: 'JWT payload decode edilemedi.' };
51
+ }
52
+ const alg = String(header?.alg || '').trim();
53
+ const sig = parts[2] || '';
54
+ // 1) alg=none → imza yok = tam bypass
55
+ if (/^none$/i.test(alg) || (!sig && parts.length === 3)) {
56
+ findings.push({ severity: 'critical', title: 'alg=none / imza yok', cwe: 'CWE-347',
57
+ detail: 'Token imzasız kabul ediliyorsa saldırgan payload\'ı (rol/kullanıcı) serbestçe değiştirir. Sunucu alg=none\'ı REDDETMELİ; izin verilen algoritmalar allow-list olmalı.' });
58
+ }
59
+ // 2) HMAC zayıf secret denemesi
60
+ if (HMAC_ALG[alg.toUpperCase()] && sig) {
61
+ const cracked = _tryCrack(alg, parts[0] + '.' + parts[1], sig);
62
+ if (cracked != null) {
63
+ findings.push({ severity: 'critical', title: `Zayıf HMAC secret KIRILDI: "${cracked}"`, cwe: 'CWE-326',
64
+ detail: 'İmza zayıf/varsayılan bir secret ile üretilmiş. Saldırgan bu secret ile GEÇERLI token forge eder (herhangi bir kullanıcı/rol). Güçlü, rastgele 256-bit+ secret kullan ve rotate et.' });
65
+ // crackedSecret döndür
66
+ findings._cracked = cracked;
67
+ }
68
+ }
69
+ // 3) RS/ES → alg-confusion notu
70
+ if (/^(RS|ES|PS)/i.test(alg)) {
71
+ findings.push({ severity: 'info', title: `Asimetrik imza (${alg}) — alg-confusion riski`, cwe: 'CWE-347',
72
+ detail: 'Sunucu algoritmayı sabitlemiyorsa, public key\'i HMAC secret\'ı olarak kullanan alg-confusion (RS256→HS256) saldırısı denenebilir. Sunucu beklenen algoritmayı KATI doğrulamalı.' });
73
+ }
74
+ // 4) expiry / nbf
75
+ const now = Math.floor(Date.now() / 1000);
76
+ if (payload?.exp == null) {
77
+ findings.push({ severity: 'low', title: 'exp (son kullanma) yok', cwe: 'CWE-613',
78
+ detail: 'Token süresiz geçerli → çalınırsa kalıcı erişim. Kısa exp + refresh token kullan.' });
79
+ }
80
+ else if (Number(payload.exp) < now) {
81
+ findings.push({ severity: 'info', title: 'Token süresi DOLMUŞ', detail: `exp=${new Date(Number(payload.exp) * 1000).toISOString()} (geçmiş). Sunucu expired token\'ı reddetmeli.` });
82
+ }
83
+ // 5) hassas claim'ler
84
+ for (const k of Object.keys(payload || {})) {
85
+ if (SENSITIVE_CLAIM.test(k)) {
86
+ findings.push({ severity: 'medium', title: `Hassas claim payload'da: "${k}"`, cwe: 'CWE-522',
87
+ detail: 'JWT payload base64\'tür, ŞIFRELI DEĞIL — herkes okuyabilir. Parola/sır/PII token içine konmamalı.' });
88
+ }
89
+ }
90
+ // 6) privilege claim notu (tampering hedefi)
91
+ const privKeys = Object.keys(payload || {}).filter((k) => /^(role|roles|admin|is_admin|scope|scopes|permissions|priv|group)$/i.test(k));
92
+ if (privKeys.length) {
93
+ findings.push({ severity: 'info', title: `Yetki claim'leri: ${privKeys.join(', ')}`,
94
+ detail: 'Sunucu imzayı düzgün doğrulamıyorsa bu alanlar yetki yükseltme için manipüle edilir (alg=none / zayıf-secret ile birlikte kritik).' });
95
+ }
96
+ if (!findings.length)
97
+ findings.push({ severity: 'info', title: 'Belirgin JWT zafiyeti yok', detail: 'alg sağlam, secret yaygın listede değil, exp var, hassas claim yok. (Derin secret-kırma için hashcat -m 16500 öner.)' });
98
+ const order = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };
99
+ findings.sort((a, b) => order[a.severity] - order[b.severity]);
100
+ const cracked = findings._cracked;
101
+ return { ok: true, header, payload, findings, crackedSecret: cracked };
102
+ }
package/dist/pentest.js CHANGED
@@ -243,10 +243,10 @@ async function execReq(req, allowed, auth) {
243
243
  }
244
244
  }
245
245
  // Tam akış: plan al → her round'da istekleri yerelde at → /exec ile analiz ettir → done'a dek döngü.
246
- export async function runPentest(config, tool, target, scopeAck, log, auth) {
246
+ export async function runPentest(config, tool, target, scopeAck, log, auth, extra) {
247
247
  const _authed = !!(auth && (auth.cookie || auth.authHeader || auth.headers));
248
248
  // authenticated: SUNUCUYA SADECE BAYRAK gider (login-arkası crawl/POST planlasın diye) — sır/cookie DEĞİL.
249
- const plan = await postJson(config, '/pentest/plan', { tool, target, scope_ack: scopeAck, authenticated: _authed }, 15000);
249
+ const plan = await postJson(config, '/pentest/plan', { tool, target, scope_ack: scopeAck, authenticated: _authed, extra: extra || undefined }, 15000);
250
250
  if (!plan.ok)
251
251
  return { ok: false, reason: plan.reason, plan };
252
252
  const allowed = new Set((plan.allowed_hosts || [plan.host || '']).map((x) => x.toLowerCase()));
package/dist/theme.js CHANGED
@@ -16,4 +16,4 @@ export const theme = {
16
16
  synType: '#a78bfa', // tip/sınıf adları, sabitler
17
17
  synProp: '#e0e0e0', // özellik/anahtar adları
18
18
  };
19
- export const VERSION = '1.0.192';
19
+ export const VERSION = '1.0.194';
package/dist/tools.js CHANGED
@@ -230,7 +230,7 @@ export const toolSchemas = [
230
230
  parameters: {
231
231
  type: 'object',
232
232
  properties: {
233
- tool: { type: 'string', enum: ['full', 'recon', 'scan', 'xss', 'sqli', 'dirscan', 'idor', 'portscan', 'osint', 'cloudscan'], description: 'full → tam kapsamlı web taraması; recon/scan/dirscan/portscan/osint/cloudscan → domain/host/şirket; xss/sqli/idor → parameterized URL. portscan = TCP port/servis. osint = DNS + e-posta güvenliği (SPF/DMARC). cloudscan = açık bulut bucket keşfi (S3/GCP/Azure şirket/domain adından aday üretip public erişim test eder; "bucket tara"/"s3 tara"/"açık depolama"/"cloud" denince)' },
233
+ tool: { type: 'string', enum: ['full', 'recon', 'scan', 'xss', 'sqli', 'dirscan', 'idor', 'portscan', 'osint', 'cloudscan', 'spray', 'defaultcreds'], description: 'full → tam kapsamlı web taraması; recon/scan/dirscan/portscan/osint/cloudscan → domain/host/şirket; xss/sqli/idor → parameterized URL. portscan = TCP port/servis. osint = DNS + e-posta güvenliği (SPF/DMARC). cloudscan = açık bulut bucket keşfi (S3/GCP/Azure). spray = login formuna parola-spray (target = login URL, username param ile; "parola dene"/"spray"/"brute" denince, trust 3+). defaultcreds = login\'e varsayılan kimlikler (admin/admin vb.) dene (target = login URL, trust 3+)' },
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
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
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.' },
@@ -256,6 +256,20 @@ export const toolSchemas = [
256
256
  },
257
257
  },
258
258
  },
259
+ {
260
+ type: 'function',
261
+ function: {
262
+ name: 'JwtAudit',
263
+ description: "Analyze a JWT (JSON Web Token) for security weaknesses, locally. Use when the user pastes/asks about a token (\"bu jwt güvenli mi\", \"token analiz et\", \"jwt incele\", \"bu token'da açık var mı\"). Decodes header+payload and checks: alg=none bypass, weak/default HMAC secret (dictionary test), missing/expired exp, sensitive claims in payload, alg-confusion (RS256→HS256), privilege claims. Fully LOCAL — token never leaves the machine. Returns decoded claims + findings.",
264
+ parameters: {
265
+ type: 'object',
266
+ properties: {
267
+ token: { type: 'string', description: 'The JWT string (eyJ...eyJ...sig). "Bearer " prefix is stripped automatically.' },
268
+ },
269
+ required: ['token'],
270
+ },
271
+ },
272
+ },
259
273
  {
260
274
  type: 'function',
261
275
  function: {
@@ -640,7 +654,7 @@ const computerToolSchemas = [
640
654
  // çağırıp işi yapar, planı ekrana basmaz. (Gerekirse buraya yeni araç eklenir.)
641
655
  const CORE_TOOLS = new Set([
642
656
  'Bash', 'PowerShell', 'Read', 'Write', 'Edit', 'Glob', 'Grep',
643
- 'WebFetch', 'WebSearch', 'Sleep', 'SecurityScan', 'CodeAudit',
657
+ 'WebFetch', 'WebSearch', 'Sleep', 'SecurityScan', 'CodeAudit', 'JwtAudit',
644
658
  'TaskOutput', // uzun komutları arka planda çalıştırıp bitişini yoklamak için (run_in_background)
645
659
  'AskUserQuestion', // GERİ EKLENDİ: FLAT şema (options: string[]) ile 32B temiz çağrı üretiyor
646
660
  // (test edildi). Eski degenere NESTED şemadandı ([{label,description}]). Handler string→{label}
@@ -669,6 +683,7 @@ const TOOL_META = {
669
683
  Scroll: { needsPermission: true, validate: (a) => (a && a.direction ? null : 'direction gerekli') },
670
684
  WebSearch: { readOnly: true, validate: (a) => (a && a.query ? null : 'query gerekli') },
671
685
  CodeAudit: { readOnly: true, concurrencySafe: true },
686
+ JwtAudit: { readOnly: true, concurrencySafe: true, validate: (a) => (a && a.token ? null : 'token gerekli') },
672
687
  TodoWrite: { readOnly: true, validate: (a) => (a && Array.isArray(a.todos) ? null : 'todos dizisi gerekli') },
673
688
  SaveMemory: { validate: (a) => (a && a.fact && String(a.fact).trim() ? null : 'fact gerekli') },
674
689
  PowerShell: { needsPermission: true, validate: (a) => (a && a.command ? null : 'command gerekli') },
@@ -752,7 +767,7 @@ async function execOne(call, hooks) {
752
767
  if (call.name === 'SecurityScan') {
753
768
  let tool = String(args?.tool || '').toLowerCase().trim();
754
769
  const target = String(args?.target || '').trim();
755
- if (!['recon', 'scan', 'xss', 'sqli', 'dirscan', 'idor', 'portscan', 'osint', 'cloud', 'cloudscan', 'full', 'fullscan'].includes(tool) || !target) {
770
+ if (!['recon', 'scan', 'xss', 'sqli', 'dirscan', 'idor', 'portscan', 'osint', 'cloud', 'cloudscan', 'spray', 'credspray', 'defaultcreds', 'full', 'fullscan'].includes(tool) || !target) {
756
771
  return { ok: false, output: 'SecurityScan: tool (recon|scan|xss|sqli|dirscan|full) ve target gerekli.', args };
757
772
  }
758
773
  if (tool === 'scan')
@@ -906,7 +921,8 @@ async function execOne(call, hooks) {
906
921
  }
907
922
  try {
908
923
  const { runPentest } = await import('./pentest.js');
909
- const out = await runPentest(cfg(), tool, target, true, () => { }, _auth);
924
+ const _extra = ['spray', 'credspray', 'defaultcreds'].includes(tool) ? { username: _username || 'admin' } : undefined;
925
+ const out = await runPentest(cfg(), tool, target, true, () => { }, _auth, _extra);
910
926
  if (!out?.ok) {
911
927
  const reason = out?.reason || out?.plan?.reason || 'error';
912
928
  const tip = reason === 'trust_required' ? ' (Doğrulanmış Araştırmacı / seviye 3+ gerekir: /dogrula)'
@@ -965,6 +981,27 @@ async function execOne(call, hooks) {
965
981
  return { ok: false, output: 'Kod denetimi hatası: ' + (e?.message || e), args };
966
982
  }
967
983
  }
984
+ // 3.46) JWT güvenlik analizi (YEREL; token sunucuya gitmez)
985
+ if (call.name === 'JwtAudit') {
986
+ try {
987
+ const { analyzeJwt } = await import('./jwt.js');
988
+ const r = analyzeJwt(String(args?.token || ''));
989
+ if (!r.ok)
990
+ return { ok: false, output: 'JWT analizi: ' + (r.error || 'çözümlenemedi'), args };
991
+ let out = 'JWT analizi\n';
992
+ out += 'header: ' + JSON.stringify(r.header) + '\n';
993
+ out += 'payload: ' + JSON.stringify(r.payload) + '\n';
994
+ if (r.crackedSecret != null)
995
+ out += `⚠ HMAC secret KIRILDI: "${r.crackedSecret}"\n`;
996
+ out += `${r.findings.length} bulgu:\n`;
997
+ out += r.findings.map((f) => `[${f.severity.toUpperCase()}]${f.cwe ? ' ' + f.cwe : ''} ${f.title}\n ${f.detail}`).join('\n');
998
+ out += '\n[jwt-done] JWT analizi bitti. Bulguları severity-sıralı özetle; payload base64\'tür (şifreli değil), bunu kullanıcıya hatırlat.';
999
+ return { ok: true, output: out, args };
1000
+ }
1001
+ catch (e) {
1002
+ return { ok: false, output: 'JWT analizi hatası: ' + (e?.message || e), args };
1003
+ }
1004
+ }
968
1005
  // 3.5) Komut güvenliği (Bash/PowerShell) — cmdsec: deny→blokla, allow→izinsiz, confirm→izin akışı
969
1006
  if ((call.name === 'Bash' || call.name === 'PowerShell') && args && args.command) {
970
1007
  const chk = checkCommand(String(args.command), { shell: call.name === 'PowerShell' ? 'powershell' : 'bash' });
@@ -1117,6 +1154,8 @@ export function toolLabel(name, args) {
1117
1154
  return `🔍 Web arandı: ${String(args.query).slice(0, 50)}`;
1118
1155
  if (name === 'CodeAudit')
1119
1156
  return `🛡️ Kod denetimi (SAST): ${String(args.path || '.').slice(0, 50)}`;
1157
+ if (name === 'JwtAudit')
1158
+ return `🎫 JWT analizi`;
1120
1159
  if (name === 'TodoWrite')
1121
1160
  return `TodoWrite(${(args.todos || []).length} öğe)`;
1122
1161
  if (name === 'PowerShell')
package/dist/tui.js CHANGED
@@ -842,6 +842,38 @@ export async function runTui() {
842
842
  runTurn(`CodeAudit aracıyla şu yolu kaynak kod güvenliği için tara (SAST): ${a}. Bulguları severity-sıralı özetle + öncelikli düzeltmeler.`, v);
843
843
  return;
844
844
  }
845
+ // /jwt — JWT token güvenlik analizi (yerel); modele JwtAudit çağırt
846
+ if (tok === '/jwt') {
847
+ const a = v.slice(tok.length).trim();
848
+ if (!a) {
849
+ printItem({ kind: 'note', text: 'Kullanım: /jwt <token>' });
850
+ return;
851
+ }
852
+ runTurn(`JwtAudit aracıyla şu JWT'yi güvenlik için analiz et: ${a}. Bulguları severity-sıralı özetle.`, v);
853
+ return;
854
+ }
855
+ // /spray — login formuna parola-spray (yetkili test); modele SecurityScan tool=spray çağırt
856
+ if (tok === '/spray') {
857
+ const rest = v.slice(tok.length).trim().split(/\s+/);
858
+ const url = rest[0] || '';
859
+ const usr = rest[1] || 'admin';
860
+ if (!url) {
861
+ printItem({ kind: 'note', text: 'Kullanım: /spray <login-url> [kullanıcı]' });
862
+ return;
863
+ }
864
+ runTurn(`SecurityScan aracıyla tool=spray, target=${url}, username=${usr} çalıştır (yetkili parola-spray testi). Sonucu özetle.`, v);
865
+ return;
866
+ }
867
+ // /defaultcreds — login'e varsayılan kimlik denemesi
868
+ if (tok === '/defaultcreds') {
869
+ const a = v.slice(tok.length).trim();
870
+ if (!a) {
871
+ printItem({ kind: 'note', text: 'Kullanım: /defaultcreds <login-url>' });
872
+ return;
873
+ }
874
+ runTurn(`SecurityScan aracıyla tool=defaultcreds, target=${a} çalıştır (varsayılan kimlik denemesi). Sonucu özetle.`, v);
875
+ return;
876
+ }
845
877
  // /exploit · /harden — aktif tarama değil, model-üretim (PoC / YARA-Sigma) → çerçeveli istemle modele
846
878
  if (tok === '/exploit') {
847
879
  const a = v.slice(tok.length).trim();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wormclaude",
3
- "version": "1.0.192",
3
+ "version": "1.0.194",
4
4
  "description": "WormClaude CLI - uncensored security+code assistant (ink TUI, Claude-style)",
5
5
  "type": "module",
6
6
  "bin": {