@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.
- package/.claude-plugin/plugin.json +19 -0
- package/LICENSE +21 -0
- package/README.md +160 -0
- package/commands/pentest.md +84 -0
- package/commands/scan-headers.md +43 -0
- package/package.json +40 -0
- package/skills/performing-penetration-testing/SKILL.md +266 -0
- package/skills/performing-penetration-testing/references/OWASP_TOP_10.md +284 -0
- package/skills/performing-penetration-testing/references/REMEDIATION_PLAYBOOK.md +452 -0
- package/skills/performing-penetration-testing/references/SECURITY_HEADERS.md +365 -0
- package/skills/performing-penetration-testing/scripts/code_security_scanner.py +780 -0
- package/skills/performing-penetration-testing/scripts/dependency_auditor.py +777 -0
- package/skills/performing-penetration-testing/scripts/requirements.txt +4 -0
- package/skills/performing-penetration-testing/scripts/security_scanner.py +1166 -0
- package/skills/performing-penetration-testing/scripts/setup_pentest_env.sh +199 -0
|
@@ -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/)
|