wormclaude 1.0.191 → 1.0.193

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,7 @@ 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>' },
64
65
  { name: '/exploit', desc: 'yetkili testte doğrulanmış PoC üret: /exploit <cve|açıklama>' },
65
66
  { name: '/harden', desc: 'savunma çıktısı üret (YARA/Sigma + yama önerisi): /harden <hedef|tehdit>' },
66
67
  { 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/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.191';
19
+ export const VERSION = '1.0.193';
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'], description: 'full → tam kapsamlı web taraması (recon+dirscan+xss+sqli+idor + tüm şablonlar); recon/scan/dirscan/portscan/osint → domain/host; xss/sqli/idor → parameterized URL. portscan = TCP port/servis taraması. osint = DNS istihbaratı + e-posta güvenliği (SPF/DMARC/DKIM, spoofing/phishing duruşu; "osint"/"dns kayıtları"/"spf dmarc"/"mail spoofing" denince, pasif)' },
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)' },
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', 'full', 'fullscan'].includes(tool) || !target) {
770
+ if (!['recon', 'scan', 'xss', 'sqli', 'dirscan', 'idor', 'portscan', 'osint', 'cloud', 'cloudscan', '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')
@@ -965,6 +980,27 @@ async function execOne(call, hooks) {
965
980
  return { ok: false, output: 'Kod denetimi hatası: ' + (e?.message || e), args };
966
981
  }
967
982
  }
983
+ // 3.46) JWT güvenlik analizi (YEREL; token sunucuya gitmez)
984
+ if (call.name === 'JwtAudit') {
985
+ try {
986
+ const { analyzeJwt } = await import('./jwt.js');
987
+ const r = analyzeJwt(String(args?.token || ''));
988
+ if (!r.ok)
989
+ return { ok: false, output: 'JWT analizi: ' + (r.error || 'çözümlenemedi'), args };
990
+ let out = 'JWT analizi\n';
991
+ out += 'header: ' + JSON.stringify(r.header) + '\n';
992
+ out += 'payload: ' + JSON.stringify(r.payload) + '\n';
993
+ if (r.crackedSecret != null)
994
+ out += `⚠ HMAC secret KIRILDI: "${r.crackedSecret}"\n`;
995
+ out += `${r.findings.length} bulgu:\n`;
996
+ out += r.findings.map((f) => `[${f.severity.toUpperCase()}]${f.cwe ? ' ' + f.cwe : ''} ${f.title}\n ${f.detail}`).join('\n');
997
+ 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.';
998
+ return { ok: true, output: out, args };
999
+ }
1000
+ catch (e) {
1001
+ return { ok: false, output: 'JWT analizi hatası: ' + (e?.message || e), args };
1002
+ }
1003
+ }
968
1004
  // 3.5) Komut güvenliği (Bash/PowerShell) — cmdsec: deny→blokla, allow→izinsiz, confirm→izin akışı
969
1005
  if ((call.name === 'Bash' || call.name === 'PowerShell') && args && args.command) {
970
1006
  const chk = checkCommand(String(args.command), { shell: call.name === 'PowerShell' ? 'powershell' : 'bash' });
@@ -1117,6 +1153,8 @@ export function toolLabel(name, args) {
1117
1153
  return `🔍 Web arandı: ${String(args.query).slice(0, 50)}`;
1118
1154
  if (name === 'CodeAudit')
1119
1155
  return `🛡️ Kod denetimi (SAST): ${String(args.path || '.').slice(0, 50)}`;
1156
+ if (name === 'JwtAudit')
1157
+ return `🎫 JWT analizi`;
1120
1158
  if (name === 'TodoWrite')
1121
1159
  return `TodoWrite(${(args.todos || []).length} öğe)`;
1122
1160
  if (name === 'PowerShell')
package/dist/tui.js CHANGED
@@ -842,6 +842,16 @@ 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
+ }
845
855
  // /exploit · /harden — aktif tarama değil, model-üretim (PoC / YARA-Sigma) → çerçeveli istemle modele
846
856
  if (tok === '/exploit') {
847
857
  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.191",
3
+ "version": "1.0.193",
4
4
  "description": "WormClaude CLI - uncensored security+code assistant (ink TUI, Claude-style)",
5
5
  "type": "module",
6
6
  "bin": {