@soulofzephir/pi-skill-pentesting 1.0.2 → 1.0.5
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/package.json +1 -1
- package/skills/pentesting/SKILL.md +122 -112
- package/skills/pentesting/checklists/api-security.md +210 -0
- package/skills/pentesting/checklists/cloud-metadata.md +290 -0
- package/skills/pentesting/checklists/sensitive-data.md +323 -0
- package/skills/pentesting/checklists/subdomain.md +243 -0
- package/skills/pentesting/checklists/websocket.md +197 -0
- package/skills/pentesting/tools/exposed-files-scan.ps1 +141 -238
- package/skills/pentesting/tools/full-scan.ps1 +278 -316
- package/soulofzephir-pi-skill-pentesting-1.0.2.tgz +0 -0
- package/soulofzephir-pi-skill-pentesting-1.0.3.tgz +0 -0
- package/soulofzephir-pi-skill-pentesting-1.0.4.tgz +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
# Full Security Scan - All-in-One
|
|
2
|
-
# Comprehensive security scanner
|
|
1
|
+
# Full Security Scan - All-in-One v3.0
|
|
2
|
+
# Comprehensive security scanner with detailed reporting
|
|
3
3
|
|
|
4
4
|
param(
|
|
5
5
|
[Parameter(Mandatory=$false)]
|
|
@@ -11,10 +11,6 @@ param(
|
|
|
11
11
|
|
|
12
12
|
$ErrorActionPreference = "Continue"
|
|
13
13
|
|
|
14
|
-
# ═══════════════════════════════════════════════════════════
|
|
15
|
-
# CONFIGURATION
|
|
16
|
-
# ═══════════════════════════════════════════════════════════
|
|
17
|
-
|
|
18
14
|
$Date = Get-Date -Format "yyyy-MM-dd"
|
|
19
15
|
|
|
20
16
|
if ($Target -match "https?://") {
|
|
@@ -32,164 +28,239 @@ if (-not (Test-Path $OutputDir)) {
|
|
|
32
28
|
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
|
33
29
|
}
|
|
34
30
|
|
|
35
|
-
# ═══════════════════════════════════════════════════════════
|
|
36
|
-
# BANNER
|
|
37
|
-
# ═══════════════════════════════════════════════════════════
|
|
38
|
-
|
|
39
31
|
Write-Host ""
|
|
40
|
-
Write-Host "
|
|
41
|
-
Write-Host "
|
|
42
|
-
Write-Host "
|
|
43
|
-
Write-Host "
|
|
44
|
-
Write-Host "
|
|
32
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
33
|
+
Write-Host " Full Security Scan v3.0" -ForegroundColor Cyan
|
|
34
|
+
Write-Host " Target: $Domain" -ForegroundColor Cyan
|
|
35
|
+
Write-Host " Date: $Date" -ForegroundColor Cyan
|
|
36
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
45
37
|
Write-Host ""
|
|
46
38
|
|
|
47
|
-
# ═══════════════════════════════════════════════════════════
|
|
48
|
-
# PHASE 1: SECURITY HEADERS
|
|
49
|
-
# ═══════════════════════════════════════════════════════════
|
|
50
|
-
|
|
51
|
-
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
52
|
-
Write-Host "🔒 PHASE 1: Security Headers" -ForegroundColor Cyan
|
|
53
|
-
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
54
|
-
|
|
55
39
|
$HeaderScore = 0
|
|
56
40
|
$HeaderIssues = @()
|
|
41
|
+
$HeaderGood = @()
|
|
42
|
+
$ExposedFiles = @()
|
|
43
|
+
$OpenPorts = @()
|
|
44
|
+
$CORSIssues = @()
|
|
45
|
+
$FalsePositives = @()
|
|
46
|
+
$TechStack = @()
|
|
47
|
+
|
|
48
|
+
# PHASE 1: Headers
|
|
49
|
+
Write-Host "Phase 1: Security Headers" -ForegroundColor Yellow
|
|
57
50
|
|
|
58
51
|
try {
|
|
59
52
|
$Response = Invoke-WebRequest -Uri $Target -Method Head -TimeoutSec 15 -ErrorAction Stop
|
|
60
53
|
$Headers = $Response.Headers
|
|
54
|
+
|
|
55
|
+
# Detect Server/Technology
|
|
56
|
+
$Server = $Headers["Server"]
|
|
57
|
+
$XPB = $Headers["X-Powered-By"]
|
|
58
|
+
$CFRay = $Response.Headers["CF-Ray"]
|
|
59
|
+
$CFCache = $Response.Headers["CF-Cache-Status"]
|
|
60
|
+
|
|
61
|
+
if ($Server) { $TechStack += "Server: $Server" }
|
|
62
|
+
if ($XPB) { $TechStack += "X-Powered-By: $XPB" }
|
|
63
|
+
if ($CFRay) { $TechStack += "CDN: Cloudflare" }
|
|
64
|
+
if ($CFCache) { $TechStack += "CDN Cache: Active" }
|
|
65
|
+
|
|
61
66
|
} catch {
|
|
62
67
|
try {
|
|
63
68
|
$Response = Invoke-WebRequest -Uri ($Target -replace "^https", "http") -Method Head -TimeoutSec 15 -ErrorAction Stop
|
|
64
69
|
$Headers = $Response.Headers
|
|
65
70
|
} catch {
|
|
66
|
-
Write-Host "
|
|
71
|
+
Write-Host "Cannot connect to target" -ForegroundColor Red
|
|
67
72
|
$Headers = @{}
|
|
68
73
|
}
|
|
69
74
|
}
|
|
70
75
|
|
|
71
|
-
# HSTS
|
|
72
76
|
$HSTS = $Headers["Strict-Transport-Security"]
|
|
73
77
|
if ($HSTS) {
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
$HeaderGood += "HSTS: Present"
|
|
79
|
+
Write-Host " HSTS: Present" -ForegroundColor Green
|
|
80
|
+
if ($HSTS -match "max-age=([3-9]\d{5,}|\d{7,})") {
|
|
81
|
+
$HeaderScore += 15
|
|
82
|
+
$HeaderGood += "HSTS: max-age >= 1 year"
|
|
83
|
+
} elseif ($HSTS -match "max-age=\d{5,6}") {
|
|
84
|
+
$HeaderScore += 8
|
|
85
|
+
$HeaderIssues += "HSTS max-age < 1 year (recommended: 31536000)"
|
|
86
|
+
}
|
|
76
87
|
} else {
|
|
77
|
-
Write-Host "
|
|
88
|
+
Write-Host " HSTS: Missing" -ForegroundColor Red
|
|
78
89
|
$HeaderIssues += "HSTS not implemented"
|
|
79
90
|
}
|
|
80
91
|
|
|
81
|
-
# CSP
|
|
82
92
|
$CSP = $Headers["Content-Security-Policy"]
|
|
83
93
|
if ($CSP) {
|
|
84
|
-
|
|
94
|
+
$HeaderGood += "CSP: Present"
|
|
95
|
+
Write-Host " CSP: Present" -ForegroundColor Green
|
|
85
96
|
$HeaderScore += 20
|
|
86
|
-
if ($CSP -match "unsafe-inline") {
|
|
97
|
+
if ($CSP -match "unsafe-inline") {
|
|
98
|
+
$HeaderIssues += "CSP contains 'unsafe-inline' (XSS risk)"
|
|
99
|
+
Write-Host " Warning: Contains unsafe-inline" -ForegroundColor Yellow
|
|
100
|
+
}
|
|
101
|
+
if ($CSP -match "unsafe-eval") {
|
|
102
|
+
$HeaderIssues += "CSP contains 'unsafe-eval'"
|
|
103
|
+
}
|
|
87
104
|
} else {
|
|
88
|
-
Write-Host "
|
|
105
|
+
Write-Host " CSP: Missing" -ForegroundColor Red
|
|
89
106
|
$HeaderIssues += "CSP not implemented (XSS risk)"
|
|
90
107
|
}
|
|
91
108
|
|
|
92
|
-
# X-Content-Type-Options
|
|
93
109
|
$XCTO = $Headers["X-Content-Type-Options"]
|
|
94
110
|
if ($XCTO -eq "nosniff") {
|
|
95
|
-
|
|
111
|
+
$HeaderGood += "X-Content-Type-Options: nosniff"
|
|
112
|
+
Write-Host " X-Content-Type-Options: nosniff" -ForegroundColor Green
|
|
96
113
|
$HeaderScore += 10
|
|
97
114
|
} else {
|
|
98
|
-
Write-Host "
|
|
115
|
+
Write-Host " X-Content-Type-Options: Missing" -ForegroundColor Red
|
|
99
116
|
$HeaderIssues += "X-Content-Type-Options not set"
|
|
100
117
|
}
|
|
101
118
|
|
|
102
|
-
# X-Frame-Options
|
|
103
119
|
$XFO = $Headers["X-Frame-Options"]
|
|
104
120
|
if ($XFO -eq "DENY" -or $XFO -eq "SAMEORIGIN") {
|
|
105
|
-
|
|
121
|
+
$HeaderGood += "X-Frame-Options: $XFO"
|
|
122
|
+
Write-Host " X-Frame-Options: $XFO" -ForegroundColor Green
|
|
106
123
|
$HeaderScore += if ($XFO -eq "DENY") { 10 } else { 8 }
|
|
107
124
|
} else {
|
|
108
|
-
Write-Host "
|
|
125
|
+
Write-Host " X-Frame-Options: Missing" -ForegroundColor Red
|
|
109
126
|
$HeaderIssues += "X-Frame-Options not set (clickjacking risk)"
|
|
110
127
|
}
|
|
111
128
|
|
|
112
|
-
# Referrer-Policy
|
|
113
129
|
$RP = $Headers["Referrer-Policy"]
|
|
114
130
|
if ($RP) {
|
|
115
|
-
|
|
131
|
+
$HeaderGood += "Referrer-Policy: $RP"
|
|
132
|
+
Write-Host " Referrer-Policy: Present" -ForegroundColor Green
|
|
116
133
|
$HeaderScore += 10
|
|
117
134
|
} else {
|
|
118
|
-
Write-Host "
|
|
135
|
+
Write-Host " Referrer-Policy: Missing" -ForegroundColor Yellow
|
|
119
136
|
$HeaderScore += 5
|
|
120
137
|
}
|
|
121
138
|
|
|
122
|
-
|
|
123
|
-
$
|
|
124
|
-
|
|
125
|
-
Write-Host "
|
|
139
|
+
$PP = $Headers["Permissions-Policy"]
|
|
140
|
+
if ($PP) {
|
|
141
|
+
$HeaderGood += "Permissions-Policy: Present"
|
|
142
|
+
Write-Host " Permissions-Policy: Present" -ForegroundColor Green
|
|
126
143
|
$HeaderScore += 10
|
|
127
144
|
} else {
|
|
128
|
-
Write-Host "
|
|
145
|
+
Write-Host " Permissions-Policy: Missing" -ForegroundColor Yellow
|
|
129
146
|
$HeaderScore += 5
|
|
130
147
|
}
|
|
131
148
|
|
|
132
|
-
|
|
133
|
-
$
|
|
134
|
-
|
|
135
|
-
Write-Host "
|
|
136
|
-
$
|
|
149
|
+
$CC = $Headers["Cache-Control"]
|
|
150
|
+
if ($CC -match "no-store|no-cache|private") {
|
|
151
|
+
$HeaderGood += "Cache-Control: $CC"
|
|
152
|
+
Write-Host " Cache-Control: $CC" -ForegroundColor Green
|
|
153
|
+
$HeaderScore += 5
|
|
154
|
+
} else {
|
|
155
|
+
Write-Host " Cache-Control: Not optimal" -ForegroundColor Yellow
|
|
156
|
+
$HeaderScore += 2
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# Check Server for version leaks
|
|
160
|
+
if ($Server -match "/\d|Apache/[0-9]|nginx/[0-9]|Microsoft-IIS/[0-9]") {
|
|
161
|
+
Write-Host " Server: Leaks version - $Server" -ForegroundColor Yellow
|
|
162
|
+
$HeaderIssues += "Server header leaks version: $Server"
|
|
163
|
+
} elseif ($Server) {
|
|
164
|
+
Write-Host " Server: $Server" -ForegroundColor Gray
|
|
137
165
|
}
|
|
138
166
|
|
|
139
|
-
# X-Powered-By
|
|
140
|
-
$XPB = $Headers["X-Powered-By"]
|
|
141
167
|
if ($XPB) {
|
|
142
|
-
Write-Host "
|
|
143
|
-
$HeaderIssues += "X-Powered-By leaks technology"
|
|
168
|
+
Write-Host " X-Powered-By: $XPB" -ForegroundColor Yellow
|
|
169
|
+
$HeaderIssues += "X-Powered-By leaks technology: $XPB"
|
|
144
170
|
}
|
|
145
171
|
|
|
172
|
+
# Check CORS
|
|
146
173
|
Write-Host ""
|
|
147
|
-
Write-Host "
|
|
174
|
+
Write-Host "Phase 1b: CORS Analysis" -ForegroundColor Yellow
|
|
175
|
+
|
|
176
|
+
$ACAO = $Headers["Access-Control-Allow-Origin"]
|
|
177
|
+
$ACAC = $Headers["Access-Control-Allow-Credentials"]
|
|
178
|
+
$ACAM = $Headers["Access-Control-Allow-Methods"]
|
|
148
179
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
180
|
+
if ($ACAO) {
|
|
181
|
+
Write-Host " CORS Origin: $ACAO" -ForegroundColor $(if($ACAO -eq "*"){"Yellow"}else{"Green"})
|
|
182
|
+
if ($ACAO -eq "*") {
|
|
183
|
+
$CORSIssues += "CORS allows all origins (Access-Control-Allow-Origin: *)"
|
|
184
|
+
Write-Host " Warning: Allows all origins" -ForegroundColor Yellow
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if ($ACAC -eq "true" -and $ACAO -eq "*") {
|
|
189
|
+
$CORSIssues += "CORS: Wildcard with credentials (invalid but misconfigured)"
|
|
190
|
+
Write-Host " CRITICAL: Wildcard with credentials!" -ForegroundColor Red
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if ($ACAM) {
|
|
194
|
+
Write-Host " CORS Methods: $ACAM" -ForegroundColor Gray
|
|
195
|
+
}
|
|
152
196
|
|
|
153
197
|
Write-Host ""
|
|
154
|
-
Write-Host "
|
|
155
|
-
|
|
156
|
-
|
|
198
|
+
Write-Host " Header Score: $HeaderScore/100" -ForegroundColor $(if($HeaderScore -ge 70){"Green"}else{"Red"})
|
|
199
|
+
|
|
200
|
+
# PHASE 2: Exposed Files
|
|
201
|
+
Write-Host ""
|
|
202
|
+
Write-Host "Phase 2: Exposed Files" -ForegroundColor Yellow
|
|
157
203
|
|
|
158
|
-
$ExposedFiles = @()
|
|
159
204
|
$CriticalPaths = @(
|
|
160
|
-
"/.env"
|
|
161
|
-
"/
|
|
162
|
-
"/
|
|
163
|
-
"/
|
|
164
|
-
"/
|
|
165
|
-
"/
|
|
205
|
+
@{ Path="/.env"; Risk="CRITICAL"; Desc="Environment variables" },
|
|
206
|
+
@{ Path="/.git/config"; Risk="CRITICAL"; Desc="Git repository" },
|
|
207
|
+
@{ Path="/.git/"; Risk="CRITICAL"; Desc="Git directory" },
|
|
208
|
+
@{ Path="/config.php"; Risk="HIGH"; Desc="PHP configuration" },
|
|
209
|
+
@{ Path="/settings.py"; Risk="HIGH"; Desc="Python settings" },
|
|
210
|
+
@{ Path="/backup.zip"; Risk="CRITICAL"; Desc="Backup archive" },
|
|
211
|
+
@{ Path="/database.sql"; Risk="CRITICAL"; Desc="Database dump" },
|
|
212
|
+
@{ Path="/db.sql"; Risk="CRITICAL"; Desc="Database dump" },
|
|
213
|
+
@{ Path="/admin/"; Risk="HIGH"; Desc="Admin panel" },
|
|
214
|
+
@{ Path="/debug/"; Risk="HIGH"; Desc="Debug endpoint" },
|
|
215
|
+
@{ Path="/phpmyadmin/"; Risk="CRITICAL"; Desc="Database UI" },
|
|
216
|
+
@{ Path="/actuator/env"; Risk="CRITICAL"; Desc="Spring Boot env" }
|
|
166
217
|
)
|
|
167
218
|
|
|
168
|
-
|
|
219
|
+
$TrueExposedFiles = @()
|
|
220
|
+
$FalsePositiveFiles = @()
|
|
221
|
+
|
|
222
|
+
foreach ($item in $CriticalPaths) {
|
|
169
223
|
try {
|
|
170
|
-
$resp = Invoke-WebRequest -Uri "$Target$
|
|
171
|
-
if ($resp.StatusCode -ne 404) {
|
|
172
|
-
|
|
173
|
-
$
|
|
224
|
+
$resp = Invoke-WebRequest -Uri "$Target$($item.Path)" -Method Head -TimeoutSec 5 -ErrorAction SilentlyContinue
|
|
225
|
+
if ($resp.StatusCode -ne 404 -and $resp.StatusCode -ne 403) {
|
|
226
|
+
$ContentType = $resp.Headers["Content-Type"]
|
|
227
|
+
$BodyPreview = ""
|
|
228
|
+
|
|
229
|
+
# Check if it's a real sensitive file or SPA
|
|
230
|
+
if ($ContentType -match "text/html|application/octet-stream" -and $item.Path -notmatch "\.zip|\.sql|\.env|\.git") {
|
|
231
|
+
# Check body content
|
|
232
|
+
try {
|
|
233
|
+
$bodyResp = Invoke-WebRequest -Uri "$Target$($item.Path)" -TimeoutSec 5 -ErrorAction SilentlyContinue
|
|
234
|
+
$BodyPreview = $bodyResp.Content.Substring(0, [Math]::Min(200, $bodyResp.Content.Length))
|
|
235
|
+
} catch {}
|
|
236
|
+
|
|
237
|
+
if ($BodyPreview -match "root|div|html|<!" -and $BodyPreview.Length -lt 1000) {
|
|
238
|
+
# Likely SPA false positive
|
|
239
|
+
$FalsePositiveFiles += $item
|
|
240
|
+
Write-Host " [FP] $($item.Path) - HTTP $($resp.StatusCode) (likely SPA)" -ForegroundColor Gray
|
|
241
|
+
} else {
|
|
242
|
+
# Real exposed file
|
|
243
|
+
$TrueExposedFiles += $item
|
|
244
|
+
Write-Host " FOUND: $($item.Path) (HTTP $($resp.StatusCode))" -ForegroundColor Red
|
|
245
|
+
}
|
|
246
|
+
} else {
|
|
247
|
+
# Real file
|
|
248
|
+
$TrueExposedFiles += $item
|
|
249
|
+
Write-Host " FOUND: $($item.Path) (HTTP $($resp.StatusCode))" -ForegroundColor Red
|
|
250
|
+
}
|
|
174
251
|
}
|
|
175
252
|
} catch {}
|
|
176
253
|
}
|
|
177
254
|
|
|
178
|
-
if ($
|
|
179
|
-
Write-Host "
|
|
255
|
+
if ($TrueExposedFiles.Count -eq 0) {
|
|
256
|
+
Write-Host " No sensitive files exposed" -ForegroundColor Green
|
|
180
257
|
}
|
|
181
258
|
|
|
182
|
-
#
|
|
183
|
-
# PHASE 3: PORT CHECK
|
|
184
|
-
# ═══════════════════════════════════════════════════════════
|
|
185
|
-
|
|
259
|
+
# PHASE 3: Port Check
|
|
186
260
|
Write-Host ""
|
|
187
|
-
Write-Host "
|
|
188
|
-
Write-Host "🔌 PHASE 3: Quick Port Check" -ForegroundColor Cyan
|
|
189
|
-
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
261
|
+
Write-Host "Phase 3: Port Check" -ForegroundColor Yellow
|
|
190
262
|
|
|
191
263
|
$Ports = @(80, 443, 8080, 3306, 5432, 6379, 27017, 22)
|
|
192
|
-
$OpenPorts = @()
|
|
193
264
|
|
|
194
265
|
foreach ($Port in $Ports) {
|
|
195
266
|
try {
|
|
@@ -198,311 +269,202 @@ foreach ($Port in $Ports) {
|
|
|
198
269
|
$Wait = $Result.AsyncWaitHandle.WaitOne(500)
|
|
199
270
|
|
|
200
271
|
if ($Wait -and $TCP.Connected) {
|
|
201
|
-
$Service = switch ($Port) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
3306 { "MySQL" }
|
|
206
|
-
5432 { "PostgreSQL" }
|
|
207
|
-
6379 { "Redis" }
|
|
208
|
-
27017 { "MongoDB" }
|
|
209
|
-
22 { "SSH" }
|
|
210
|
-
}
|
|
211
|
-
$Risk = if ($Port -in @(3306, 5432, 6379, 27017)) { "HIGH" } else { "INFO" }
|
|
212
|
-
|
|
213
|
-
Write-Host "⚠️ Port $Port ($Service) - OPEN" -ForegroundColor $(if($Risk -eq "HIGH"){"Red"}else{"Yellow"})
|
|
214
|
-
$OpenPorts += [PSCustomObject]@{ Port = $Port; Service = $Service; Risk = $Risk }
|
|
272
|
+
$Service = switch ($Port) { 80{"HTTP"} 443{"HTTPS"} 8080{"HTTP-Alt"} 3306{"MySQL"} 5432{"PostgreSQL"} 6379{"Redis"} 27017{"MongoDB"} 22{"SSH"} }
|
|
273
|
+
$Risk = if ($Port -in @(3306,5432,6379,27017)) { "HIGH" } else { "INFO" }
|
|
274
|
+
Write-Host " Port $Port ($Service) - OPEN" -ForegroundColor $(if($Risk -eq "HIGH"){"Red"}else{"Gray"})
|
|
275
|
+
$OpenPorts += [PSCustomObject]@{ Port=$Port; Service=$Service; Risk=$Risk }
|
|
215
276
|
}
|
|
216
277
|
$TCP.Close()
|
|
217
278
|
} catch {}
|
|
218
279
|
}
|
|
219
280
|
|
|
220
|
-
|
|
221
|
-
Write-Host "✅ No common ports detected" -ForegroundColor Green
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
# ═══════════════════════════════════════════════════════════
|
|
225
|
-
# PHASE 4: BASIC INJECTION TEST
|
|
226
|
-
# ═══════════════════════════════════════════════════════════
|
|
227
|
-
|
|
281
|
+
# PHASE 4: Injection Tests
|
|
228
282
|
Write-Host ""
|
|
229
|
-
Write-Host "
|
|
230
|
-
Write-Host "💉 PHASE 4: Basic Injection Tests" -ForegroundColor Cyan
|
|
231
|
-
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
283
|
+
Write-Host "Phase 4: Injection Tests" -ForegroundColor Yellow
|
|
232
284
|
|
|
233
|
-
# XSS Test
|
|
234
|
-
Write-Host "Testing XSS..." -ForegroundColor Gray
|
|
235
285
|
$XSSPayload = "<script>alert(1)</script>"
|
|
236
286
|
try {
|
|
237
287
|
$Response = Invoke-WebRequest -Uri "$Target/search?q=$XSSPayload" -TimeoutSec 10 -ErrorAction SilentlyContinue
|
|
238
288
|
if ($Response.Content -match [regex]::Escape($XSSPayload)) {
|
|
239
|
-
Write-Host "
|
|
289
|
+
Write-Host " XSS: Possible reflection detected" -ForegroundColor Yellow
|
|
240
290
|
} else {
|
|
241
|
-
Write-Host "
|
|
291
|
+
Write-Host " XSS: No obvious reflection" -ForegroundColor Green
|
|
242
292
|
}
|
|
243
|
-
} catch {
|
|
244
|
-
Write-Host "✅ No obvious XSS reflection" -ForegroundColor Green
|
|
245
|
-
}
|
|
293
|
+
} catch { Write-Host " XSS: No obvious reflection" -ForegroundColor Green }
|
|
246
294
|
|
|
247
|
-
# SQLi Test
|
|
248
|
-
Write-Host "Testing SQL Injection..." -ForegroundColor Gray
|
|
249
295
|
$SQLPayload = "' OR '1'='1"
|
|
250
296
|
try {
|
|
251
297
|
$Response = Invoke-WebRequest -Uri "$Target/?id=$SQLPayload" -TimeoutSec 10 -ErrorAction SilentlyContinue
|
|
252
|
-
$SQLErrors = @("SQL syntax",
|
|
298
|
+
$SQLErrors = @("SQL syntax","MySQL","PostgreSQL","sqlite","Microsoft SQL","Warning: mysql")
|
|
253
299
|
$Found = $SQLErrors | Where-Object { $Response.Content -match $_ }
|
|
254
300
|
if ($Found) {
|
|
255
|
-
Write-Host "
|
|
301
|
+
Write-Host " SQLi: Error detected" -ForegroundColor Yellow
|
|
256
302
|
} else {
|
|
257
|
-
Write-Host "
|
|
303
|
+
Write-Host " SQLi: No obvious errors" -ForegroundColor Green
|
|
258
304
|
}
|
|
259
|
-
} catch {
|
|
260
|
-
Write-Host "✅ No obvious SQL errors" -ForegroundColor Green
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
# ═══════════════════════════════════════════════════════════
|
|
264
|
-
# PHASE 5: SSL/TLS CHECK
|
|
265
|
-
# ═══════════════════════════════════════════════════════════
|
|
305
|
+
} catch { Write-Host " SQLi: No obvious errors" -ForegroundColor Green }
|
|
266
306
|
|
|
307
|
+
# PHASE 5: SSL Check
|
|
267
308
|
Write-Host ""
|
|
268
|
-
Write-Host "
|
|
269
|
-
Write-Host "🔐 PHASE 5: SSL/TLS Check" -ForegroundColor Cyan
|
|
270
|
-
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
271
|
-
|
|
272
|
-
$SSLIssues = @()
|
|
309
|
+
Write-Host "Phase 5: SSL/TLS Check" -ForegroundColor Yellow
|
|
273
310
|
|
|
274
311
|
if ($Scheme -eq "https") {
|
|
275
|
-
Write-Host "
|
|
276
|
-
|
|
277
|
-
# Check HSTS
|
|
278
|
-
if ($HSTS -notmatch "max-age=([3-9]\d{5,}|\d{7,})") {
|
|
279
|
-
Write-Host "⚠️ HSTS max-age should be at least 1 year" -ForegroundColor Yellow
|
|
280
|
-
$SSLIssues += "HSTS max-age too short"
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
Write-Host "📝 For full SSL analysis: https://ssllabs.com/ssltest/analyze.html?d=$Domain" -ForegroundColor Cyan
|
|
312
|
+
Write-Host " HTTPS: Enabled" -ForegroundColor Green
|
|
284
313
|
} else {
|
|
285
|
-
Write-Host "
|
|
286
|
-
$SSLIssues += "HTTPS not enabled"
|
|
314
|
+
Write-Host " HTTPS: NOT enforced" -ForegroundColor Red
|
|
287
315
|
}
|
|
288
316
|
|
|
289
|
-
# ═══════════════════════════════════════════════════════════
|
|
290
317
|
# SUMMARY
|
|
291
|
-
# ═══════════════════════════════════════════════════════════
|
|
292
|
-
|
|
293
318
|
Write-Host ""
|
|
294
|
-
Write-Host "
|
|
295
|
-
Write-Host "
|
|
296
|
-
Write-Host "
|
|
319
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
320
|
+
Write-Host " SCAN SUMMARY" -ForegroundColor Cyan
|
|
321
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
297
322
|
Write-Host ""
|
|
323
|
+
Write-Host "Header Score: $HeaderScore/100" -ForegroundColor $(if($HeaderScore -ge 70){"Green"}else{"Red"})
|
|
324
|
+
Write-Host "True Exposed: $($TrueExposedFiles.Count)" -ForegroundColor $(if($TrueExposedFiles.Count -gt 0){"Red"}else{"Green"})
|
|
325
|
+
Write-Host "False Positives: $($FalsePositiveFiles.Count)" -ForegroundColor Gray
|
|
326
|
+
Write-Host "Open Ports: $($OpenPorts.Count)" -ForegroundColor $(if(($OpenPorts | Where-Object{$_.Risk -eq "HIGH"}).Count -gt 0){"Red"}else{"Green"})
|
|
327
|
+
|
|
328
|
+
# Determine Overall Risk
|
|
329
|
+
$CriticalPorts = ($OpenPorts | Where-Object { $_.Risk -eq "HIGH" }).Count
|
|
330
|
+
$OverallRisk = if ($TrueExposedFiles.Count -gt 0 -or $CriticalPorts -gt 2 -or $HeaderScore -lt 40) { "HIGH" }
|
|
331
|
+
elseif ($TrueExposedFiles.Count -gt 0 -or $CriticalPorts -gt 0 -or $CORSIssues.Count -gt 0) { "MEDIUM" }
|
|
332
|
+
elseif ($HeaderScore -lt 70 -or $FalsePositiveFiles.Count -gt 0) { "LOW" }
|
|
333
|
+
else { "LOW" }
|
|
334
|
+
|
|
335
|
+
# Generate Report
|
|
336
|
+
$HeaderGrade = if ($HeaderScore -ge 90) { "A - Excellent" }
|
|
337
|
+
elseif ($HeaderScore -ge 80) { "B - Good" }
|
|
338
|
+
elseif ($HeaderScore -ge 70) { "B - Good" }
|
|
339
|
+
elseif ($HeaderScore -ge 50) { "C - Needs Improvement" }
|
|
340
|
+
else { "D/F - Poor" }
|
|
341
|
+
|
|
342
|
+
$IssuesSection = if ($HeaderIssues.Count -gt 0) { "- " + ($HeaderIssues -join "`n- ") } else { "None" }
|
|
343
|
+
|
|
344
|
+
$ExposedSection = ""
|
|
345
|
+
if ($TrueExposedFiles.Count -gt 0) {
|
|
346
|
+
$ExposedSection = "| Path | Status | Risk | Description |`n"
|
|
347
|
+
$ExposedSection += "|------|--------|------|-------------|`n"
|
|
348
|
+
foreach ($f in $TrueExposedFiles) {
|
|
349
|
+
$ExposedSection += "| $($f.Path) | OPEN | $($f.Risk) | $($f.Desc) |`n"
|
|
350
|
+
}
|
|
351
|
+
} else {
|
|
352
|
+
$ExposedSection = "No sensitive files actually exposed."
|
|
353
|
+
}
|
|
298
354
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
355
|
+
$FalsePOSection = ""
|
|
356
|
+
if ($FalsePositiveFiles.Count -gt 0) {
|
|
357
|
+
$FalsePOSection = "### False Positives (Not Real Issues)`n`n"
|
|
358
|
+
$FalsePOSection += "These paths returned HTML/SPA content, not actual sensitive files:`n`n"
|
|
359
|
+
foreach ($f in $FalsePositiveFiles) {
|
|
360
|
+
$FalsePOSection += "- $($f.Path) - HTTP 200 (SPA routing)`n"
|
|
361
|
+
}
|
|
362
|
+
$FalsePOSection += "`n"
|
|
363
|
+
}
|
|
304
364
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
365
|
+
$CORSSection = ""
|
|
366
|
+
if ($CORSIssues.Count -gt 0) {
|
|
367
|
+
$CORSSection = "### CORS Issues`n`n"
|
|
368
|
+
foreach ($c in $CORSIssues) {
|
|
369
|
+
$CORSSection += "- $c`n"
|
|
370
|
+
}
|
|
371
|
+
$CORSSection += "`n"
|
|
372
|
+
}
|
|
308
373
|
|
|
309
|
-
|
|
310
|
-
|
|
374
|
+
$PortSection = ""
|
|
375
|
+
if ($OpenPorts.Count -gt 0) {
|
|
376
|
+
$PortSection = "| Port | Service | Risk |`n|------|---------|------|`n"
|
|
377
|
+
foreach ($p in $OpenPorts) {
|
|
378
|
+
$PortSection += "| $($p.Port) | $($p.Service) | $($p.Risk) |`n"
|
|
379
|
+
}
|
|
380
|
+
} else {
|
|
381
|
+
$PortSection = "No common ports detected.`n"
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
$Remediation = @()
|
|
385
|
+
if ($TrueExposedFiles.Count -gt 0) { $Remediation += "1. **URGENT: Remove exposed sensitive files**" }
|
|
386
|
+
if ($CORSIssues.Count -gt 0) { $Remediation += "2. Review CORS policy" }
|
|
387
|
+
if ($HeaderIssues -match "unsafe-inline") { $Remediation += "3. Consider removing unsafe-inline from CSP" }
|
|
388
|
+
if ($HeaderScore -lt 70) { $Remediation += "4. Improve security headers" }
|
|
389
|
+
if ($Remediation.Count -eq 0) { $Remediation += "1. Continue monitoring security" }
|
|
390
|
+
|
|
391
|
+
$TechSection = if ($TechStack.Count -gt 0) { "- " + ($TechStack -join "`n- ") } else { "Not detected" }
|
|
311
392
|
|
|
312
393
|
$Report = @"
|
|
313
|
-
#
|
|
394
|
+
# Security Audit Report
|
|
314
395
|
|
|
315
396
|
**Target:** $Target
|
|
316
397
|
**Domain:** $Domain
|
|
317
398
|
**Date:** $Date
|
|
318
|
-
**Scanner:** Full Security Scan
|
|
399
|
+
**Scanner:** Full Security Scan v3.0
|
|
400
|
+
**Author:** Rz (@soulofzephir)
|
|
319
401
|
|
|
320
402
|
---
|
|
321
403
|
|
|
322
|
-
##
|
|
404
|
+
## Executive Summary
|
|
323
405
|
|
|
324
406
|
| Metric | Value |
|
|
325
407
|
|--------|-------|
|
|
326
|
-
|
|
|
327
|
-
|
|
|
328
|
-
|
|
|
329
|
-
| Exposed Files | $($ExposedFiles.Count) |
|
|
408
|
+
| Header Score | $HeaderScore/100 ($HeaderGrade) |
|
|
409
|
+
| True Exposed Files | $($TrueExposedFiles.Count) |
|
|
410
|
+
| False Positives | $($FalsePositiveFiles.Count) |
|
|
330
411
|
| Open Ports | $($OpenPorts.Count) |
|
|
331
|
-
|
|
|
332
|
-
|
|
333
|
-
### Overall Risk Assessment
|
|
334
|
-
|
|
335
|
-
$(if ($HeaderScore -lt 50 -or $ExposedFiles.Count -gt 0 -or ($OpenPorts | Where-Object {$_.Risk -eq "HIGH"}).Count -gt 0) {
|
|
336
|
-
"🔴 **HIGH RISK** - Issues found requiring immediate attention"
|
|
337
|
-
} elseif ($HeaderScore -lt 70 -or $ExposedFiles.Count -gt 0) {
|
|
338
|
-
"🟠 **MEDIUM RISK** - Some security improvements recommended"
|
|
339
|
-
} else {
|
|
340
|
-
"🟢 **LOW RISK** - Minor issues to address"
|
|
341
|
-
})
|
|
412
|
+
| **Overall Risk** | **$OverallRisk** |
|
|
342
413
|
|
|
343
414
|
---
|
|
344
415
|
|
|
345
|
-
##
|
|
416
|
+
## Security Headers
|
|
346
417
|
|
|
347
|
-
###
|
|
418
|
+
### Score: $HeaderScore/100 ($HeaderGrade)
|
|
348
419
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
elseif ($HeaderScore -ge 50) { "⚠️ **Grade C - Needs Improvement**" }
|
|
352
|
-
else { "❌ **Grade D/F - Poor**" })
|
|
420
|
+
#### Good Headers
|
|
421
|
+
$($HeaderGood -join "`n")
|
|
353
422
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
| HSTS | $(if ($HSTS) { "✅ Present" } else { "❌ Missing" }) |
|
|
357
|
-
| CSP | $(if ($CSP) { "✅ Present" } else { "❌ Missing" }) |
|
|
358
|
-
| X-Content-Type-Options | $(if ($XCTO -eq "nosniff") { "✅ nosniff" } else { "❌ Missing" }) |
|
|
359
|
-
| X-Frame-Options | $(if ($XFO) { "✅ $XFO" } else { "❌ Missing" }) |
|
|
360
|
-
| Referrer-Policy | $(if ($RP) { "✅ Present" } else { "⚠️ Missing" }) |
|
|
361
|
-
| Cache-Control | $(if ($CC) { "✅ Present" } else { "⚠️ Missing" }) |
|
|
362
|
-
| Server | $(if ($Server) { "⚠️ $Server" } else { "✅ Hidden" }) |
|
|
363
|
-
| X-Powered-By | $(if ($XPB) { "⚠️ $XPB" } else { "✅ Hidden" }) |
|
|
364
|
-
|
|
365
|
-
### Issues Found
|
|
366
|
-
|
|
367
|
-
$(if ($HeaderIssues.Count -gt 0) {
|
|
368
|
-
foreach ($issue in $HeaderIssues) {
|
|
369
|
-
"- ⚠️ $issue"
|
|
370
|
-
}
|
|
371
|
-
} else {
|
|
372
|
-
"✅ No major header issues"
|
|
373
|
-
})
|
|
423
|
+
#### Issues Found
|
|
424
|
+
$IssuesSection
|
|
374
425
|
|
|
375
426
|
---
|
|
376
427
|
|
|
377
|
-
##
|
|
428
|
+
## Exposed Files
|
|
378
429
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
} else {
|
|
382
|
-
"### ✅ No Critical Files Exposed"
|
|
383
|
-
})
|
|
384
|
-
|
|
385
|
-
| Path | Risk |
|
|
386
|
-
|------|------|
|
|
387
|
-
$(foreach ($file in $ExposedFiles) {
|
|
388
|
-
"| $file | 🔴 CRITICAL |"
|
|
389
|
-
})
|
|
390
|
-
|
|
391
|
-
**Recommendation:** Remove or protect these files from public access.
|
|
430
|
+
### True Exposures
|
|
431
|
+
$ExposedSection
|
|
392
432
|
|
|
433
|
+
$FalsePOSection
|
|
434
|
+
## CORS Analysis
|
|
435
|
+
$CORSSection
|
|
436
|
+
## Port Scan Results
|
|
437
|
+
$PortSection
|
|
438
|
+
## Technology Stack
|
|
439
|
+
$TechSection
|
|
393
440
|
---
|
|
394
441
|
|
|
395
|
-
##
|
|
396
|
-
|
|
397
|
-
$(if (($OpenPorts | Where-Object {$_.Risk -eq "HIGH"}).Count -gt 0) {
|
|
398
|
-
"### 🚨 High-Risk Ports Open"
|
|
399
|
-
} else {
|
|
400
|
-
"### ✅ No High-Risk Ports Detected"
|
|
401
|
-
})
|
|
402
|
-
|
|
403
|
-
| Port | Service | Risk |
|
|
404
|
-
|------|---------|------|
|
|
405
|
-
$(foreach ($p in $OpenPorts) {
|
|
406
|
-
"| $($p.Port) | $($p.Service) | $(if($p.Risk -eq "HIGH"){"🔴 HIGH"}else{"🟢 INFO"}) |"
|
|
407
|
-
})
|
|
442
|
+
## Remediation
|
|
408
443
|
|
|
409
|
-
|
|
444
|
+
$(if ($Remediation.Count -gt 0) { $Remediation -join "`n" })
|
|
410
445
|
|
|
411
446
|
---
|
|
412
447
|
|
|
413
|
-
##
|
|
414
|
-
|
|
415
|
-
Basic automated tests completed.
|
|
448
|
+
## Quick Links
|
|
416
449
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
| XSS Reflection | ⚠️ Review manually |
|
|
420
|
-
| SQL Injection | ⚠️ Review manually |
|
|
421
|
-
|
|
422
|
-
**Note:** For comprehensive injection testing, use:
|
|
423
|
-
- SQLMap: \`sqlmap -u "$Target"\`
|
|
424
|
-
- Dalfox: \`dalfox url "$Target"\`
|
|
450
|
+
- Security Headers: https://securityheaders.com/?q=$Domain
|
|
451
|
+
- SSL Labs: https://ssllabs.com/ssltest/analyze.html?d=$Domain
|
|
425
452
|
|
|
426
453
|
---
|
|
427
454
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
$(if ($Scheme -eq "https") {
|
|
431
|
-
"✅ HTTPS is enabled"
|
|
432
|
-
} else {
|
|
433
|
-
"❌ HTTPS is NOT enabled"
|
|
434
|
-
})
|
|
435
|
-
|
|
436
|
-
$(if ($SSLIssues.Count -gt 0) {
|
|
437
|
-
"### ⚠️ SSL Issues:"
|
|
438
|
-
foreach ($issue in $SSLIssues) {
|
|
439
|
-
"- $issue"
|
|
440
|
-
}
|
|
441
|
-
})
|
|
442
|
-
|
|
443
|
-
**Full SSL Analysis:** https://ssllabs.com/ssltest/analyze.html?d=$Domain
|
|
444
|
-
|
|
445
|
-
---
|
|
446
|
-
|
|
447
|
-
## 🛡️ Remediation Priority
|
|
448
|
-
|
|
449
|
-
### Immediate (Critical)
|
|
450
|
-
1. Implement missing security headers
|
|
451
|
-
2. Remove/block exposed sensitive files (.env, .git/, backups)
|
|
452
|
-
3. Close database ports from public access
|
|
453
|
-
|
|
454
|
-
### Short-term
|
|
455
|
-
1. Enable HSTS with long max-age
|
|
456
|
-
2. Configure Content-Security-Policy
|
|
457
|
-
3. Set up proper Cache-Control
|
|
458
|
-
4. Hide server information
|
|
459
|
-
|
|
460
|
-
### Long-term
|
|
461
|
-
1. Regular security scanning
|
|
462
|
-
2. Implement OWASP Top 10 controls
|
|
463
|
-
3. Set up monitoring and alerting
|
|
464
|
-
4. Security headers automated testing
|
|
465
|
-
|
|
466
|
-
---
|
|
467
|
-
|
|
468
|
-
## 🔗 Recommended Tools for Deeper Analysis
|
|
469
|
-
|
|
470
|
-
| Tool | Purpose |
|
|
471
|
-
|------|---------|
|
|
472
|
-
| Nuclei | Vulnerability scanning |
|
|
473
|
-
| SQLMap | SQL injection testing |
|
|
474
|
-
| Dalfox | XSS scanning |
|
|
475
|
-
| Nmap | Full port scan |
|
|
476
|
-
| testssl.sh | SSL/TLS audit |
|
|
477
|
-
| Burp Suite | Web vulnerability testing |
|
|
478
|
-
|
|
479
|
-
---
|
|
480
|
-
|
|
481
|
-
## 📄 Report Location
|
|
482
|
-
|
|
483
|
-
**File:** \`$OutputFile\`
|
|
484
|
-
**Generated:** $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
|
|
485
|
-
**Author:** Rz (@soulofzephir)
|
|
486
|
-
|
|
487
|
-
---
|
|
488
|
-
|
|
489
|
-
**⚠️ Disclaimer:** This is an automated scan. Manual testing recommended for comprehensive security assessment.
|
|
455
|
+
**Generated:** $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
|
|
490
456
|
"@
|
|
491
457
|
|
|
492
458
|
$Report | Out-File -FilePath $OutputFile -Encoding UTF8
|
|
493
459
|
|
|
494
|
-
# ═══════════════════════════════════════════════════════════
|
|
495
|
-
# COMPLETE
|
|
496
|
-
# ═══════════════════════════════════════════════════════════
|
|
497
|
-
|
|
498
460
|
Write-Host ""
|
|
499
|
-
Write-Host "
|
|
500
|
-
Write-Host "
|
|
501
|
-
Write-Host "
|
|
461
|
+
Write-Host "========================================" -ForegroundColor Green
|
|
462
|
+
Write-Host " Scan Complete!" -ForegroundColor Green
|
|
463
|
+
Write-Host "========================================" -ForegroundColor Green
|
|
502
464
|
Write-Host ""
|
|
503
|
-
Write-Host "
|
|
465
|
+
Write-Host "Report: $OutputFile" -ForegroundColor White
|
|
504
466
|
Write-Host ""
|
|
505
|
-
Write-Host "
|
|
506
|
-
Write-Host "
|
|
507
|
-
Write-Host "
|
|
467
|
+
Write-Host "Quick Links:" -ForegroundColor Cyan
|
|
468
|
+
Write-Host " Headers: https://securityheaders.com/?q=$Domain"
|
|
469
|
+
Write-Host " SSL: https://ssllabs.com/ssltest/analyze.html?d=$Domain"
|
|
508
470
|
Write-Host ""
|