@voidagency/web-scanner 0.0.1
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/README.md +198 -0
- package/dist/aggregator.d.ts +65 -0
- package/dist/aggregator.d.ts.map +1 -0
- package/dist/aggregator.js +546 -0
- package/dist/aggregator.js.map +1 -0
- package/dist/categories.d.ts +59 -0
- package/dist/categories.d.ts.map +1 -0
- package/dist/categories.js +278 -0
- package/dist/categories.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +457 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +121 -0
- package/dist/config.js.map +1 -0
- package/dist/coverage.d.ts +49 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/coverage.js +165 -0
- package/dist/coverage.js.map +1 -0
- package/dist/enrichers/nvd.d.ts +55 -0
- package/dist/enrichers/nvd.d.ts.map +1 -0
- package/dist/enrichers/nvd.js +326 -0
- package/dist/enrichers/nvd.js.map +1 -0
- package/dist/report.d.ts +12 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +460 -0
- package/dist/report.js.map +1 -0
- package/dist/runners/nuclei.d.ts +59 -0
- package/dist/runners/nuclei.d.ts.map +1 -0
- package/dist/runners/nuclei.js +531 -0
- package/dist/runners/nuclei.js.map +1 -0
- package/dist/runners/testssl.d.ts +16 -0
- package/dist/runners/testssl.d.ts.map +1 -0
- package/dist/runners/testssl.js +179 -0
- package/dist/runners/testssl.js.map +1 -0
- package/dist/runners/zap.d.ts +30 -0
- package/dist/runners/zap.d.ts.map +1 -0
- package/dist/runners/zap.js +389 -0
- package/dist/runners/zap.js.map +1 -0
- package/dist/types.d.ts +172 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
- package/templates/drupal-api-index-exposed.yaml +81 -0
- package/templates/drupal-api-user-detail.yaml +76 -0
- package/templates/drupal-api-user-listing.yaml +59 -0
- package/templates/drupal-dev-files-exposed.yaml +73 -0
- package/templates/drupal-file-path-disclosure.yaml +59 -0
- package/templates/drupal-files-listing.yaml +63 -0
- package/templates/drupal-install-error-disclosure.yaml +62 -0
- package/templates/drupal-theme-lockfiles.yaml +79 -0
- package/templates/drupal-version-detect.yaml +89 -0
- package/templates/http-options-enabled.yaml +56 -0
- package/templates/nextjs-version-detect.yaml +35 -0
- package/templates/php-version-detect.yaml +37 -0
- package/zap.yaml +33 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* testssl.sh Runner
|
|
3
|
+
* Execute SSL/TLS analysis and parse JSON output
|
|
4
|
+
*/
|
|
5
|
+
import { execa } from 'execa';
|
|
6
|
+
import { readFile, unlink } from 'fs/promises';
|
|
7
|
+
import { join } from 'path';
|
|
8
|
+
import { tmpdir } from 'os';
|
|
9
|
+
// Scan options for each profile
|
|
10
|
+
const PROFILE_OPTIONS = {
|
|
11
|
+
quick: ['--protocols', '--vulnerable'],
|
|
12
|
+
standard: ['--protocols', '--vulnerable', '--cipher-per-proto'],
|
|
13
|
+
deep: [], // Full scan (no options = everything)
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Map testssl severity to normalized severity
|
|
17
|
+
*/
|
|
18
|
+
function mapSeverity(severity) {
|
|
19
|
+
const s = severity.toUpperCase();
|
|
20
|
+
if (s === 'CRITICAL')
|
|
21
|
+
return 'critical';
|
|
22
|
+
if (s === 'HIGH')
|
|
23
|
+
return 'high';
|
|
24
|
+
if (s === 'MEDIUM')
|
|
25
|
+
return 'medium';
|
|
26
|
+
if (s === 'LOW' || s === 'WARN')
|
|
27
|
+
return 'low';
|
|
28
|
+
return 'info';
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* IDs that indicate "not vulnerable" results - these have CVEs but are negative findings
|
|
32
|
+
*/
|
|
33
|
+
const VULNERABILITY_TEST_IDS = [
|
|
34
|
+
'heartbleed', 'CCS', 'ticketbleed', 'ROBOT', 'secure_client_renego',
|
|
35
|
+
'CRIME_TLS', 'BREACH', 'POODLE_SSL', 'SWEET32', 'FREAK', 'DROWN',
|
|
36
|
+
'DROWN_hint', 'LOGJAM', 'LOGJAM-common_primes', 'BEAST', 'winshock', 'RC4',
|
|
37
|
+
'secure_renego', 'fallback_SCSV',
|
|
38
|
+
];
|
|
39
|
+
/**
|
|
40
|
+
* IDs that are scanner errors, not target vulnerabilities
|
|
41
|
+
* These indicate issues with the local scanning environment
|
|
42
|
+
*/
|
|
43
|
+
const SCANNER_ERROR_IDS = new Set([
|
|
44
|
+
'engine_problem', // OpenSSL engine not available on scanner machine
|
|
45
|
+
'scanProblem', // Generic scan issues
|
|
46
|
+
'pre_128cipher', // Old cipher check issues
|
|
47
|
+
]);
|
|
48
|
+
/**
|
|
49
|
+
* Vulnerability IDs to skip (too theoretical for web app pentests)
|
|
50
|
+
*/
|
|
51
|
+
const SKIP_VULN_IDS = new Set([
|
|
52
|
+
'BREACH', // Requires MITM + content injection, every site uses gzip
|
|
53
|
+
]);
|
|
54
|
+
/**
|
|
55
|
+
* Parse testssl JSON output into findings
|
|
56
|
+
* Only include actual vulnerabilities, not "passed" tests
|
|
57
|
+
*/
|
|
58
|
+
function parseTestsslOutput(data, startIndex) {
|
|
59
|
+
const findings = [];
|
|
60
|
+
for (const item of data) {
|
|
61
|
+
const severity = item.severity.toUpperCase();
|
|
62
|
+
// Skip OK/INFO items - these are "not vulnerable" or informational
|
|
63
|
+
// Even if they have CVEs, INFO means the test PASSED (not vulnerable)
|
|
64
|
+
if (['OK', 'INFO'].includes(severity)) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
// Skip LOW severity - cipher details, session tickets, etc.
|
|
68
|
+
// These are too granular for web app pentests and require MITM to exploit
|
|
69
|
+
if (['LOW', 'WARN'].includes(severity)) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
// Skip items without meaningful findings
|
|
73
|
+
if (!item.finding || item.finding === '--') {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
// Skip scanner errors (local machine issues, not target vulnerabilities)
|
|
77
|
+
if (SCANNER_ERROR_IDS.has(item.id)) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
// Skip theoretical vulns not useful for web app pentests
|
|
81
|
+
if (SKIP_VULN_IDS.has(item.id)) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
// Skip findings that are scanner issues, not target vulnerabilities
|
|
85
|
+
if (item.finding.includes('No engine or GOST support')) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
// Skip certain verbose informational entries
|
|
89
|
+
if (item.id.startsWith('cert_') && severity === 'LOW') {
|
|
90
|
+
// Certificate info entries that aren't critical
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
findings.push({
|
|
94
|
+
id: String(startIndex + findings.length + 1).padStart(3, '0'),
|
|
95
|
+
title: formatTestsslTitle(item.id),
|
|
96
|
+
description: item.finding,
|
|
97
|
+
severity: mapSeverity(severity),
|
|
98
|
+
source: 'testssl',
|
|
99
|
+
target: `${item.ip}:${item.port}`,
|
|
100
|
+
cve: item.cve,
|
|
101
|
+
cwe: item.cwe,
|
|
102
|
+
tags: ['ssl', 'tls'],
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return findings;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Format testssl ID into readable title
|
|
109
|
+
*/
|
|
110
|
+
function formatTestsslTitle(id) {
|
|
111
|
+
// Convert snake_case to Title Case
|
|
112
|
+
return id
|
|
113
|
+
.replaceAll('_', ' ')
|
|
114
|
+
.replaceAll(/\b\w/g, c => c.toUpperCase())
|
|
115
|
+
.replaceAll('Ssl', 'SSL')
|
|
116
|
+
.replaceAll('Tls', 'TLS')
|
|
117
|
+
.replaceAll('Hsts', 'HSTS')
|
|
118
|
+
.replaceAll('Csp', 'CSP');
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Run testssl.sh scan on target
|
|
122
|
+
*/
|
|
123
|
+
export async function runTestssl(target, profile = 'standard', options = {}) {
|
|
124
|
+
// Create temp file for JSON output
|
|
125
|
+
const tempFile = join(tmpdir(), `testssl-${Date.now()}.json`);
|
|
126
|
+
// Extract host from URL if needed
|
|
127
|
+
let host;
|
|
128
|
+
try {
|
|
129
|
+
const url = new URL(target);
|
|
130
|
+
host = url.hostname;
|
|
131
|
+
// Add port if not default HTTPS
|
|
132
|
+
if (url.port && url.port !== '443') {
|
|
133
|
+
host = `${host}:${url.port}`;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
host = target;
|
|
138
|
+
}
|
|
139
|
+
// Build command arguments
|
|
140
|
+
const profileOptions = PROFILE_OPTIONS[profile];
|
|
141
|
+
const args = [
|
|
142
|
+
'--jsonfile', tempFile,
|
|
143
|
+
'--quiet',
|
|
144
|
+
...profileOptions,
|
|
145
|
+
host,
|
|
146
|
+
];
|
|
147
|
+
try {
|
|
148
|
+
await execa('testssl.sh', args, {
|
|
149
|
+
reject: false, // Don't throw on non-zero exit
|
|
150
|
+
timeout: profile === 'deep' ? 600000 : 300000, // 10min for deep, 5min otherwise
|
|
151
|
+
});
|
|
152
|
+
// Read and parse JSON output
|
|
153
|
+
const jsonContent = await readFile(tempFile, 'utf-8');
|
|
154
|
+
const data = JSON.parse(jsonContent);
|
|
155
|
+
// Parse into findings
|
|
156
|
+
const findings = parseTestsslOutput(data, options.startIndex || 0);
|
|
157
|
+
// Clean up temp file
|
|
158
|
+
await unlink(tempFile).catch(() => { });
|
|
159
|
+
return findings;
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
// Clean up temp file on error
|
|
163
|
+
await unlink(tempFile).catch(() => { });
|
|
164
|
+
throw new Error(`testssl scan failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Check if testssl.sh is installed
|
|
169
|
+
*/
|
|
170
|
+
export async function isTestsslInstalled() {
|
|
171
|
+
try {
|
|
172
|
+
await execa('testssl.sh', ['--version']);
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=testssl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testssl.js","sourceRoot":"","sources":["../../src/runners/testssl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZAP Runner - OWASP ZAP baseline scanner via Docker
|
|
3
|
+
* Primary scanner for:
|
|
4
|
+
* - JS Library CVEs (Retire.js)
|
|
5
|
+
* - Security Headers
|
|
6
|
+
* - CORS Misconfigurations
|
|
7
|
+
* - CSRF Detection
|
|
8
|
+
* - XSS Detection hints
|
|
9
|
+
*/
|
|
10
|
+
import { Finding, TechDetection } from '../types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Run ZAP baseline scan via Docker
|
|
13
|
+
*/
|
|
14
|
+
export declare function runZap(target: string, options?: {
|
|
15
|
+
outputDir?: string;
|
|
16
|
+
timeout?: number;
|
|
17
|
+
onProgress?: (msg: string) => void;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
findings: Finding[];
|
|
20
|
+
technologies: TechDetection[];
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* Check if Docker and ZAP image are available
|
|
24
|
+
*/
|
|
25
|
+
export declare function checkZapAvailable(): Promise<boolean>;
|
|
26
|
+
/**
|
|
27
|
+
* Pull ZAP Docker image if not present
|
|
28
|
+
*/
|
|
29
|
+
export declare function pullZapImage(onProgress?: (msg: string) => void): Promise<void>;
|
|
30
|
+
//# sourceMappingURL=zap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zap.d.ts","sourceRoot":"","sources":["../../src/runners/zap.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAE,OAAO,EAAY,aAAa,EAAE,MAAM,aAAa,CAAC;AA0U/D;;GAEG;AACH,wBAAsB,MAAM,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B,GACL,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAAC,YAAY,EAAE,aAAa,EAAE,CAAA;CAAE,CAAC,CA6FjE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAQ1D;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBpF"}
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZAP Runner - OWASP ZAP baseline scanner via Docker
|
|
3
|
+
* Primary scanner for:
|
|
4
|
+
* - JS Library CVEs (Retire.js)
|
|
5
|
+
* - Security Headers
|
|
6
|
+
* - CORS Misconfigurations
|
|
7
|
+
* - CSRF Detection
|
|
8
|
+
* - XSS Detection hints
|
|
9
|
+
*/
|
|
10
|
+
import { execa } from 'execa';
|
|
11
|
+
import { readFile, unlink } from 'fs/promises';
|
|
12
|
+
import { existsSync } from 'fs';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
/**
|
|
15
|
+
* ZAP plugin IDs to skip (noisy/not useful)
|
|
16
|
+
* List from https://www.zaproxy.org/docs/alerts/
|
|
17
|
+
*
|
|
18
|
+
* 10109 - Modern Web Application (just tells you it's a SPA, not a vulnerability)
|
|
19
|
+
* 10015 - Re-examine Cache-control Directives (usually false positive)
|
|
20
|
+
* 10049 - Non-Storable Content (informational, not actionable)
|
|
21
|
+
* 10050 - Retrieved from Cache (informational)
|
|
22
|
+
* 10054 - Cookie Without SameSite (often intentional)
|
|
23
|
+
* 10044 - Big Redirect Detected (normal for frameworks, not a real vuln)
|
|
24
|
+
* 10027 - Suspicious Comments (flags "username", "query" in JS - too noisy)
|
|
25
|
+
* 10112 - Session Management Response Identified (just says "found session token")
|
|
26
|
+
* 10017 - Cross-Domain JS (redundant with SRI Missing - same fix)
|
|
27
|
+
*/
|
|
28
|
+
const SKIP_PLUGIN_IDS = new Set([
|
|
29
|
+
'10109', // Modern Web Application
|
|
30
|
+
'10015', // Re-examine Cache-control Directives
|
|
31
|
+
'10049', // Non-Storable Content
|
|
32
|
+
'10050', // Retrieved from Cache
|
|
33
|
+
'10044', // Big Redirect Detected
|
|
34
|
+
'10027', // Suspicious Comments
|
|
35
|
+
'10112', // Session Management Response Identified
|
|
36
|
+
'10017', // Cross-Domain JS (merged into SRI Missing)
|
|
37
|
+
'10096', // Timestamp Disclosure - Unix (build IDs, cache busters - not sensitive)
|
|
38
|
+
]);
|
|
39
|
+
/**
|
|
40
|
+
* Alert names to skip (when plugin ID can't be used - e.g., shared IDs)
|
|
41
|
+
* All CSP alerts share plugin ID 10055, so filter by name
|
|
42
|
+
*/
|
|
43
|
+
const SKIP_ALERT_NAMES = new Set([
|
|
44
|
+
'CSP: Notices', // Informational only
|
|
45
|
+
'CSP: X-Content-Security-Policy', // Deprecated header notice
|
|
46
|
+
'CSP: X-WebKit-CSP', // Deprecated header notice
|
|
47
|
+
'CSP: Header & Meta', // Just says you have both - not a vuln
|
|
48
|
+
]);
|
|
49
|
+
/**
|
|
50
|
+
* Rename certain findings to be clearer/combined
|
|
51
|
+
*/
|
|
52
|
+
const RENAME_FINDINGS = {
|
|
53
|
+
'90003': 'External JavaScript Without Integrity Verification',
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Check if a CSRF finding should be filtered (Drupal uses its own form tokens)
|
|
57
|
+
*/
|
|
58
|
+
function isDrupalCsrfFalsePositive(alert) {
|
|
59
|
+
if (alert.pluginid !== '10202')
|
|
60
|
+
return false; // Not CSRF alert
|
|
61
|
+
// Check if the form is a Drupal form (has drupal-selector or form_build_id)
|
|
62
|
+
const evidence = alert.instances[0]?.evidence || '';
|
|
63
|
+
return evidence.includes('data-drupal-selector') ||
|
|
64
|
+
evidence.includes('form_build_id') ||
|
|
65
|
+
evidence.includes('drupal');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Map ZAP risk code to our severity
|
|
69
|
+
*/
|
|
70
|
+
function mapZapSeverity(riskcode) {
|
|
71
|
+
switch (riskcode) {
|
|
72
|
+
case '3': return 'high'; // ZAP doesn't have critical
|
|
73
|
+
case '2': return 'medium';
|
|
74
|
+
case '1': return 'low';
|
|
75
|
+
case '0': return 'info';
|
|
76
|
+
default: return 'info';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Extract CVEs from ZAP otherinfo field
|
|
81
|
+
* ZAP puts CVEs in the otherinfo for vulnerable JS libraries
|
|
82
|
+
*/
|
|
83
|
+
function extractCves(otherinfo) {
|
|
84
|
+
const cvePattern = /CVE-\d{4}-\d+/g;
|
|
85
|
+
const matches = otherinfo.match(cvePattern);
|
|
86
|
+
return matches ? [...new Set(matches)] : [];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Extract technology/library info from ZAP findings
|
|
90
|
+
*/
|
|
91
|
+
function extractTechFromZap(alerts) {
|
|
92
|
+
const techMap = new Map();
|
|
93
|
+
for (const alert of alerts) {
|
|
94
|
+
// Vulnerable JS Library findings contain library info
|
|
95
|
+
if (alert.pluginid === '10003') {
|
|
96
|
+
for (const instance of alert.instances) {
|
|
97
|
+
const host = new URL(instance.uri).hostname;
|
|
98
|
+
// Extract library name and version from evidence
|
|
99
|
+
const libMatch = alert.otherinfo.match(/library ([a-z-]+), version ([0-9.]+)/i);
|
|
100
|
+
if (libMatch) {
|
|
101
|
+
const tech = `${libMatch[1]}:${libMatch[2]}`;
|
|
102
|
+
if (!techMap.has(host)) {
|
|
103
|
+
techMap.set(host, new Set());
|
|
104
|
+
}
|
|
105
|
+
techMap.get(host).add(tech);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Server version from headers
|
|
110
|
+
if (alert.pluginid === '10036' || alert.pluginid === '10037') {
|
|
111
|
+
for (const instance of alert.instances) {
|
|
112
|
+
const host = new URL(instance.uri).hostname;
|
|
113
|
+
if (instance.evidence) {
|
|
114
|
+
if (!techMap.has(host)) {
|
|
115
|
+
techMap.set(host, new Set());
|
|
116
|
+
}
|
|
117
|
+
techMap.get(host).add(instance.evidence);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return Array.from(techMap.entries()).map(([host, techs]) => ({
|
|
123
|
+
host,
|
|
124
|
+
technologies: Array.from(techs),
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Parse ZAP alert to Finding
|
|
129
|
+
*/
|
|
130
|
+
function parseZapAlert(alert, index) {
|
|
131
|
+
const findings = [];
|
|
132
|
+
const severity = mapZapSeverity(alert.riskcode);
|
|
133
|
+
const cves = extractCves(alert.otherinfo);
|
|
134
|
+
// Clean HTML from descriptions
|
|
135
|
+
const cleanHtml = (html) => html
|
|
136
|
+
.replace(/<\/?p>/g, '\n')
|
|
137
|
+
.replace(/<[^>]+>/g, '')
|
|
138
|
+
.replace(/"/g, '"')
|
|
139
|
+
.replace(/&/g, '&')
|
|
140
|
+
.replace(/</g, '<')
|
|
141
|
+
.replace(/>/g, '>')
|
|
142
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
143
|
+
.trim();
|
|
144
|
+
// For JS library vulnerabilities, create one finding per CVE
|
|
145
|
+
if (alert.pluginid === '10003' && cves.length > 0) {
|
|
146
|
+
// Group by library
|
|
147
|
+
const libMatch = alert.otherinfo.match(/library ([a-z-]+), version ([0-9.]+)/i);
|
|
148
|
+
const libName = libMatch ? `${libMatch[1]} ${libMatch[2]}` : alert.name;
|
|
149
|
+
findings.push({
|
|
150
|
+
id: '', // Will be renumbered
|
|
151
|
+
title: `Vulnerable JS Library: ${libName}`,
|
|
152
|
+
description: cleanHtml(alert.desc),
|
|
153
|
+
severity: severity,
|
|
154
|
+
source: 'zap',
|
|
155
|
+
target: alert.instances[0]?.uri || '',
|
|
156
|
+
cve: cves.join(', '),
|
|
157
|
+
cwe: alert.cweid !== '-1' ? `CWE-${alert.cweid}` : undefined,
|
|
158
|
+
tags: ['js-library', 'cve', 'outdated-component'],
|
|
159
|
+
extracted: cves,
|
|
160
|
+
references: alert.reference ? [cleanHtml(alert.reference)] : [],
|
|
161
|
+
matcher: libName,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// Standard finding - check for renamed titles
|
|
166
|
+
const title = RENAME_FINDINGS[alert.pluginid] || alert.name;
|
|
167
|
+
findings.push({
|
|
168
|
+
id: '',
|
|
169
|
+
title,
|
|
170
|
+
description: cleanHtml(alert.desc),
|
|
171
|
+
severity: severity,
|
|
172
|
+
source: 'zap',
|
|
173
|
+
target: alert.instances[0]?.uri || '',
|
|
174
|
+
cwe: alert.cweid !== '-1' ? `CWE-${alert.cweid}` : undefined,
|
|
175
|
+
tags: getZapTags(alert.pluginid, alert.name),
|
|
176
|
+
references: alert.reference ? [cleanHtml(alert.reference)] : [],
|
|
177
|
+
matcher: alert.instances[0]?.evidence || undefined,
|
|
178
|
+
request: alert.instances.length > 0 ?
|
|
179
|
+
`${alert.instances[0].method} ${alert.instances[0].uri}` : undefined,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
return findings;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Map ZAP plugin IDs to tags for categorization
|
|
186
|
+
* Reference: https://www.zaproxy.org/docs/alerts/
|
|
187
|
+
*/
|
|
188
|
+
function getZapTags(pluginid, name) {
|
|
189
|
+
const tags = ['zap'];
|
|
190
|
+
const tagMap = {
|
|
191
|
+
// Vulnerability Detection
|
|
192
|
+
'10003': ['js-library', 'cve', 'outdated-component'], // Vulnerable JS Library
|
|
193
|
+
'10202': ['csrf', 'security-misconfiguration'], // Absence of Anti-CSRF Tokens
|
|
194
|
+
'10031': ['xss', 'user-input'], // User Controllable HTML Attr (Potential XSS)
|
|
195
|
+
'10043': ['xss', 'user-input'], // User Controllable JS Event (XSS)
|
|
196
|
+
'40012': ['xss', 'reflected'], // Cross Site Scripting (Reflected)
|
|
197
|
+
'40014': ['xss', 'persistent'], // Cross Site Scripting (Persistent)
|
|
198
|
+
'40016': ['xss', 'dom'], // Cross Site Scripting (DOM Based)
|
|
199
|
+
'40018': ['sqli'], // SQL Injection
|
|
200
|
+
'6': ['lfi', 'path-traversal'], // Path Traversal
|
|
201
|
+
'7': ['rfi', 'file-inclusion'], // Remote File Inclusion
|
|
202
|
+
'90019': ['ssti', 'injection'], // Server Side Template Injection
|
|
203
|
+
'90020': ['ssrf'], // Server Side Request Forgery
|
|
204
|
+
'90021': ['xxe', 'injection'], // XML External Entity Attack
|
|
205
|
+
'90023': ['command-injection', 'rce'], // OS Command Injection
|
|
206
|
+
'20019': ['redirect', 'open-redirect'], // External Redirect
|
|
207
|
+
// Security Headers
|
|
208
|
+
'10038': ['csp', 'header', 'security-misconfiguration'], // CSP Header Not Set
|
|
209
|
+
'10020': ['clickjacking', 'header', 'security-misconfiguration'], // Anti-clickjacking Header
|
|
210
|
+
'10035': ['hsts', 'header', 'security-misconfiguration'], // Strict-Transport-Security
|
|
211
|
+
'10021': ['header', 'security-misconfiguration'], // X-Content-Type-Options Missing
|
|
212
|
+
'10063': ['permissions-policy', 'header'], // Permissions Policy Header
|
|
213
|
+
'90003': ['sri', 'integrity', 'security-misconfiguration'], // Sub Resource Integrity Missing
|
|
214
|
+
'90004': ['spectre', 'isolation', 'header'], // Spectre Vulnerability
|
|
215
|
+
// Information Disclosure
|
|
216
|
+
'10009': ['info-disclosure', 'version-leak'], // In Page Banner Information Leak
|
|
217
|
+
'10037': ['info-disclosure', 'version-leak', 'header'], // X-Powered-By Leak
|
|
218
|
+
'10036': ['info-disclosure', 'version-leak', 'header'], // Server Header Leak
|
|
219
|
+
'10039': ['info-disclosure', 'header'], // X-Backend-Server Leak
|
|
220
|
+
'10023': ['info-disclosure', 'debug-errors'], // Debug Error Messages
|
|
221
|
+
'10044': ['redirect', 'info-disclosure'], // Big Redirect
|
|
222
|
+
'10027': ['info-disclosure', 'comments'], // Suspicious Comments
|
|
223
|
+
'2': ['info-disclosure', 'private-ip'], // Private IP Disclosure
|
|
224
|
+
'10062': ['info-disclosure', 'pii'], // PII Disclosure
|
|
225
|
+
// Cookie Issues
|
|
226
|
+
'10010': ['cookie', 'httponly'], // Cookie No HttpOnly
|
|
227
|
+
'10011': ['cookie', 'secure-flag'], // Cookie Without Secure Flag
|
|
228
|
+
'10054': ['cookie', 'samesite'], // Cookie without SameSite
|
|
229
|
+
// CORS & Cross-Domain
|
|
230
|
+
'10098': ['cors', 'security-misconfiguration'], // Cross-Domain Misconfiguration
|
|
231
|
+
'10017': ['cross-domain', 'js-inclusion'], // Cross-Domain JS Source Inclusion
|
|
232
|
+
// Directory & File Issues
|
|
233
|
+
'0': ['directory-listing'], // Directory Browsing (Active)
|
|
234
|
+
'10033': ['directory-listing'], // Directory Browsing (Passive)
|
|
235
|
+
'10095': ['backup-files', 'sensitive-files'], // Backup File Disclosure
|
|
236
|
+
'10045': ['source-disclosure', 'sensitive-files'], // Source Code Disclosure - WEB-INF
|
|
237
|
+
'10099': ['source-disclosure', 'php'], // Source Code Disclosure - PHP
|
|
238
|
+
// TLS/SSL Issues
|
|
239
|
+
'10034': ['heartbleed', 'ssl', 'cve'], // Heartbleed (Indicative)
|
|
240
|
+
'20015': ['heartbleed', 'ssl', 'cve'], // Heartbleed (Active)
|
|
241
|
+
'10040': ['mixed-content', 'ssl'], // Mixed Content
|
|
242
|
+
'10041': ['insecure-form', 'ssl'], // HTTP to HTTPS Insecure Transition
|
|
243
|
+
'10042': ['insecure-form', 'ssl'], // HTTPS to HTTP Insecure Transition
|
|
244
|
+
// Session & Auth
|
|
245
|
+
'3': ['session', 'url-rewrite'], // Session ID in URL Rewrite
|
|
246
|
+
'10105': ['auth', 'weak-auth'], // Weak Authentication Method
|
|
247
|
+
'10108': ['tabnabbing', 'security-misconfiguration'], // Reverse Tabnabbing
|
|
248
|
+
// Informational (mostly filtered)
|
|
249
|
+
'10109': ['modern-app', 'spa'], // Modern Web Application
|
|
250
|
+
'10015': ['cache', 'header'], // Re-examine Cache-control
|
|
251
|
+
'10110': ['dangerous-js', 'code-quality'], // Dangerous JS Functions
|
|
252
|
+
'10004': ['tech-detection'], // Tech Detection
|
|
253
|
+
'10112': ['session', 'informational'], // Session Management Response
|
|
254
|
+
'10111': ['auth', 'informational'], // Authentication Request Identified
|
|
255
|
+
};
|
|
256
|
+
if (tagMap[pluginid]) {
|
|
257
|
+
tags.push(...tagMap[pluginid]);
|
|
258
|
+
}
|
|
259
|
+
// Add tags based on name
|
|
260
|
+
if (name.toLowerCase().includes('header'))
|
|
261
|
+
tags.push('header');
|
|
262
|
+
if (name.toLowerCase().includes('xss'))
|
|
263
|
+
tags.push('xss');
|
|
264
|
+
if (name.toLowerCase().includes('csrf'))
|
|
265
|
+
tags.push('csrf');
|
|
266
|
+
return [...new Set(tags)];
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Run ZAP baseline scan via Docker
|
|
270
|
+
*/
|
|
271
|
+
export async function runZap(target, options = {}) {
|
|
272
|
+
const outputDir = options.outputDir || process.cwd();
|
|
273
|
+
const jsonFile = path.join(outputDir, 'zap-report.json');
|
|
274
|
+
const timeout = options.timeout || 300; // 5 minutes default
|
|
275
|
+
// Clean up old report if exists
|
|
276
|
+
if (existsSync(jsonFile)) {
|
|
277
|
+
await unlink(jsonFile);
|
|
278
|
+
}
|
|
279
|
+
options.onProgress?.('Starting ZAP baseline scan via Docker...');
|
|
280
|
+
try {
|
|
281
|
+
// Run ZAP baseline scan
|
|
282
|
+
// -t target URL
|
|
283
|
+
// -J json output filename
|
|
284
|
+
// -I don't return error on warnings
|
|
285
|
+
// -d debug mode for more output
|
|
286
|
+
const args = [
|
|
287
|
+
'run',
|
|
288
|
+
'--rm',
|
|
289
|
+
'-v', `${outputDir}:/zap/wrk/:rw`,
|
|
290
|
+
'-t',
|
|
291
|
+
'ghcr.io/zaproxy/zaproxy:stable',
|
|
292
|
+
'zap-baseline.py',
|
|
293
|
+
'-t', target,
|
|
294
|
+
'-J', 'zap-report.json',
|
|
295
|
+
'-I', // Don't fail on warnings
|
|
296
|
+
];
|
|
297
|
+
options.onProgress?.(`Running: docker ${args.slice(0, 5).join(' ')}...`);
|
|
298
|
+
await execa('docker', args, {
|
|
299
|
+
timeout: timeout * 1000,
|
|
300
|
+
reject: false, // Don't throw on non-zero exit
|
|
301
|
+
});
|
|
302
|
+
// Check if report was generated
|
|
303
|
+
if (!existsSync(jsonFile)) {
|
|
304
|
+
throw new Error('ZAP did not generate report file');
|
|
305
|
+
}
|
|
306
|
+
// Parse the report
|
|
307
|
+
options.onProgress?.('Parsing ZAP results...');
|
|
308
|
+
const reportContent = await readFile(jsonFile, 'utf-8');
|
|
309
|
+
const report = JSON.parse(reportContent);
|
|
310
|
+
const allFindings = [];
|
|
311
|
+
const allTechnologies = [];
|
|
312
|
+
// Process each site
|
|
313
|
+
for (const site of report.site || []) {
|
|
314
|
+
const alerts = site.alerts || [];
|
|
315
|
+
// Extract technologies
|
|
316
|
+
const techs = extractTechFromZap(alerts);
|
|
317
|
+
allTechnologies.push(...techs);
|
|
318
|
+
// Convert alerts to findings (skip noisy ones)
|
|
319
|
+
for (let i = 0; i < alerts.length; i++) {
|
|
320
|
+
// Skip noisy/non-actionable alerts by plugin ID
|
|
321
|
+
if (SKIP_PLUGIN_IDS.has(alerts[i].pluginid)) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
// Skip noisy alerts by name (when plugin ID is shared)
|
|
325
|
+
if (SKIP_ALERT_NAMES.has(alerts[i].name)) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
// Skip Drupal CSRF false positives (Drupal uses form tokens)
|
|
329
|
+
if (isDrupalCsrfFalsePositive(alerts[i])) {
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
const findings = parseZapAlert(alerts[i], i);
|
|
333
|
+
allFindings.push(...findings);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
// Clean up report file
|
|
337
|
+
try {
|
|
338
|
+
await unlink(jsonFile);
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
// Ignore cleanup errors
|
|
342
|
+
}
|
|
343
|
+
options.onProgress?.(`ZAP found ${allFindings.length} issues`);
|
|
344
|
+
return { findings: allFindings, technologies: allTechnologies };
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
if (error instanceof Error && error.message.includes('ETIMEDOUT')) {
|
|
348
|
+
throw new Error(`ZAP scan timed out after ${timeout} seconds`);
|
|
349
|
+
}
|
|
350
|
+
throw new Error(`ZAP scan failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Check if Docker and ZAP image are available
|
|
355
|
+
*/
|
|
356
|
+
export async function checkZapAvailable() {
|
|
357
|
+
try {
|
|
358
|
+
// Check Docker is running
|
|
359
|
+
await execa('docker', ['info'], { reject: true });
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
catch {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Pull ZAP Docker image if not present
|
|
368
|
+
*/
|
|
369
|
+
export async function pullZapImage(onProgress) {
|
|
370
|
+
onProgress?.('Checking ZAP Docker image...');
|
|
371
|
+
try {
|
|
372
|
+
// Check if image exists
|
|
373
|
+
const { stdout } = await execa('docker', [
|
|
374
|
+
'images', '-q', 'ghcr.io/zaproxy/zaproxy:stable'
|
|
375
|
+
]);
|
|
376
|
+
if (!stdout.trim()) {
|
|
377
|
+
onProgress?.('Pulling ZAP Docker image (this may take a few minutes)...');
|
|
378
|
+
await execa('docker', ['pull', 'ghcr.io/zaproxy/zaproxy:stable']);
|
|
379
|
+
onProgress?.('ZAP image downloaded successfully');
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
onProgress?.('ZAP image already available');
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
throw new Error(`Failed to pull ZAP image: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
//# sourceMappingURL=zap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zap.js","sourceRoot":"","sources":["../../src/runners/zap.ts"],"names":[],"mappings":"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"}
|