@soulofzephir/pi-skill-pentesting 1.0.0
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/LICENSE +21 -0
- package/PUBLISH.md +97 -0
- package/README.md +255 -0
- package/package.json +39 -0
- package/skills/pentesting/SKILL.md +399 -0
- package/skills/pentesting/checklists/headers.md +286 -0
- package/skills/pentesting/checklists/injection.md +456 -0
- package/skills/pentesting/checklists/owasp.md +291 -0
- package/skills/pentesting/checklists/ports.md +323 -0
- package/skills/pentesting/reports/template.md +268 -0
- package/skills/pentesting/tools/generate-report.ps1 +327 -0
- package/skills/pentesting/tools/header-scan.ps1 +202 -0
- package/skills/pentesting/tools/header-scan.sh +173 -0
- package/skills/pentesting/tools/security-scan.ps1 +338 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# Security Quick Scanner v1.0
|
|
2
|
+
# Combined scanner for Headers + Ports + Basic Injection Tests
|
|
3
|
+
|
|
4
|
+
param(
|
|
5
|
+
[Parameter(Mandatory=$false)]
|
|
6
|
+
[string]$Target = "",
|
|
7
|
+
|
|
8
|
+
[Parameter(Mandatory=$false)]
|
|
9
|
+
[switch]$HeadersOnly,
|
|
10
|
+
|
|
11
|
+
[Parameter(Mandatory=$false)]
|
|
12
|
+
[switch]$PortsOnly,
|
|
13
|
+
|
|
14
|
+
[Parameter(Mandatory=$false)]
|
|
15
|
+
[switch]$InjectionOnly
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
$ErrorActionPreference = "SilentlyContinue"
|
|
19
|
+
|
|
20
|
+
# Color codes
|
|
21
|
+
function Get-Color { param($Score)
|
|
22
|
+
if ($Score -ge 80) { return "Green" }
|
|
23
|
+
if ($Score -ge 60) { return "Yellow" }
|
|
24
|
+
return "Red"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# Banner
|
|
28
|
+
Write-Host ""
|
|
29
|
+
Write-Host "╔═══════════════════════════════════════════════════╗" -ForegroundColor Cyan
|
|
30
|
+
Write-Host "║ 🔒 Security Quick Scanner v1.0 ║" -ForegroundColor Cyan
|
|
31
|
+
Write-Host "╚═══════════════════════════════════════════════════╝" -ForegroundColor Cyan
|
|
32
|
+
Write-Host ""
|
|
33
|
+
|
|
34
|
+
# Validate target
|
|
35
|
+
if (-not $Target) {
|
|
36
|
+
Write-Host "Usage: .\security-scan.ps1 -Target https://target.com" -ForegroundColor Yellow
|
|
37
|
+
Write-Host ""
|
|
38
|
+
Write-Host "Options:" -ForegroundColor White
|
|
39
|
+
Write-Host " -Target Target URL or hostname"
|
|
40
|
+
Write-Host " -HeadersOnly Scan headers only"
|
|
41
|
+
Write-Host " -PortsOnly Scan ports only"
|
|
42
|
+
Write-Host " -InjectionOnly Test injection only"
|
|
43
|
+
exit
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# Parse target
|
|
47
|
+
if ($Target -match "https?://") {
|
|
48
|
+
$Uri = [System.Uri]$Target
|
|
49
|
+
$Hostname = $Uri.Host
|
|
50
|
+
} else {
|
|
51
|
+
$Hostname = $Target
|
|
52
|
+
$Target = "https://$Target"
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
Write-Host "Target: $Hostname" -ForegroundColor White
|
|
56
|
+
Write-Host "Mode: $(if($HeadersOnly){'Headers'}elseif($PortsOnly){'Ports'}elseif($InjectionOnly){'Injection'}else{'All'})"
|
|
57
|
+
Write-Host ""
|
|
58
|
+
|
|
59
|
+
# ═══════════════════════════════════════════════════════════
|
|
60
|
+
# HEADER SCANNER
|
|
61
|
+
# ═══════════════════════════════════════════════════════════
|
|
62
|
+
if (-not $PortsOnly -and -not $InjectionOnly) {
|
|
63
|
+
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
64
|
+
Write-Host "🔒 SECURITY HEADERS ANALYSIS" -ForegroundColor Cyan
|
|
65
|
+
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
66
|
+
|
|
67
|
+
$HeaderScore = 0
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
$Response = Invoke-WebRequest -Uri $Target -Method Head -TimeoutSec 10 -ErrorAction Stop
|
|
71
|
+
$Headers = $Response.Headers
|
|
72
|
+
} catch {
|
|
73
|
+
Write-Host "⚠️ Could not fetch headers (trying HTTP instead)..." -ForegroundColor Yellow
|
|
74
|
+
try {
|
|
75
|
+
$Target = $Target -replace "^https", "http"
|
|
76
|
+
$Response = Invoke-WebRequest -Uri $Target -Method Head -TimeoutSec 10 -ErrorAction Stop
|
|
77
|
+
$Headers = $Response.Headers
|
|
78
|
+
} catch {
|
|
79
|
+
Write-Host "❌ Cannot connect to target" -ForegroundColor Red
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if ($Headers) {
|
|
84
|
+
# HSTS Check
|
|
85
|
+
$HSTS = $Headers["Strict-Transport-Security"]
|
|
86
|
+
if ($HSTS) {
|
|
87
|
+
if ($HSTS -match "max-age=([3-9]\d{5,}|\d{7,})") {
|
|
88
|
+
Write-Host "✅ HSTS: Good (max-age >= 1 year)" -ForegroundColor Green
|
|
89
|
+
$HeaderScore += 15
|
|
90
|
+
} else {
|
|
91
|
+
Write-Host "⚠️ HSTS: Present but max-age < 1 year" -ForegroundColor Yellow
|
|
92
|
+
$HeaderScore += 8
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
Write-Host "❌ HSTS: Missing" -ForegroundColor Red
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# CSP Check
|
|
99
|
+
$CSP = $Headers["Content-Security-Policy"]
|
|
100
|
+
if ($CSP) {
|
|
101
|
+
Write-Host "✅ CSP: Present" -ForegroundColor Green
|
|
102
|
+
$HeaderScore += 20
|
|
103
|
+
if ($CSP -match "unsafe-inline") {
|
|
104
|
+
Write-Host " ⚠️ Contains 'unsafe-inline' (XSS risk)" -ForegroundColor Red
|
|
105
|
+
}
|
|
106
|
+
if ($CSP -match "unsafe-eval") {
|
|
107
|
+
Write-Host " ⚠️ Contains 'unsafe-eval'" -ForegroundColor Red
|
|
108
|
+
}
|
|
109
|
+
if ($CSP -match "frame-ancestors") {
|
|
110
|
+
Write-Host " ✅ frame-ancestors directive present" -ForegroundColor Green
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
Write-Host "❌ CSP: Missing (XSS/clickjacking risk)" -ForegroundColor Red
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
# X-Content-Type-Options
|
|
117
|
+
$XCTO = $Headers["X-Content-Type-Options"]
|
|
118
|
+
if ($XCTO -eq "nosniff") {
|
|
119
|
+
Write-Host "✅ X-Content-Type-Options: nosniff" -ForegroundColor Green
|
|
120
|
+
$HeaderScore += 10
|
|
121
|
+
} else {
|
|
122
|
+
Write-Host "❌ X-Content-Type-Options: Missing or wrong" -ForegroundColor Red
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# X-Frame-Options
|
|
126
|
+
$XFO = $Headers["X-Frame-Options"]
|
|
127
|
+
if ($XFO) {
|
|
128
|
+
if ($XFO -eq "DENY") {
|
|
129
|
+
Write-Host "✅ X-Frame-Options: DENY" -ForegroundColor Green
|
|
130
|
+
$HeaderScore += 10
|
|
131
|
+
} elseif ($XFO -eq "SAMEORIGIN") {
|
|
132
|
+
Write-Host "✅ X-Frame-Options: SAMEORIGIN" -ForegroundColor Green
|
|
133
|
+
$HeaderScore += 8
|
|
134
|
+
} else {
|
|
135
|
+
Write-Host "⚠️ X-Frame-Options: $XFO" -ForegroundColor Yellow
|
|
136
|
+
$HeaderScore += 5
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
Write-Host "❌ X-Frame-Options: Missing" -ForegroundColor Red
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
# Referrer-Policy
|
|
143
|
+
$RP = $Headers["Referrer-Policy"]
|
|
144
|
+
if ($RP) {
|
|
145
|
+
Write-Host "✅ Referrer-Policy: $RP" -ForegroundColor Green
|
|
146
|
+
$HeaderScore += 10
|
|
147
|
+
} else {
|
|
148
|
+
Write-Host "⚠️ Referrer-Policy: Missing" -ForegroundColor Yellow
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
# Cache-Control
|
|
152
|
+
$CC = $Headers["Cache-Control"]
|
|
153
|
+
if ($CC -match "no-store|no-cache") {
|
|
154
|
+
Write-Host "✅ Cache-Control: Secure" -ForegroundColor Green
|
|
155
|
+
$HeaderScore += 10
|
|
156
|
+
} elseif ($CC) {
|
|
157
|
+
Write-Host "⚠️ Cache-Control: $CC" -ForegroundColor Yellow
|
|
158
|
+
$HeaderScore += 5
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
# Server info leakage
|
|
162
|
+
$Server = $Headers["Server"]
|
|
163
|
+
if ($Server -match "/\d" -or $Server -match "Advanced") {
|
|
164
|
+
Write-Host "❌ Server: Leaks version - $Server" -ForegroundColor Red
|
|
165
|
+
} elseif ($Server) {
|
|
166
|
+
Write-Host "⚠️ Server: $Server" -ForegroundColor Yellow
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
# X-Powered-By
|
|
170
|
+
$XPB = $Headers["X-Powered-By"]
|
|
171
|
+
if ($XPB) {
|
|
172
|
+
Write-Host "❌ X-Powered-By: $XPB" -ForegroundColor Red
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
# Permissions-Policy
|
|
176
|
+
$PP = $Headers["Permissions-Policy"]
|
|
177
|
+
if ($PP) {
|
|
178
|
+
Write-Host "✅ Permissions-Policy: Present" -ForegroundColor Green
|
|
179
|
+
$HeaderScore += 10
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
Write-Host ""
|
|
184
|
+
Write-Host "📊 Header Score: $HeaderScore/100" -ForegroundColor $(Get-Color $HeaderScore)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
# ═══════════════════════════════════════════════════════════
|
|
188
|
+
# PORT SCANNER
|
|
189
|
+
# ═══════════════════════════════════════════════════════════
|
|
190
|
+
if (-not $HeadersOnly -and -not $InjectionOnly) {
|
|
191
|
+
Write-Host ""
|
|
192
|
+
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
193
|
+
Write-Host "🔌 PORT SCAN" -ForegroundColor Cyan
|
|
194
|
+
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
195
|
+
|
|
196
|
+
# Check if nmap available
|
|
197
|
+
$NmapAvailable = Get-Command nmap -ErrorAction SilentlyContinue
|
|
198
|
+
|
|
199
|
+
if ($NmapAvailable) {
|
|
200
|
+
Write-Host "Using Nmap for port scan..." -ForegroundColor Gray
|
|
201
|
+
nmap -sV -p 21,22,23,25,53,80,110,135,139,143,443,445,993,995,3306,3389,5432,5900,6379,8080,8443,27017 $Hostname 2>&1 | Where-Object { $_ -match "^\d|open|closed|filtered" }
|
|
202
|
+
} else {
|
|
203
|
+
Write-Host "Nmap not found. Checking common ports with TCP..." -ForegroundColor Yellow
|
|
204
|
+
|
|
205
|
+
$Ports = @(21,22,80,443,3306,5432,8080,3389)
|
|
206
|
+
$OpenPorts = @()
|
|
207
|
+
|
|
208
|
+
foreach ($Port in $Ports) {
|
|
209
|
+
try {
|
|
210
|
+
$TCP = New-Object System.Net.Sockets.TcpClient
|
|
211
|
+
$Result = $TCP.BeginConnect($Hostname, $Port, $null, $null)
|
|
212
|
+
$Wait = $Result.AsyncWaitHandle.WaitOne(500)
|
|
213
|
+
|
|
214
|
+
if ($Wait -and $TCP.Connected) {
|
|
215
|
+
$OpenPorts += $Port
|
|
216
|
+
$Service = switch ($Port) {
|
|
217
|
+
21 {"FTP"}
|
|
218
|
+
22 {"SSH"}
|
|
219
|
+
80 {"HTTP"}
|
|
220
|
+
443 {"HTTPS"}
|
|
221
|
+
3306 {"MySQL"}
|
|
222
|
+
3389 {"RDP"}
|
|
223
|
+
5432 {"PostgreSQL"}
|
|
224
|
+
8080 {"HTTP-Alt"}
|
|
225
|
+
}
|
|
226
|
+
Write-Host "⚠️ Port $Port ($Service) - OPEN" -ForegroundColor Yellow
|
|
227
|
+
}
|
|
228
|
+
$TCP.Close()
|
|
229
|
+
} catch {}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if ($OpenPorts.Count -eq 0) {
|
|
233
|
+
Write-Host "✅ No common high-risk ports detected" -ForegroundColor Green
|
|
234
|
+
} else {
|
|
235
|
+
Write-Host ""
|
|
236
|
+
Write-Host "📊 High-Risk Open Ports: $($OpenPorts.Count)" -ForegroundColor Yellow
|
|
237
|
+
Write-Host " Review: Port 3306/5432/6379 should not be public!" -ForegroundColor Red
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
# ═══════════════════════════════════════════════════════════
|
|
243
|
+
# INJECTION TESTER
|
|
244
|
+
# ═══════════════════════════════════════════════════════════
|
|
245
|
+
if (-not $HeadersOnly -and -not $PortsOnly) {
|
|
246
|
+
Write-Host ""
|
|
247
|
+
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
248
|
+
Write-Host "💉 BASIC INJECTION TESTS" -ForegroundColor Cyan
|
|
249
|
+
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
250
|
+
|
|
251
|
+
# XSS Test
|
|
252
|
+
Write-Host ""
|
|
253
|
+
Write-Host "🧪 XSS Test:" -ForegroundColor White
|
|
254
|
+
$XSSPayload = "<script>alert(1)</script>"
|
|
255
|
+
$TestURL = "$Target/search?q=$XSSPayload"
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
$Response = Invoke-WebRequest -Uri $TestURL -TimeoutSec 10 -ErrorAction SilentlyContinue
|
|
259
|
+
$Content = $Response.Content
|
|
260
|
+
|
|
261
|
+
if ($Content -match [regex]::Escape($XSSPayload)) {
|
|
262
|
+
Write-Host "⚠️ REFLECTED XSS - Payload found in response" -ForegroundColor Red
|
|
263
|
+
Write-Host " Payload: $XSSPayload" -ForegroundColor Gray
|
|
264
|
+
} else {
|
|
265
|
+
Write-Host "✅ No obvious XSS reflection detected" -ForegroundColor Green
|
|
266
|
+
}
|
|
267
|
+
} catch {
|
|
268
|
+
Write-Host "⚠️ Could not complete XSS test" -ForegroundColor Yellow
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
# SQLi Test
|
|
272
|
+
Write-Host ""
|
|
273
|
+
Write-Host "🧪 SQLi Test:" -ForegroundColor White
|
|
274
|
+
$SQLPayload = "' OR '1'='1"
|
|
275
|
+
$TestURL = "$Target/?id=$SQLPayload"
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
$Response = Invoke-WebRequest -Uri $TestURL -TimeoutSec 10 -ErrorAction SilentlyContinue
|
|
279
|
+
$Content = $Response.Content
|
|
280
|
+
$Headers = $Response.Headers
|
|
281
|
+
|
|
282
|
+
# Check for SQL errors
|
|
283
|
+
$SQLErrors = @("SQL syntax", "MySQL", "PostgreSQL", "sqlite", "Microsoft SQL", "ODBC", "Warning: mysql", "error in your SQL")
|
|
284
|
+
$FoundError = $SQLErrors | Where-Object { $Content -match $_ }
|
|
285
|
+
|
|
286
|
+
if ($FoundError) {
|
|
287
|
+
Write-Host "⚠️ SQL ERROR DETECTED in response" -ForegroundColor Red
|
|
288
|
+
Write-Host " Error hint: $($FoundError[0])" -ForegroundColor Gray
|
|
289
|
+
} else {
|
|
290
|
+
Write-Host "✅ No obvious SQL errors in response" -ForegroundColor Green
|
|
291
|
+
}
|
|
292
|
+
} catch {
|
|
293
|
+
Write-Host "⚠️ Could not complete SQLi test" -ForegroundColor Yellow
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
# Command Injection Test
|
|
297
|
+
Write-Host ""
|
|
298
|
+
Write-Host "🧪 Command Injection Test:" -ForegroundColor White
|
|
299
|
+
$CmdPayload = ";ls"
|
|
300
|
+
$TestURL = "$Target/?cmd=$CmdPayload"
|
|
301
|
+
|
|
302
|
+
try {
|
|
303
|
+
$Response = Invoke-WebRequest -Uri $TestURL -TimeoutSec 10 -ErrorAction SilentlyContinue
|
|
304
|
+
$Content = $Response.Content
|
|
305
|
+
|
|
306
|
+
# Check for common command output patterns
|
|
307
|
+
if ($Content -match "total \d+|drwx|root:|bin|etc|passwd" -and $Content -match "root|daemon|bin") {
|
|
308
|
+
Write-Host "⚠️ Possible command injection - system output detected" -ForegroundColor Red
|
|
309
|
+
} else {
|
|
310
|
+
Write-Host "✅ No obvious command injection detected" -ForegroundColor Green
|
|
311
|
+
}
|
|
312
|
+
} catch {
|
|
313
|
+
Write-Host "✅ No obvious command injection detected" -ForegroundColor Green
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
Write-Host ""
|
|
317
|
+
Write-Host "⚠️ Note: Automated injection tests are basic. Manual testing recommended." -ForegroundColor Yellow
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
# ═══════════════════════════════════════════════════════════
|
|
321
|
+
# SUMMARY
|
|
322
|
+
# ═══════════════════════════════════════════════════════════
|
|
323
|
+
if (-not $HeadersOnly -and -not $PortsOnly -and -not $InjectionOnly) {
|
|
324
|
+
Write-Host ""
|
|
325
|
+
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
326
|
+
Write-Host "📋 SCAN COMPLETE" -ForegroundColor Cyan
|
|
327
|
+
Write-Host "═══════════════════════════════════════════════════" -ForegroundColor Cyan
|
|
328
|
+
|
|
329
|
+
Write-Host ""
|
|
330
|
+
Write-Host "🔗 Online Tools for Deeper Analysis:" -ForegroundColor White
|
|
331
|
+
Write-Host " Headers: https://securityheaders.com/?q=$Hostname"
|
|
332
|
+
Write-Host " SSL/TLS: https://ssllabs.com/ssltest/analyze.html?d=$Hostname"
|
|
333
|
+
Write-Host " DNS: https://dnsdumpster.com/?domain=$Hostname"
|
|
334
|
+
Write-Host ""
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
Write-Host "Scan completed at: $(Get-Date)" -ForegroundColor Gray
|
|
338
|
+
Write-Host ""
|