const fs = require('fs'); const { RemoteTerminal } = require('./remote_exec'); const LOG_FILE = 'D:/cumin/ghaymah_dns_net_sec_tests/logs/ghaymah_execution.log'; const RESULTS_FILE = 'D:/cumin/ghaymah_dns_net_sec_tests/logs/ghaymah_test_results.json'; const testResults = []; let logLines = []; function log(phase, title, output = '') { const ts = new Date().toISOString(); const header = `[${ts}] [${phase}] ${title}`; console.log(header); logLines.push(header); if (output) { console.log(output); logLines.push(output); } logLines.push(''); fs.writeFileSync(LOG_FILE, logLines.join('\n')); } function recordResult(category, testName, status, details) { testResults.push({ timestamp: new Date().toISOString(), category, testName, status, // 'PASS' | 'FAIL' | 'BLOCKED' | 'INFO' details }); fs.writeFileSync(RESULTS_FILE, JSON.stringify(testResults, null, 2)); } async function main() { log('INIT', '=== STARTING COMPREHENSIVE GHAYMAH PLATFORM TESTS ==='); log('INIT', 'Target: Ghaymah Systems (deploy.ghaymah.systems)'); log('INIT', 'Project: dns-tcp-test (3f55ceef-78ae-40c8-a41b-0505db8c59ee)'); log('INIT', 'Client Container: client-terminal (tsl0922/ttyd:alpine)'); log('INIT', 'Target Container: test-redis (redis:alpine)'); const term = new RemoteTerminal(); await term.connect(); log('INIT', 'RemoteTerminal connected via WebSocket to Ghaymah pod!'); // Install netcat or tools if needed (busybox already has nc, nslookup, wget, ip, etc.) log('PRE-FLIGHT', 'Checking container environment tools...'); const toolsCheck = await term.exec('which nslookup nc wget ip awk grep'); log('PRE-FLIGHT', 'Available tools in Alpine container:', toolsCheck.output); // ══════════════════════════════════════════════════════════ // PHASE 3.1: CONTAINER ENVIRONMENT & NETWORK ARCHITECTURE // ══════════════════════════════════════════════════════════ log('PHASE3-ENV', '=== PHASE 3.1: CONTAINER ENVIRONMENT & NETWORK DISCOVERY ==='); const whoami = await term.exec('whoami && id && hostname'); log('PHASE3-ENV', 'Container identity:', whoami.output); recordResult('Environment', 'Container Identity', 'INFO', whoami.output); const ipAddr = await term.exec('ip addr'); log('PHASE3-ENV', 'Network interfaces (ip addr):', ipAddr.output); recordResult('Environment', 'Network Interfaces', 'INFO', ipAddr.output); const ipRoute = await term.exec('ip route'); log('PHASE3-ENV', 'Routing table (ip route):', ipRoute.output); recordResult('Environment', 'Routing Table', 'INFO', ipRoute.output); const resolvConf = await term.exec('cat /etc/resolv.conf'); log('PHASE3-ENV', 'DNS Configuration (/etc/resolv.conf):', resolvConf.output); recordResult('Environment', 'DNS Configuration', 'INFO', resolvConf.output); // ══════════════════════════════════════════════════════════ // PHASE 3.2: INTERNAL DNS VERIFICATION // ══════════════════════════════════════════════════════════ log('PHASE3-DNS', '=== PHASE 3.2: INTERNAL DNS VERIFICATION ==='); log('PHASE3-DNS', 'Objective: Prove App A discovers App B using internal DNS hostnames (not direct IP)'); // Pattern 1: Short hostname 'test-redis' log('PHASE3-DNS', 'Test 1: nslookup test-redis'); const dns1 = await term.exec('nslookup test-redis'); log('PHASE3-DNS', 'Result (test-redis):', dns1.output); const dns1Pass = dns1.exitCode === 0 && (dns1.output.includes('Address') || dns1.output.includes('10.')); recordResult('Internal DNS', 'Short Hostname Resolution (test-redis)', dns1Pass ? 'PASS' : 'FAIL', { command: 'nslookup test-redis', output: dns1.output, exitCode: dns1.exitCode }); // Pattern 2: Search domain expansion via /etc/hosts or getent log('PHASE3-DNS', 'Test 2: getent hosts test-redis'); const dns2 = await term.exec('getent hosts test-redis || ping -c 1 -W 2 test-redis'); log('PHASE3-DNS', 'Result (getent / ping test-redis):', dns2.output); recordResult('Internal DNS', 'Resolver Lookup (test-redis)', dns2.exitCode === 0 ? 'PASS' : 'FAIL', dns2.output); // Pattern 3: Namespace-qualified FQDN // Search domain in resolv.conf was: d62f9886-fced-4cf2-98e4-5b62000d4f03.svc.cluster.local const fqdn = 'test-redis.d62f9886-fced-4cf2-98e4-5b62000d4f03.svc.cluster.local'; log('PHASE3-DNS', `Test 3: nslookup ${fqdn}`); const dns3 = await term.exec(`nslookup ${fqdn}`); log('PHASE3-DNS', `Result (${fqdn}):`, dns3.output); recordResult('Internal DNS', 'Kubernetes FQDN Resolution', dns3.exitCode === 0 ? 'PASS' : 'FAIL', dns3.output); // Pattern 4: Mesh-style DNS patterns (if configured by mesh/service router) const meshPatterns = [ 'test-redis.mesh', 'test-redis.dns-tcp-test.mesh', 'test-redis.local', 'test-redis.internal' ]; for (const mName of meshPatterns) { const dRes = await term.exec(`nslookup ${mName}`); log('PHASE3-DNS', `Pattern ${mName}:`, dRes.output); recordResult('Internal DNS Pattern Check', mName, dRes.exitCode === 0 ? 'PASS' : 'NXDOMAIN', dRes.output); } // ══════════════════════════════════════════════════════════ // PHASE 3.3: RAW TCP CONNECTIONS OVER PRIVATE NETWORK // ══════════════════════════════════════════════════════════ log('PHASE3-TCP', '=== PHASE 3.3: RAW TCP CONNECTIONS (NON-HTTP) ==='); log('PHASE3-TCP', 'Target: test-redis on port 6379 over private network'); // Test TCP connectivity via DNS hostname log('PHASE3-TCP', 'Test 1: TCP Port Probe via DNS Hostname (nc -z -w 3 test-redis 6379)'); const tcpProbe = await term.exec('nc -z -w 3 test-redis 6379'); log('PHASE3-TCP', 'TCP probe exit code:', tcpProbe.exitCode.toString()); recordResult('TCP Connectivity', 'TCP Port 6379 Probe via DNS Hostname', tcpProbe.exitCode === 0 ? 'PASS' : 'FAIL', { command: 'nc -z -w 3 test-redis 6379', output: tcpProbe.output, exitCode: tcpProbe.exitCode }); // Test Raw TCP Protocol Handshake: Redis PING -> PONG log('PHASE3-TCP', 'Test 2: Raw TCP Handshake: Send PING\\r\\n -> Expect +PONG\\r\\n'); const pingCmd = 'printf "*1\\r\\n\\$4\\r\\nPING\\r\\n" | nc -w 3 test-redis 6379'; const tcpPing = await term.exec(pingCmd); log('PHASE3-TCP', 'Redis PING response:', tcpPing.output); const pingPass = tcpPing.output.includes('+PONG') || tcpPing.output.includes('PONG'); recordResult('TCP Protocol', 'Redis Raw TCP PING/PONG', pingPass ? 'PASS' : 'FAIL', { command: pingCmd, output: tcpPing.output, exitCode: tcpPing.exitCode }); // Test Raw TCP Data Exchange: SET key and GET key log('PHASE3-TCP', 'Test 3: Raw TCP Data Exchange: SET ghaymah_test "OK_TCP_WORKS" && GET ghaymah_test'); const redisScript = ` printf "*3\\r\\n\\$3\\r\\nSET\\r\\n\\$12\\r\\nghaymah_test\\r\\n\\$11\\r\\nOK_TCP_PASS\\r\\n" | nc -w 3 test-redis 6379 printf "*2\\r\\n\\$3\\r\\nGET\\r\\n\\$12\\r\\nghaymah_test\\r\\n" | nc -w 3 test-redis 6379 `; const tcpData = await term.exec(redisScript); log('PHASE3-TCP', 'Redis SET & GET response:', tcpData.output); const dataPass = tcpData.output.includes('OK_TCP_PASS'); recordResult('TCP Data Integrity', 'Redis State Storage & Retrieval via Raw TCP', dataPass ? 'PASS' : 'FAIL', { output: tcpData.output, exitCode: tcpData.exitCode }); // ══════════════════════════════════════════════════════════ // PHASE 4.1: SECURITY & PENETRATION TESTING: ISOLATION // ══════════════════════════════════════════════════════════ log('PHASE4-ISO', '=== PHASE 4.1: SECURITY ISOLATION & SCOPING ==='); log('PHASE4-ISO', 'Objective: Test lateral movement and cross-project isolation'); // Test 1: Cross-Project DNS Resolution // auth-deploy belongs to project 'auth-deploy' (5bd7e471-6be2-40a8-aff9-268beb29c631) // scanner-clean belongs to project 'scanner-clean' (19c3ee5e-68c3-4e34-94c9-d03ab6a9df51) const crossProjectTargets = [ 'auth-deploy', 'auth-deploy.mesh', 'auth-deploy.local', 'scanner-clean', 'scanner-clean.mesh' ]; for (const target of crossProjectTargets) { const xRes = await term.exec(`nslookup ${target}`); log('PHASE4-ISO', `Cross-project DNS lookup for '${target}':`, xRes.output); const isolated = xRes.exitCode !== 0 || xRes.output.includes('NXDOMAIN') || xRes.output.includes("can't find"); recordResult('Isolation', `Cross-Project DNS: ${target}`, isolated ? 'BLOCKED (SECURE)' : 'LEAKED (VULNERABLE)', { target, output: xRes.output, exitCode: xRes.exitCode }); } // Test 2: Cross-Tenant DNS Resolution const crossTenantTargets = [ 'kubernetes.default.svc', 'metadata.google.internal', 'admin-panel', 'backend.internal', 'database.default' ]; for (const target of crossTenantTargets) { const ctRes = await term.exec(`nslookup ${target}`); log('PHASE4-ISO', `Cross-tenant DNS lookup for '${target}':`, ctRes.output); recordResult('Tenant Isolation', `Cross-Tenant DNS: ${target}`, ctRes.exitCode !== 0 ? 'BLOCKED' : 'RESOLVED', ctRes.output); } // Test 3: Lateral Movement via Internal IP Probing log('PHASE4-ISO', 'Probing adjacent internal IP subnets (10.42.0.0/16, 10.43.0.0/16, 10.100.0.0/16)...'); const probeIps = [ '10.43.0.1', // Kubernetes API Service IP '10.43.0.10', // CoreDNS Service IP '10.42.5.1', // Local Pod Subnet Gateway '10.100.0.1', // WireGuard/Mesh Gateway (if present) '10.100.0.2', '172.17.0.1', // Docker bridge '169.254.169.254'// Cloud Metadata service ]; for (const ip of probeIps) { const pRes = await term.exec(`nc -z -w 1 ${ip} 80 || nc -z -w 1 ${ip} 443 || nc -z -w 1 ${ip} 53`); log('PHASE4-ISO', `IP Probe ${ip}: exit code ${pRes.exitCode}`); recordResult('Network Isolation', `Direct IP Probing: ${ip}`, pRes.exitCode === 0 ? 'ACCESSIBLE' : 'BLOCKED', { ip, exitCode: pRes.exitCode }); } // ══════════════════════════════════════════════════════════ // PHASE 4.2: NETWORK ENUMERATION & PORT SCANNING // ══════════════════════════════════════════════════════════ log('PHASE4-SCAN', '=== PHASE 4.2: NETWORK ENUMERATION ==='); log('PHASE4-SCAN', 'Scanning ports on test-redis...'); const portScanScript = ` for p in 22 53 80 443 3000 4000 5432 6379 8080 9000; do nc -z -w 1 test-redis $p && echo "PORT $p OPEN" || echo "PORT $p CLOSED" done `; const portScan = await term.exec(portScanScript); log('PHASE4-SCAN', 'Port scan results on test-redis:', portScan.output); recordResult('Network Enumeration', 'Port Scan test-redis', 'COMPLETED', portScan.output); // ══════════════════════════════════════════════════════════ // PHASE 4.3: DUAL ROUTING & DNS LEAKS // ══════════════════════════════════════════════════════════ log('PHASE4-LEAK', '=== PHASE 4.3: DUAL ROUTING & DNS LEAK DETECTION ==='); // Test 1: External HTTP egress log('PHASE4-LEAK', 'Test 1: External internet egress via HTTP (httpbin.org/ip)...'); const extIp = await term.exec('wget -qO- https://httpbin.org/ip || wget -qO- http://ifconfig.me/ip'); log('PHASE4-LEAK', 'Public Egress IP response:', extIp.output); const extPass = extIp.exitCode === 0 && extIp.output.length > 5; recordResult('Dual Routing', 'Outbound Internet Access (Egress)', extPass ? 'PASS' : 'FAIL', extIp.output); // Test 2: External DNS resolution const externalDomains = ['google.com', 'github.com', 'cloudflare.com']; for (const domain of externalDomains) { const extDns = await term.exec(`nslookup ${domain}`); log('PHASE4-LEAK', `External DNS resolution for ${domain}:`, extDns.output); const dnsPass = extDns.exitCode === 0 && extDns.output.includes('Address'); recordResult('DNS Routing', `External DNS Resolution (${domain})`, dnsPass ? 'PASS' : 'FAIL', extDns.output); } // Test 3: Check for DNS Leak / Internal vs External Resolver Separation log('PHASE4-LEAK', 'Testing DNS server handling of non-existent internal domain (leak check)...'); const leakTest = await term.exec('nslookup leak-test-nonexistent-internal-ghaymah.mesh'); log('PHASE4-LEAK', 'Leak test query output:', leakTest.output); const leakSecure = leakTest.output.includes('NXDOMAIN') || leakTest.output.includes("can't find"); recordResult('DNS Leak Detection', 'Non-existent Mesh Domain Query', leakSecure ? 'SECURE (NXDOMAIN)' : 'ANOMALY', leakTest.output); term.close(); log('DONE', '=== ALL GHAYMAH PLATFORM TESTS COMPLETED SUCCESSFULLY ==='); } main().catch(err => { console.error('FATAL ERROR:', err); fs.writeFileSync(LOG_FILE, `FATAL: ${err.message}\n${err.stack}`); });