@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,202 @@
|
|
|
1
|
+
# Security Header Scanner (PowerShell Version)
|
|
2
|
+
# Usage: .\header-scan.ps1 https://target.com
|
|
3
|
+
|
|
4
|
+
param(
|
|
5
|
+
[Parameter(Mandatory=$false)]
|
|
6
|
+
[string]$Target = "https://example.com"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
$ErrorActionPreference = "SilentlyContinue"
|
|
10
|
+
$Score = 0
|
|
11
|
+
$MaxScore = 100
|
|
12
|
+
|
|
13
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
14
|
+
Write-Host "🔒 Security Header Scanner" -ForegroundColor Cyan
|
|
15
|
+
Write-Host "Target: $Target" -ForegroundColor Cyan
|
|
16
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
17
|
+
Write-Host ""
|
|
18
|
+
|
|
19
|
+
# Get headers
|
|
20
|
+
try {
|
|
21
|
+
$Headers = Invoke-WebRequest -Uri $Target -Method Head -UserAgent "SecurityScanner/1.0" -MaximumFollowRelLink 5 -ErrorAction Stop
|
|
22
|
+
$AllHeaders = $Headers.Headers
|
|
23
|
+
} catch {
|
|
24
|
+
Write-Host "❌ Error connecting to target: $_" -ForegroundColor Red
|
|
25
|
+
exit 1
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Write-Host "📋 Response Headers:" -ForegroundColor Yellow
|
|
29
|
+
$AllHeaders | Format-Table -AutoSize
|
|
30
|
+
Write-Host ""
|
|
31
|
+
|
|
32
|
+
# Helper function
|
|
33
|
+
function Test-Header {
|
|
34
|
+
param($Name, $Pattern)
|
|
35
|
+
return $AllHeaders.Keys | Where-Object { $_ -match $Pattern }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# Check HSTS
|
|
39
|
+
$hsts = $AllHeaders.Keys | Where-Object { $_ -like "*strict-transport*" }
|
|
40
|
+
if ($hsts) {
|
|
41
|
+
$hstsValue = $AllHeaders[$hsts]
|
|
42
|
+
if ($hstsValue -match "max-age=([3-9]\d{5,}|\d{7,})") {
|
|
43
|
+
Write-Host "✅ HSTS: Good (max-age >= 1 year)" -ForegroundColor Green
|
|
44
|
+
$Score += 15
|
|
45
|
+
} elseif ($hstsValue -match "max-age=(\d{5,6})") {
|
|
46
|
+
Write-Host "⚠️ HSTS: Medium (max-age too short)" -ForegroundColor Yellow
|
|
47
|
+
$Score += 8
|
|
48
|
+
} else {
|
|
49
|
+
Write-Host "⚠️ HSTS: Present but check max-age value" -ForegroundColor Yellow
|
|
50
|
+
$Score += 5
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
Write-Host "❌ HSTS: Missing" -ForegroundColor Red
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Check CSP
|
|
57
|
+
$cspKeys = $AllHeaders.Keys | Where-Object { $_ -like "*content-security*" }
|
|
58
|
+
if ($cspKeys) {
|
|
59
|
+
Write-Host "✅ CSP: Present" -ForegroundColor Green
|
|
60
|
+
foreach ($key in $cspKeys) {
|
|
61
|
+
$cspValue = $AllHeaders[$key]
|
|
62
|
+
if ($cspValue -match "'unsafe-inline'") {
|
|
63
|
+
Write-Host " ⚠️ CSP contains 'unsafe-inline' (XSS risk)" -ForegroundColor Red
|
|
64
|
+
}
|
|
65
|
+
if ($cspValue -match "'unsafe-eval'") {
|
|
66
|
+
Write-Host " ⚠️ CSP contains 'unsafe-eval'" -ForegroundColor Red
|
|
67
|
+
}
|
|
68
|
+
if ($cspValue -match "frame-ancestors") {
|
|
69
|
+
Write-Host " ✅ frame-ancestors directive present" -ForegroundColor Green
|
|
70
|
+
}
|
|
71
|
+
if ($cspValue -notmatch "'unsafe-" -and $cspValue -notmatch "\*") {
|
|
72
|
+
Write-Host " ✅ No dangerous CSP directives" -ForegroundColor Green
|
|
73
|
+
$Score += 20
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
Write-Host "❌ CSP: Missing (XSS/clickjacking risk)" -ForegroundColor Red
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# Check X-Content-Type-Options
|
|
81
|
+
$xctoKeys = $AllHeaders.Keys | Where-Object { $_ -like "*x-content-type*" }
|
|
82
|
+
if ($xctoKeys) {
|
|
83
|
+
$xctoValue = $AllHeaders[$xctoKeys[0]]
|
|
84
|
+
if ($xctoValue -eq "nosniff") {
|
|
85
|
+
Write-Host "✅ X-Content-Type-Options: nosniff" -ForegroundColor Green
|
|
86
|
+
$Score += 10
|
|
87
|
+
} else {
|
|
88
|
+
Write-Host "⚠️ X-Content-Type-Options: Wrong value ($xctoValue)" -ForegroundColor Yellow
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
Write-Host "❌ X-Content-Type-Options: Missing" -ForegroundColor Red
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# Check X-Frame-Options
|
|
95
|
+
$xfoKeys = $AllHeaders.Keys | Where-Object { $_ -like "*x-frame*" }
|
|
96
|
+
if ($xfoKeys) {
|
|
97
|
+
$xfoValue = $AllHeaders[$xfoKeys[0]]
|
|
98
|
+
if ($xfoValue -eq "DENY") {
|
|
99
|
+
Write-Host "✅ X-Frame-Options: DENY" -ForegroundColor Green
|
|
100
|
+
$Score += 10
|
|
101
|
+
} elseif ($xfoValue -eq "SAMEORIGIN") {
|
|
102
|
+
Write-Host "✅ X-Frame-Options: SAMEORIGIN" -ForegroundColor Green
|
|
103
|
+
$Score += 8
|
|
104
|
+
} elseif ($xfoValue -eq "ALLOWALL") {
|
|
105
|
+
Write-Host "❌ X-Frame-Options: ALLOWALL (Dangerous!)" -ForegroundColor Red
|
|
106
|
+
} else {
|
|
107
|
+
Write-Host "⚠️ X-Frame-Options: $xfoValue" -ForegroundColor Yellow
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
Write-Host "❌ X-Frame-Options: Missing (Clickjacking risk)" -ForegroundColor Red
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# Check Referrer-Policy
|
|
114
|
+
$rpKeys = $AllHeaders.Keys | Where-Object { $_ -like "*referrer*" }
|
|
115
|
+
if ($rpKeys) {
|
|
116
|
+
Write-Host "✅ Referrer-Policy: Present" -ForegroundColor Green
|
|
117
|
+
$rpValue = $AllHeaders[$rpKeys[0]]
|
|
118
|
+
if ($rpValue -match "unsafe-url") {
|
|
119
|
+
Write-Host " ⚠️ Contains 'unsafe-url' (leaks referrer)" -ForegroundColor Red
|
|
120
|
+
}
|
|
121
|
+
$Score += 10
|
|
122
|
+
} else {
|
|
123
|
+
Write-Host "⚠️ Referrer-Policy: Missing" -ForegroundColor Yellow
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# Check Permissions-Policy
|
|
127
|
+
$ppKeys = $AllHeaders.Keys | Where-Object { $_ -like "*permissions*" }
|
|
128
|
+
if ($ppKeys) {
|
|
129
|
+
Write-Host "✅ Permissions-Policy: Present" -ForegroundColor Green
|
|
130
|
+
$Score += 10
|
|
131
|
+
} else {
|
|
132
|
+
Write-Host "⚠️ Permissions-Policy: Missing (recommended)" -ForegroundColor Yellow
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
# Check Cache-Control
|
|
136
|
+
Write-Host ""
|
|
137
|
+
Write-Host "🔍 Testing Cache-Control..." -ForegroundColor Yellow
|
|
138
|
+
$ccKeys = $AllHeaders.Keys | Where-Object { $_ -like "*cache*" }
|
|
139
|
+
if ($ccKeys) {
|
|
140
|
+
$ccValue = $AllHeaders[$ccKeys[0]]
|
|
141
|
+
if ($ccValue -match "no-store|no-cache") {
|
|
142
|
+
Write-Host "✅ Cache-Control: Secure" -ForegroundColor Green
|
|
143
|
+
$Score += 10
|
|
144
|
+
} elseif ($ccValue -match "private") {
|
|
145
|
+
Write-Host "⚠️ Cache-Control: private (not optimal)" -ForegroundColor Yellow
|
|
146
|
+
$Score += 5
|
|
147
|
+
} else {
|
|
148
|
+
Write-Host "⚠️ Cache-Control: Check if sensitive data cached" -ForegroundColor Yellow
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
Write-Host "⚠️ Cache-Control: Not found" -ForegroundColor Yellow
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
# Check Server header
|
|
155
|
+
$serverKeys = $AllHeaders.Keys | Where-Object { $_ -like "server" }
|
|
156
|
+
if ($serverKeys) {
|
|
157
|
+
$serverValue = $AllHeaders[$serverKeys[0]]
|
|
158
|
+
if ($serverValue -match "Apache/\d|nginx/\d|IIS/\d|Apache-Advanced|Server version") {
|
|
159
|
+
Write-Host "❌ Server header leaks version: $serverValue" -ForegroundColor Red
|
|
160
|
+
Write-Host " Recommendation: Hide version info" -ForegroundColor Gray
|
|
161
|
+
} elseif ($serverValue -match "Apache|nginx|IIS") {
|
|
162
|
+
Write-Host "⚠️ Server header: $serverValue" -ForegroundColor Yellow
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
# Check X-Powered-By
|
|
167
|
+
$pwKeys = $AllHeaders.Keys | Where-Object { $_ -like "*x-powered-by*" }
|
|
168
|
+
if ($pwKeys) {
|
|
169
|
+
$pwValue = $AllHeaders[$pwKeys[0]]
|
|
170
|
+
Write-Host "❌ X-Powered-By leaks info: $pwValue" -ForegroundColor Red
|
|
171
|
+
Write-Host " Recommendation: Remove this header" -ForegroundColor Gray
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
# Check debug headers
|
|
175
|
+
$debugKeys = $AllHeaders.Keys | Where-Object { $_ -match "debug|x-source-map|sourcemap" }
|
|
176
|
+
if ($debugKeys) {
|
|
177
|
+
Write-Host "❌ Debug/Sourcemap headers present" -ForegroundColor Red
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
# Calculate grade
|
|
181
|
+
Write-Host ""
|
|
182
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
183
|
+
Write-Host "📊 Security Header Score: $Score/100" -ForegroundColor Cyan
|
|
184
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
185
|
+
|
|
186
|
+
if ($Score -ge 90) {
|
|
187
|
+
Write-Host "Grade: A (Excellent)" -ForegroundColor Green
|
|
188
|
+
} elseif ($Score -ge 70) {
|
|
189
|
+
Write-Host "Grade: B (Good)" -ForegroundColor Green
|
|
190
|
+
} elseif ($Score -ge 50) {
|
|
191
|
+
Write-Host "Grade: C (Needs Improvement)" -ForegroundColor Yellow
|
|
192
|
+
} elseif ($Score -ge 30) {
|
|
193
|
+
Write-Host "Grade: D (Poor)" -ForegroundColor Red
|
|
194
|
+
} else {
|
|
195
|
+
Write-Host "Grade: F (Critical Issues)" -ForegroundColor Red
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
Write-Host ""
|
|
199
|
+
Write-Host "🔗 Online Scanners:" -ForegroundColor Cyan
|
|
200
|
+
Write-Host " https://securityheaders.com/?q=$Target"
|
|
201
|
+
Write-Host " https://observatory.mozilla.org/analyze/$Target"
|
|
202
|
+
Write-Host ""
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Security Header Scanner v1.0
|
|
3
|
+
# Usage: ./header-scan.sh https://target.com
|
|
4
|
+
|
|
5
|
+
TARGET=${1:-https://example.com}
|
|
6
|
+
SCORE=0
|
|
7
|
+
MAX_SCORE=100
|
|
8
|
+
|
|
9
|
+
echo "========================================"
|
|
10
|
+
echo "🔒 Security Header Scanner"
|
|
11
|
+
echo "Target: $TARGET"
|
|
12
|
+
echo "========================================"
|
|
13
|
+
echo ""
|
|
14
|
+
|
|
15
|
+
# Color codes
|
|
16
|
+
RED='\033[0;31m'
|
|
17
|
+
GREEN='\033[0;32m'
|
|
18
|
+
YELLOW='\033[1;33m'
|
|
19
|
+
NC='\033[0m' # No Color
|
|
20
|
+
|
|
21
|
+
# Get headers
|
|
22
|
+
HEADERS=$(curl -I -s -L -A "SecurityScanner/1.0" "$TARGET" 2>/dev/null)
|
|
23
|
+
|
|
24
|
+
echo "📋 Response Headers:"
|
|
25
|
+
echo "$HEADERS"
|
|
26
|
+
echo ""
|
|
27
|
+
|
|
28
|
+
# Check HSTS
|
|
29
|
+
if echo "$HEADERS" | grep -qi "strict-transport-security"; then
|
|
30
|
+
HSTS=$(echo "$HEADERS" | grep -i "strict-transport-security" | head -1)
|
|
31
|
+
if echo "$HSTS" | grep -qi "max-age=[3-9][0-9]{5,}"; then
|
|
32
|
+
echo -e "${GREEN}✅ HSTS: Good (max-age ≥ 1 year)${NC}"
|
|
33
|
+
SCORE=$((SCORE + 15))
|
|
34
|
+
elif echo "$HSTS" | grep -qi "max-age=[1-2][0-9]{5,}"; then
|
|
35
|
+
echo -e "${YELLOW}⚠️ HSTS: Medium (max-age too short)${NC}"
|
|
36
|
+
SCORE=$((SCORE + 8))
|
|
37
|
+
else
|
|
38
|
+
echo -e "${RED}❌ HSTS: Weak (max-age < 1 year)${NC}"
|
|
39
|
+
fi
|
|
40
|
+
else
|
|
41
|
+
echo -e "${RED}❌ HSTS: Missing${NC}"
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Check CSP
|
|
45
|
+
if echo "$HEADERS" | grep -qi "content-security-policy"; then
|
|
46
|
+
CSP=$(echo "$HEADERS" | grep -i "content-security-policy" | head -1)
|
|
47
|
+
echo -e "${GREEN}✅ CSP: Present${NC}"
|
|
48
|
+
|
|
49
|
+
if echo "$CSP" | grep -qi "'unsafe-inline'"; then
|
|
50
|
+
echo -e "${RED} ⚠️ CSP contains 'unsafe-inline' (XSS risk)${NC}"
|
|
51
|
+
elif echo "$CSP" | grep -qi "'unsafe-eval'"; then
|
|
52
|
+
echo -e "${RED} ⚠️ CSP contains 'unsafe-eval'${NC}"
|
|
53
|
+
else
|
|
54
|
+
echo -e "${GREEN} ✅ No dangerous directives found${NC}"
|
|
55
|
+
SCORE=$((SCORE + 20))
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
if echo "$CSP" | grep -qi "frame-ancestors"; then
|
|
59
|
+
echo -e "${GREEN} ✅ frame-ancestors directive present${NC}"
|
|
60
|
+
fi
|
|
61
|
+
else
|
|
62
|
+
echo -e "${RED}❌ CSP: Missing (XSS/clickjacking risk)${NC}"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# Check X-Content-Type-Options
|
|
66
|
+
if echo "$HEADERS" | grep -qi "x-content-type-options"; then
|
|
67
|
+
if echo "$HEADERS" | grep -i "x-content-type-options" | grep -qi "nosniff"; then
|
|
68
|
+
echo -e "${GREEN}✅ X-Content-Type-Options: nosniff${NC}"
|
|
69
|
+
SCORE=$((SCORE + 10))
|
|
70
|
+
else
|
|
71
|
+
echo -e "${YELLOW}⚠️ X-Content-Type-Options: Present but wrong value${NC}"
|
|
72
|
+
fi
|
|
73
|
+
else
|
|
74
|
+
echo -e "${RED}❌ X-Content-Type-Options: Missing${NC}"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Check X-Frame-Options
|
|
78
|
+
if echo "$HEADERS" | grep -qi "x-frame-options"; then
|
|
79
|
+
XFO=$(echo "$HEADERS" | grep -i "x-frame-options" | head -1)
|
|
80
|
+
if echo "$XFO" | grep -qi "deny"; then
|
|
81
|
+
echo -e "${GREEN}✅ X-Frame-Options: DENY${NC}"
|
|
82
|
+
SCORE=$((SCORE + 10))
|
|
83
|
+
elif echo "$XFO" | grep -qi "sameorigin"; then
|
|
84
|
+
echo -e "${GREEN}✅ X-Frame-Options: SAMEORIGIN${NC}"
|
|
85
|
+
SCORE=$((SCORE + 8))
|
|
86
|
+
elif echo "$XFO" | grep -qi "allowall"; then
|
|
87
|
+
echo -e "${RED}❌ X-Frame-Options: ALLOWALL (Dangerous!)${NC}"
|
|
88
|
+
fi
|
|
89
|
+
else
|
|
90
|
+
echo -e "${RED}❌ X-Frame-Options: Missing (Clickjacking risk)${NC}"
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Check Referrer-Policy
|
|
94
|
+
if echo "$HEADERS" | grep -qi "referrer-policy"; then
|
|
95
|
+
RP=$(echo "$HEADERS" | grep -i "referrer-policy" | head -1)
|
|
96
|
+
echo -e "${GREEN}✅ Referrer-Policy: Present${NC}"
|
|
97
|
+
SCORE=$((SCORE + 10))
|
|
98
|
+
|
|
99
|
+
if echo "$RP" | grep -qi "unsafe-url"; then
|
|
100
|
+
echo -e "${RED} ⚠️ Contains 'unsafe-url' (leaks referrer)${NC}"
|
|
101
|
+
fi
|
|
102
|
+
else
|
|
103
|
+
echo -e "${YELLOW}⚠️ Referrer-Policy: Missing${NC}"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# Check Permissions-Policy
|
|
107
|
+
if echo "$HEADERS" | grep -qi "permissions-policy"; then
|
|
108
|
+
echo -e "${GREEN}✅ Permissions-Policy: Present${NC}"
|
|
109
|
+
SCORE=$((SCORE + 10))
|
|
110
|
+
else
|
|
111
|
+
echo -e "${YELLOW}⚠️ Permissions-Policy: Missing (recommended)${NC}"
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# Check Cache-Control (test sensitive page)
|
|
115
|
+
echo ""
|
|
116
|
+
echo "🔍 Testing Cache-Control for sensitive data..."
|
|
117
|
+
CACHE_CHECK=$(curl -I -s "$TARGET" 2>/dev/null | grep -i "cache-control")
|
|
118
|
+
if echo "$CACHE_CHECK" | grep -qi "no-store\|no-cache"; then
|
|
119
|
+
echo -e "${GREEN}✅ Cache-Control: Secure${NC}"
|
|
120
|
+
SCORE=$((SCORE + 10))
|
|
121
|
+
elif echo "$CACHE_CHECK" | grep -qi "private"; then
|
|
122
|
+
echo -e "${YELLOW}⚠️ Cache-Control: private (not optimal for shared caches)${NC}"
|
|
123
|
+
SCORE=$((SCORE + 5))
|
|
124
|
+
else
|
|
125
|
+
echo -e "${YELLOW}⚠️ Cache-Control: Check if sensitive data is cached${NC}"
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
# Check Server header (info leakage)
|
|
129
|
+
if echo "$HEADERS" | grep -qi "^server:"; then
|
|
130
|
+
SERVER=$(echo "$HEADERS" | grep -i "^server:" | head -1)
|
|
131
|
+
if echo "$SERVER" | grep -qE "Apache/[0-9]|nginx/[0-9]|Microsoft-IIS/[0-9]"; then
|
|
132
|
+
echo -e "${RED}❌ Server header leaks version: $SERVER${NC}"
|
|
133
|
+
echo -e "${RED} Recommendation: Hide version info${NC}"
|
|
134
|
+
elif echo "$SERVER" | grep -qiE "apache|nginx|microsoft"; then
|
|
135
|
+
echo -e "${YELLOW}⚠️ Server header: $(echo $SERVER | xargs)${NC}"
|
|
136
|
+
echo -e "${YELLOW} Recommendation: Consider generic 'Server: webserver'${NC}"
|
|
137
|
+
fi
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
# Check X-Powered-By
|
|
141
|
+
if echo "$HEADERS" | grep -qi "x-powered-by"; then
|
|
142
|
+
POWERED=$(echo "$HEADERS" | grep -i "x-powered-by" | head -1)
|
|
143
|
+
echo -e "${RED}❌ X-Powered-By leaks info: $POWERED${NC}"
|
|
144
|
+
echo -e "${RED} Recommendation: Remove this header${NC}"
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
# Check for debug headers
|
|
148
|
+
if echo "$HEADERS" | grep -qi "x-debug\|x-source-map\|sourcemap"; then
|
|
149
|
+
echo -e "${RED}❌ Debug/Sourcemap headers present${NC}"
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
echo ""
|
|
153
|
+
echo "========================================"
|
|
154
|
+
echo "📊 Security Header Score: $SCORE/100"
|
|
155
|
+
echo "========================================"
|
|
156
|
+
|
|
157
|
+
if [ $SCORE -ge 90 ]; then
|
|
158
|
+
echo -e "${GREEN}Grade: A (Excellent)${NC}"
|
|
159
|
+
elif [ $SCORE -ge 70 ]; then
|
|
160
|
+
echo -e "${GREEN}Grade: B (Good)${NC}"
|
|
161
|
+
elif [ $SCORE -ge 50 ]; then
|
|
162
|
+
echo -e "${YELLOW}Grade: C (Needs Improvement)${NC}"
|
|
163
|
+
elif [ $SCORE -ge 30 ]; then
|
|
164
|
+
echo -e "${RED}Grade: D (Poor)${NC}"
|
|
165
|
+
else
|
|
166
|
+
echo -e "${RED}Grade: F (Critical Issues)${NC}"
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
echo ""
|
|
170
|
+
echo "🔗 Online Scanners:"
|
|
171
|
+
echo " - https://securityheaders.com/?q=$TARGET"
|
|
172
|
+
echo " - https://observatory.mozilla.org/analyze/$TARGET"
|
|
173
|
+
echo ""
|