@intentsolutionsio/penetration-tester 2.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.
@@ -0,0 +1,365 @@
1
+ # Security Headers Reference
2
+
3
+ Comprehensive guide to HTTP security headers, what they protect against,
4
+ recommended values, and implementation across common frameworks.
5
+
6
+ ---
7
+
8
+ ## Content-Security-Policy (CSP)
9
+
10
+ **Purpose:** Prevents XSS, clickjacking, and code injection by controlling which
11
+ resources the browser is allowed to load.
12
+
13
+ **Recommended value:**
14
+ ```
15
+ Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'
16
+ ```
17
+
18
+ **What security_scanner.py checks:**
19
+ - Header is present
20
+ - `default-src` directive exists
21
+ - No `unsafe-eval` in `script-src`
22
+ - No wildcard `*` in `default-src` or `script-src`
23
+
24
+ **Implementation:**
25
+
26
+ Express.js:
27
+ ```javascript
28
+ const helmet = require("helmet");
29
+ app.use(helmet.contentSecurityPolicy({
30
+ directives: {
31
+ defaultSrc: ["'self'"],
32
+ scriptSrc: ["'self'"],
33
+ styleSrc: ["'self'", "'unsafe-inline'"],
34
+ imgSrc: ["'self'", "data:", "https:"],
35
+ frameAncestors: ["'none'"],
36
+ }
37
+ }));
38
+ ```
39
+
40
+ Django:
41
+ ```python
42
+ # settings.py
43
+ CSP_DEFAULT_SRC = ("'self'",)
44
+ CSP_SCRIPT_SRC = ("'self'",)
45
+ CSP_STYLE_SRC = ("'self'", "'unsafe-inline'")
46
+ CSP_IMG_SRC = ("'self'", "data:", "https:")
47
+ CSP_FRAME_ANCESTORS = ("'none'",)
48
+ ```
49
+
50
+ Nginx:
51
+ ```nginx
52
+ add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'none';" always;
53
+ ```
54
+
55
+ Apache:
56
+ ```apache
57
+ Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'none';"
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Strict-Transport-Security (HSTS)
63
+
64
+ **Purpose:** Forces browsers to use HTTPS for all future requests to the domain,
65
+ preventing protocol downgrade attacks and cookie hijacking.
66
+
67
+ **Recommended value:**
68
+ ```
69
+ Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
70
+ ```
71
+
72
+ **What security_scanner.py checks:**
73
+ - Header is present (critical if site supports HTTPS)
74
+ - `max-age` >= 31536000 (1 year)
75
+ - `includeSubDomains` directive present
76
+ - Notes `preload` status
77
+
78
+ **Implementation:**
79
+
80
+ Express.js:
81
+ ```javascript
82
+ app.use(helmet.hsts({
83
+ maxAge: 31536000,
84
+ includeSubDomains: true,
85
+ preload: true
86
+ }));
87
+ ```
88
+
89
+ Django:
90
+ ```python
91
+ # settings.py
92
+ SECURE_HSTS_SECONDS = 31536000
93
+ SECURE_HSTS_INCLUDE_SUBDOMAINS = True
94
+ SECURE_HSTS_PRELOAD = True
95
+ ```
96
+
97
+ Nginx:
98
+ ```nginx
99
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
100
+ ```
101
+
102
+ Apache:
103
+ ```apache
104
+ Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
105
+ ```
106
+
107
+ ---
108
+
109
+ ## X-Frame-Options
110
+
111
+ **Purpose:** Prevents clickjacking by controlling whether the page can be rendered
112
+ in a frame, iframe, embed, or object.
113
+
114
+ **Recommended value:**
115
+ ```
116
+ X-Frame-Options: DENY
117
+ ```
118
+ Or `SAMEORIGIN` if framing by same-origin pages is needed.
119
+
120
+ **What security_scanner.py checks:**
121
+ - Header is present
122
+ - Value is DENY or SAMEORIGIN (not ALLOW-FROM, which is deprecated)
123
+
124
+ **Implementation:**
125
+
126
+ Express.js:
127
+ ```javascript
128
+ app.use(helmet.frameguard({ action: "deny" }));
129
+ ```
130
+
131
+ Django:
132
+ ```python
133
+ # settings.py (default in Django 3+)
134
+ X_FRAME_OPTIONS = "DENY"
135
+ ```
136
+
137
+ Nginx:
138
+ ```nginx
139
+ add_header X-Frame-Options "DENY" always;
140
+ ```
141
+
142
+ ---
143
+
144
+ ## X-Content-Type-Options
145
+
146
+ **Purpose:** Prevents MIME-type sniffing, which can lead to XSS when browsers
147
+ interpret files as a different content type than declared.
148
+
149
+ **Recommended value:**
150
+ ```
151
+ X-Content-Type-Options: nosniff
152
+ ```
153
+
154
+ **What security_scanner.py checks:**
155
+ - Header is present
156
+ - Value is exactly `nosniff`
157
+
158
+ **Implementation:**
159
+
160
+ Express.js:
161
+ ```javascript
162
+ app.use(helmet.noSniff());
163
+ ```
164
+
165
+ Django:
166
+ ```python
167
+ # Enabled by default via SecurityMiddleware
168
+ SECURE_CONTENT_TYPE_NOSNIFF = True
169
+ ```
170
+
171
+ Nginx:
172
+ ```nginx
173
+ add_header X-Content-Type-Options "nosniff" always;
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Referrer-Policy
179
+
180
+ **Purpose:** Controls how much referrer information is included with requests,
181
+ preventing leakage of sensitive URLs to third parties.
182
+
183
+ **Recommended values:**
184
+ ```
185
+ Referrer-Policy: strict-origin-when-cross-origin
186
+ ```
187
+ Or `no-referrer` for maximum privacy.
188
+
189
+ **What security_scanner.py checks:**
190
+ - Header is present
191
+ - Value is not `unsafe-url` (leaks full URL including path and query)
192
+ - Value is not empty
193
+
194
+ **Implementation:**
195
+
196
+ Express.js:
197
+ ```javascript
198
+ app.use(helmet.referrerPolicy({ policy: "strict-origin-when-cross-origin" }));
199
+ ```
200
+
201
+ Django:
202
+ ```python
203
+ SECURE_REFERRER_POLICY = "strict-origin-when-cross-origin"
204
+ ```
205
+
206
+ Nginx:
207
+ ```nginx
208
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
209
+ ```
210
+
211
+ ---
212
+
213
+ ## Permissions-Policy
214
+
215
+ **Purpose:** Controls which browser features and APIs can be used by the page and
216
+ its iframes (camera, microphone, geolocation, etc.).
217
+
218
+ **Recommended value:**
219
+ ```
220
+ Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
221
+ ```
222
+
223
+ **What security_scanner.py checks:**
224
+ - Header is present
225
+ - Notes which features are restricted
226
+
227
+ **Implementation:**
228
+
229
+ Express.js:
230
+ ```javascript
231
+ app.use(helmet.permittedCrossDomainPolicies());
232
+ // Or manually:
233
+ app.use((req, res, next) => {
234
+ res.setHeader("Permissions-Policy",
235
+ "camera=(), microphone=(), geolocation=(), payment=()");
236
+ next();
237
+ });
238
+ ```
239
+
240
+ Nginx:
241
+ ```nginx
242
+ add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
243
+ ```
244
+
245
+ ---
246
+
247
+ ## X-XSS-Protection (Deprecated)
248
+
249
+ **Purpose:** Legacy header that enabled the browser's built-in XSS filter.
250
+ Deprecated in modern browsers in favor of CSP. Can cause issues if set to
251
+ `1; mode=block` on some older browsers.
252
+
253
+ **Recommended value:**
254
+ ```
255
+ X-XSS-Protection: 0
256
+ ```
257
+ Set to 0 (disabled) since the browser feature is deprecated and CSP is the
258
+ proper replacement.
259
+
260
+ **What security_scanner.py checks:**
261
+ - Notes if present
262
+ - Info-level finding (not a vulnerability)
263
+
264
+ ---
265
+
266
+ ## Cache-Control (Security-Relevant)
267
+
268
+ **Purpose:** Prevents sensitive responses from being cached and served to
269
+ unauthorized users.
270
+
271
+ **Recommended value for sensitive pages:**
272
+ ```
273
+ Cache-Control: no-store, no-cache, must-revalidate, private
274
+ ```
275
+
276
+ **Implementation:**
277
+
278
+ Express.js:
279
+ ```javascript
280
+ app.use("/api/private", (req, res, next) => {
281
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, private");
282
+ next();
283
+ });
284
+ ```
285
+
286
+ Django:
287
+ ```python
288
+ from django.views.decorators.cache import never_cache
289
+
290
+ @never_cache
291
+ def sensitive_view(request):
292
+ ...
293
+ ```
294
+
295
+ ---
296
+
297
+ ## Complete Header Set
298
+
299
+ Recommended minimum security headers for a production web application:
300
+
301
+ ```
302
+ Content-Security-Policy: default-src 'self'; script-src 'self'; frame-ancestors 'none'
303
+ Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
304
+ X-Frame-Options: DENY
305
+ X-Content-Type-Options: nosniff
306
+ Referrer-Policy: strict-origin-when-cross-origin
307
+ Permissions-Policy: camera=(), microphone=(), geolocation=()
308
+ X-XSS-Protection: 0
309
+ ```
310
+
311
+ ### Nginx complete block:
312
+ ```nginx
313
+ # Security Headers
314
+ add_header Content-Security-Policy "default-src 'self'; script-src 'self'; frame-ancestors 'none'" always;
315
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
316
+ add_header X-Frame-Options "DENY" always;
317
+ add_header X-Content-Type-Options "nosniff" always;
318
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
319
+ add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
320
+ add_header X-XSS-Protection "0" always;
321
+
322
+ # Hide server version
323
+ server_tokens off;
324
+ ```
325
+
326
+ ### Apache complete block:
327
+ ```apache
328
+ # Security Headers
329
+ Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; frame-ancestors 'none'"
330
+ Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
331
+ Header always set X-Frame-Options "DENY"
332
+ Header always set X-Content-Type-Options "nosniff"
333
+ Header always set Referrer-Policy "strict-origin-when-cross-origin"
334
+ Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
335
+ Header always set X-XSS-Protection "0"
336
+
337
+ # Hide server version
338
+ ServerTokens Prod
339
+ ServerSignature Off
340
+ ```
341
+
342
+ ---
343
+
344
+ ## Header Grading
345
+
346
+ The `security_scanner.py` grades headers on a 0-100 scale:
347
+
348
+ | Header | Weight | Scoring |
349
+ |--------|--------|---------|
350
+ | Content-Security-Policy | 25 | Present + default-src + no unsafe-eval |
351
+ | Strict-Transport-Security | 20 | Present + max-age >= 1yr + includeSubDomains |
352
+ | X-Content-Type-Options | 15 | Present + nosniff |
353
+ | X-Frame-Options | 15 | Present + DENY or SAMEORIGIN |
354
+ | Referrer-Policy | 10 | Present + not unsafe-url |
355
+ | Permissions-Policy | 10 | Present |
356
+ | Server header hidden | 5 | No version info in Server header |
357
+
358
+ ---
359
+
360
+ ## Further Reading
361
+
362
+ - [MDN HTTP Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)
363
+ - [OWASP Secure Headers Project](https://owasp.org/www-project-secure-headers/)
364
+ - [SecurityHeaders.com](https://securityheaders.com/) - Free header scanner
365
+ - [Helmet.js Documentation](https://helmetjs.github.io/)