forked from OlderMutt/HeaderGuardian-Burpsuite-Pro-Extension
-
Notifications
You must be signed in to change notification settings - Fork 0
/
HeaderGuardianPassive.py
193 lines (157 loc) · 8.07 KB
/
HeaderGuardianPassive.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
from burp import IBurpExtender, IScannerCheck, IScanIssue
from java.net import URL
class BurpExtender(IBurpExtender, IScannerCheck):
def registerExtenderCallbacks(self, callbacks):
self._callbacks = callbacks
self._helpers = callbacks.getHelpers()
callbacks.setExtensionName("Header Guardian")
callbacks.registerScannerCheck(self)
def doPassiveScan(self, baseRequestResponse):
issues = []
# Extract request and response details
analyzed_response = self._helpers.analyzeResponse(baseRequestResponse.getResponse())
headers = analyzed_response.getHeaders()
# Perform the checks on headers
missing_headers = self.checkMissingHeaders(headers)
misconfigured_headers = self.checkMisconfiguredHeaders(headers)
toremove_headers = self.checkToRemoveHeaders(headers)
correct_headers = self.checkCorrectHeaders(headers)
if missing_headers or misconfigured_headers or toremove_headers:
issues.append(self.createIssue(baseRequestResponse, missing_headers, misconfigured_headers, toremove_headers, correct_headers))
return issues if issues else None
def checkMissingHeaders(self, headers):
# Define expected headers
expected_headers = [
'Access-Control-Allow-Origin', 'X-Content-Type-Options', 'Permissions-Policy',
'Cross-Origin-Opener-Policy', 'X-Frame-Options', 'Referrer-Policy',
'Strict-Transport-Security', 'Content-Security-Policy', 'X-DNS-Prefetch-Control',
'Cross-Origin-Embedder-Policy', 'Cross-Origin-Resource-Policy', 'X-XSS-Protection'
]
missing_headers = []
for header in expected_headers:
if not any(h.startswith(header) for h in headers):
missing_headers.append(header)
return missing_headers
def checkMisconfiguredHeaders(self, headers):
# Define expected headers and their expected values
expected_values = {
"X-Frame-Options": "DENY",
"X-XSS-Protection": "0",
"X-Content-Type-Options": "nosniff",
"Content-Type": "charset=UTF-8",
"Referrer-Policy": "strict-origin-when-cross-origin",
"Strict-Transport-Security": "max-age=63072000; includeSubDomains; preload",
"Content-Security-Policy": "default-src 'self'",
"Access-Control-Allow-Origin": "https://yoursite.com",
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
"Cross-Origin-Resource-Policy": "same-site",
"Permissions-Policy": "geolocation=(), camera=(), microphone=()",
"X-DNS-Prefetch-Control": "off"
}
# Check for misconfigured headers
misconfigured_headers = []
for header in headers:
header_name = header.split(':')[0]
if header_name in expected_values:
current_value = header.split(':', 1)[1].strip() # Get the value after the header name
if current_value != expected_values[header_name]:
misconfigured_headers.append({
'name': header_name,
'current_value': current_value,
'expected_value': expected_values[header_name]
})
return misconfigured_headers
def checkCorrectHeaders(self, headers):
# Define expected headers and their expected values
expected_values = {
"X-Frame-Options": "DENY",
"X-XSS-Protection": "0",
"X-Content-Type-Options": "nosniff",
"Content-Type": "charset=UTF-8",
"Referrer-Policy": "strict-origin-when-cross-origin",
"Strict-Transport-Security": "max-age=63072000; includeSubDomains; preload",
"Content-Security-Policy": "default-src 'self'",
"Access-Control-Allow-Origin": "https://yoursite.com",
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
"Cross-Origin-Resource-Policy": "same-site",
"Permissions-Policy": "geolocation=(), camera=(), microphone=()",
"X-DNS-Prefetch-Control": "off"
}
correct_headers = []
for header in headers:
header_name = header.split(':')[0]
if header_name in expected_values:
current_value = header.split(':', 1)[1].strip()
if current_value == expected_values[header_name]:
correct_headers.append(header_name)
return correct_headers
def checkToRemoveHeaders(self, headers):
# Define removal headers
toremove_headers = []
for header in headers:
if header.startswith("Server:") or header.startswith("X-Powered-By") or \
header.startswith("X-AspNet-Version") or header.startswith("X-AspNetMvc-Version"):
toremove_headers.append(header)
return toremove_headers
def createIssue(self, baseRequestResponse, missing_headers, misconfigured_headers, toremove_headers, correct_headers):
# Create advisory message
details = "<b>Missing Headers:</b><br><br>"
details += "<br>".join(missing_headers) if missing_headers else "None<br>"
details += "<br><br><b>Misconfigured Headers:</b><br><br>"
if misconfigured_headers:
for header in misconfigured_headers:
details += "<b>Header:</b> {}<br>".format(header['name'])
details += "<b>Current Value:</b> {}<br>".format(header['current_value'])
details += "<b>Expected Value:</b> {}<br><br>".format(header['expected_value'])
else:
details += "None<br>"
details += "<br><b>Correct Headers:</b><br><br>"
details += "<br>".join(correct_headers) if correct_headers else "None<br>"
details += "<br><br><b>To Remove Headers:</b><br><br>"
details += "<br>".join(toremove_headers) if toremove_headers else "None<br>"
return CustomScanIssue(
baseRequestResponse.getHttpService(),
self._helpers.analyzeRequest(baseRequestResponse).getUrl(),
[self._callbacks.applyMarkers(baseRequestResponse, None, None)],
"Header Guardian - Check Headers Issues",
details,
"Information",
"Certain"
)
class CustomScanIssue(IScanIssue):
def __init__(self, httpService, url, httpMessages, name, detail, severity, confidence):
self._httpService = httpService
self._url = url
self._httpMessages = httpMessages
self._name = name
self._detail = detail
self._severity = severity
self._confidence = confidence
def getUrl(self):
return self._url
def getIssueName(self):
return self._name
def getIssueType(self):
return 0x08000000 # Custom issue type
def getSeverity(self):
return self._severity
def getConfidence(self):
return self._confidence
def getIssueBackground(self):
return "This issue stems from missing or improperly configured HTTP security headers, which play a crucial role in protecting web applications. These headers help mitigate a wide range of security vulnerabilities, including cross-site scripting (XSS), clickjacking, and information leakage, making their proper implementation essential for safeguarding user data and maintaining application integrity."
def getRemediationBackground(self):
return (
"Ensure all security-related HTTP headers are configured correctly according to OWASP best practices. "
"For more details, refer to the <a href='https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html'>"
"OWASP HTTP Headers Cheat Sheet</a>."
)
def getIssueDetail(self):
return self._detail
def getRemediationDetail(self):
return None
def getHttpMessages(self):
return self._httpMessages
def getHttpService(self):
return self._httpService