@intentsolutionsio/penetration-tester 2.0.0 → 3.0.4

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.
Files changed (112) hide show
  1. package/.claude-plugin/plugin.json +8 -3
  2. package/README.md +8 -0
  3. package/commands/pentest.md +5 -0
  4. package/package.json +8 -3
  5. package/skills/analyzing-tls-config/SKILL.md +221 -0
  6. package/skills/analyzing-tls-config/references/AUTHORIZATION.md +133 -0
  7. package/skills/analyzing-tls-config/references/PLAYBOOK.md +267 -0
  8. package/skills/analyzing-tls-config/references/THEORY.md +128 -0
  9. package/skills/analyzing-tls-config/scripts/analyze_tls.py +415 -0
  10. package/skills/auditing-cors-policy/SKILL.md +186 -0
  11. package/skills/auditing-cors-policy/references/PLAYBOOK.md +220 -0
  12. package/skills/auditing-cors-policy/references/THEORY.md +142 -0
  13. package/skills/auditing-cors-policy/scripts/audit_cors.py +350 -0
  14. package/skills/auditing-npm-dependencies/SKILL.md +254 -0
  15. package/skills/auditing-npm-dependencies/references/PLAYBOOK.md +175 -0
  16. package/skills/auditing-npm-dependencies/references/THEORY.md +122 -0
  17. package/skills/auditing-npm-dependencies/scripts/audit_npm.py +408 -0
  18. package/skills/auditing-python-dependencies/SKILL.md +251 -0
  19. package/skills/auditing-python-dependencies/references/PLAYBOOK.md +193 -0
  20. package/skills/auditing-python-dependencies/references/THEORY.md +122 -0
  21. package/skills/auditing-python-dependencies/scripts/audit_python.py +459 -0
  22. package/skills/checking-http-security-headers/SKILL.md +176 -0
  23. package/skills/checking-http-security-headers/references/PLAYBOOK.md +212 -0
  24. package/skills/checking-http-security-headers/references/THEORY.md +137 -0
  25. package/skills/checking-http-security-headers/scripts/check_headers.py +362 -0
  26. package/skills/checking-license-compliance/SKILL.md +225 -0
  27. package/skills/checking-license-compliance/references/PLAYBOOK.md +161 -0
  28. package/skills/checking-license-compliance/references/THEORY.md +152 -0
  29. package/skills/checking-license-compliance/scripts/check_licenses.py +461 -0
  30. package/skills/composing-vulnerability-report/SKILL.md +212 -0
  31. package/skills/composing-vulnerability-report/references/PLAYBOOK.md +180 -0
  32. package/skills/composing-vulnerability-report/references/THEORY.md +178 -0
  33. package/skills/composing-vulnerability-report/scripts/compose_report.py +396 -0
  34. package/skills/confirming-pentest-authorization/SKILL.md +247 -0
  35. package/skills/confirming-pentest-authorization/references/PLAYBOOK.md +189 -0
  36. package/skills/confirming-pentest-authorization/references/THEORY.md +167 -0
  37. package/skills/confirming-pentest-authorization/scripts/check_authorization.py +457 -0
  38. package/skills/defining-pentest-scope/SKILL.md +227 -0
  39. package/skills/defining-pentest-scope/references/PLAYBOOK.md +238 -0
  40. package/skills/defining-pentest-scope/references/THEORY.md +170 -0
  41. package/skills/defining-pentest-scope/scripts/define_scope.py +472 -0
  42. package/skills/detecting-command-injection-patterns/SKILL.md +144 -0
  43. package/skills/detecting-command-injection-patterns/references/PLAYBOOK.md +302 -0
  44. package/skills/detecting-command-injection-patterns/references/THEORY.md +206 -0
  45. package/skills/detecting-command-injection-patterns/scripts/scan_cmdi.py +290 -0
  46. package/skills/detecting-debug-endpoints/SKILL.md +207 -0
  47. package/skills/detecting-debug-endpoints/references/PLAYBOOK.md +402 -0
  48. package/skills/detecting-debug-endpoints/references/THEORY.md +218 -0
  49. package/skills/detecting-debug-endpoints/scripts/probe_debug.py +518 -0
  50. package/skills/detecting-directory-listing/SKILL.md +206 -0
  51. package/skills/detecting-directory-listing/references/PLAYBOOK.md +277 -0
  52. package/skills/detecting-directory-listing/references/THEORY.md +203 -0
  53. package/skills/detecting-directory-listing/scripts/probe_directory_listing.py +180 -0
  54. package/skills/detecting-eval-exec-usage/SKILL.md +128 -0
  55. package/skills/detecting-eval-exec-usage/references/PLAYBOOK.md +306 -0
  56. package/skills/detecting-eval-exec-usage/references/THEORY.md +159 -0
  57. package/skills/detecting-eval-exec-usage/scripts/scan_eval.py +223 -0
  58. package/skills/detecting-exposed-secrets-files/SKILL.md +179 -0
  59. package/skills/detecting-exposed-secrets-files/references/PLAYBOOK.md +274 -0
  60. package/skills/detecting-exposed-secrets-files/references/THEORY.md +174 -0
  61. package/skills/detecting-exposed-secrets-files/scripts/probe_secrets.py +207 -0
  62. package/skills/detecting-insecure-deserialization/SKILL.md +148 -0
  63. package/skills/detecting-insecure-deserialization/references/PLAYBOOK.md +333 -0
  64. package/skills/detecting-insecure-deserialization/references/THEORY.md +199 -0
  65. package/skills/detecting-insecure-deserialization/scripts/scan_deserialization.py +250 -0
  66. package/skills/detecting-sql-injection-patterns/SKILL.md +161 -0
  67. package/skills/detecting-sql-injection-patterns/references/PLAYBOOK.md +317 -0
  68. package/skills/detecting-sql-injection-patterns/references/THEORY.md +261 -0
  69. package/skills/detecting-sql-injection-patterns/scripts/scan_sqli.py +354 -0
  70. package/skills/detecting-ssl-cert-issues/SKILL.md +182 -0
  71. package/skills/detecting-ssl-cert-issues/references/PLAYBOOK.md +203 -0
  72. package/skills/detecting-ssl-cert-issues/references/THEORY.md +133 -0
  73. package/skills/detecting-ssl-cert-issues/scripts/check_cert_chain.py +481 -0
  74. package/skills/detecting-weak-cryptography/SKILL.md +147 -0
  75. package/skills/detecting-weak-cryptography/references/PLAYBOOK.md +466 -0
  76. package/skills/detecting-weak-cryptography/references/THEORY.md +194 -0
  77. package/skills/detecting-weak-cryptography/scripts/scan_weak_crypto.py +417 -0
  78. package/skills/fingerprinting-server-software/SKILL.md +191 -0
  79. package/skills/fingerprinting-server-software/references/PLAYBOOK.md +337 -0
  80. package/skills/fingerprinting-server-software/references/THEORY.md +183 -0
  81. package/skills/fingerprinting-server-software/scripts/fingerprint_server.py +347 -0
  82. package/skills/generating-executive-summary/SKILL.md +261 -0
  83. package/skills/generating-executive-summary/references/PLAYBOOK.md +201 -0
  84. package/skills/generating-executive-summary/references/THEORY.md +195 -0
  85. package/skills/generating-executive-summary/scripts/exec_summary.py +538 -0
  86. package/skills/mapping-findings-to-owasp-top10/SKILL.md +235 -0
  87. package/skills/mapping-findings-to-owasp-top10/references/PLAYBOOK.md +193 -0
  88. package/skills/mapping-findings-to-owasp-top10/references/THEORY.md +160 -0
  89. package/skills/mapping-findings-to-owasp-top10/scripts/map_owasp.py +540 -0
  90. package/skills/performing-penetration-testing/SKILL.md +282 -190
  91. package/skills/performing-penetration-testing/references/OWASP_TOP_10.md +22 -0
  92. package/skills/performing-penetration-testing/references/REMEDIATION_PLAYBOOK.md +46 -0
  93. package/skills/performing-penetration-testing/references/SECURITY_HEADERS.md +41 -0
  94. package/skills/performing-penetration-testing/scripts/code_security_scanner.py +144 -79
  95. package/skills/performing-penetration-testing/scripts/dependency_auditor.py +116 -93
  96. package/skills/performing-penetration-testing/scripts/security_scanner.py +574 -446
  97. package/skills/probing-dangerous-http-methods/SKILL.md +182 -0
  98. package/skills/probing-dangerous-http-methods/references/PLAYBOOK.md +234 -0
  99. package/skills/probing-dangerous-http-methods/references/THEORY.md +145 -0
  100. package/skills/probing-dangerous-http-methods/scripts/probe_methods.py +263 -0
  101. package/skills/recording-pentest-engagement/SKILL.md +253 -0
  102. package/skills/recording-pentest-engagement/references/PLAYBOOK.md +203 -0
  103. package/skills/recording-pentest-engagement/references/THEORY.md +195 -0
  104. package/skills/recording-pentest-engagement/scripts/record_engagement.py +461 -0
  105. package/skills/scanning-for-hardcoded-secrets/SKILL.md +215 -0
  106. package/skills/scanning-for-hardcoded-secrets/references/PLAYBOOK.md +325 -0
  107. package/skills/scanning-for-hardcoded-secrets/references/THEORY.md +175 -0
  108. package/skills/scanning-for-hardcoded-secrets/scripts/scan_secrets.py +395 -0
  109. package/skills/tracing-transitive-vulnerabilities/SKILL.md +235 -0
  110. package/skills/tracing-transitive-vulnerabilities/references/PLAYBOOK.md +233 -0
  111. package/skills/tracing-transitive-vulnerabilities/references/THEORY.md +138 -0
  112. package/skills/tracing-transitive-vulnerabilities/scripts/trace_vulns.py +484 -0
@@ -0,0 +1,402 @@
1
+ # Debug-Endpoint Remediation Playbook
2
+
3
+ ## Spring Boot Actuator
4
+
5
+ ### Narrow the exposed endpoints (preferred)
6
+
7
+ Default Spring Boot 3.x already only exposes `health` + `info`. If
8
+ something widened the surface, narrow it back:
9
+
10
+ `application-prod.yml`:
11
+
12
+ ```yaml
13
+ management:
14
+ endpoints:
15
+ web:
16
+ exposure:
17
+ include: health, info
18
+ exclude: env, heapdump, jolokia, configprops, beans, mappings, threaddump, loggers
19
+ endpoint:
20
+ health:
21
+ show-details: never # or 'when-authorized'
22
+ ```
23
+
24
+ ### Require auth on Actuator endpoints
25
+
26
+ For internal-ops use of Actuator, gate behind authentication:
27
+
28
+ ```yaml
29
+ management:
30
+ endpoints:
31
+ web:
32
+ base-path: /internal/actuator # not /actuator
33
+ ```
34
+
35
+ `SecurityConfig.java`:
36
+
37
+ ```java
38
+ @Configuration
39
+ public class ActuatorSecurityConfig {
40
+ @Bean
41
+ SecurityFilterChain actuatorChain(HttpSecurity http) throws Exception {
42
+ http.securityMatcher(EndpointRequest.toAnyEndpoint())
43
+ .authorizeHttpRequests(a -> a.anyRequest().hasRole("ACTUATOR_ADMIN"))
44
+ .httpBasic(Customizer.withDefaults());
45
+ return http.build();
46
+ }
47
+ }
48
+ ```
49
+
50
+ Or restrict by IP in a reverse proxy (nginx):
51
+
52
+ ```nginx
53
+ location /actuator/ {
54
+ allow 10.0.0.0/8;
55
+ deny all;
56
+ proxy_pass http://springapp:8080;
57
+ }
58
+ ```
59
+
60
+ ### Disable Jolokia entirely (most aggressive)
61
+
62
+ `pom.xml`:
63
+
64
+ ```xml
65
+ <!-- Remove the dependency -->
66
+ <dependency>
67
+ <groupId>org.jolokia</groupId>
68
+ <artifactId>jolokia-core</artifactId>
69
+ <!-- ... DELETE THIS BLOCK ... -->
70
+ </dependency>
71
+ ```
72
+
73
+ Or via `application.yml`:
74
+
75
+ ```yaml
76
+ management:
77
+ endpoint:
78
+ jolokia:
79
+ access: NONE
80
+ ```
81
+
82
+ ## Apache mod_status
83
+
84
+ ### Disable globally (preferred for production)
85
+
86
+ `httpd.conf`:
87
+
88
+ ```apache
89
+ # Comment out or remove the mod_status load
90
+ # LoadModule status_module modules/mod_status.so
91
+
92
+ # Remove the Location block
93
+ # <Location "/server-status">
94
+ # SetHandler server-status
95
+ # Require local
96
+ # </Location>
97
+ ```
98
+
99
+ ### If needed, lock down by IP
100
+
101
+ ```apache
102
+ <Location "/server-status">
103
+ SetHandler server-status
104
+ Require ip 10.0.0.0/8
105
+ Require ip 192.168.0.0/16
106
+ # Require local # already includes 127.0.0.1 + IPv6 loopback
107
+ </Location>
108
+
109
+ <Location "/server-info">
110
+ SetHandler server-info
111
+ Require ip 10.0.0.0/8
112
+ </Location>
113
+
114
+ # Disable ExtendedStatus to stop URL disclosure in scoreboard
115
+ ExtendedStatus Off
116
+ ```
117
+
118
+ ## nginx stub_status
119
+
120
+ ```nginx
121
+ location = /nginx_status {
122
+ stub_status;
123
+ allow 10.0.0.0/8;
124
+ deny all;
125
+ }
126
+ ```
127
+
128
+ Or remove the block entirely if not needed.
129
+
130
+ ## Prometheus /metrics
131
+
132
+ ### Add bearer-token auth
133
+
134
+ `application.yml` (Spring Boot example):
135
+
136
+ ```yaml
137
+ management:
138
+ endpoint:
139
+ prometheus:
140
+ enabled: true
141
+ metrics:
142
+ export:
143
+ prometheus:
144
+ enabled: true
145
+
146
+ # Apply security to the metrics path:
147
+ spring:
148
+ security:
149
+ user:
150
+ name: prometheus
151
+ password: ${PROMETHEUS_SCRAPE_PASSWORD}
152
+ ```
153
+
154
+ ### Or restrict by IP at the reverse proxy
155
+
156
+ ```nginx
157
+ location /metrics {
158
+ allow 10.0.10.5/32; # the prometheus server IP
159
+ deny all;
160
+ proxy_pass http://app:8080;
161
+ }
162
+ ```
163
+
164
+ ### Audit metric labels for credential leaks
165
+
166
+ Run a sanity scan over the actual metric output:
167
+
168
+ ```bash
169
+ curl -s http://localhost:8080/metrics | grep -iE 'token=|password=|key=|secret=' | head -20
170
+ ```
171
+
172
+ If any labels contain credentials, fix the metric emission code to
173
+ sanitize / drop those labels before scraping.
174
+
175
+ ## Elasticsearch _cat /_search
176
+
177
+ ### Enable security (free in 7.x+ Basic license)
178
+
179
+ `elasticsearch.yml`:
180
+
181
+ ```yaml
182
+ xpack.security.enabled: true
183
+ xpack.security.authc:
184
+ api_key.enabled: true
185
+ xpack.security.transport.ssl.enabled: true
186
+ ```
187
+
188
+ Then create users:
189
+
190
+ ```bash
191
+ ./bin/elasticsearch-setup-passwords interactive
192
+ # Set passwords for: elastic, apm_system, kibana_system, logstash_system, beats_system
193
+ ```
194
+
195
+ Update Kibana + Logstash + Beats to authenticate with their new
196
+ credentials.
197
+
198
+ ### Restrict to internal network
199
+
200
+ ```yaml
201
+ # elasticsearch.yml
202
+ network.host: 10.0.10.42 # internal IP only, NOT 0.0.0.0
203
+ ```
204
+
205
+ Or at the firewall: block 9200 from public internet entirely.
206
+
207
+ ## Kibana / Grafana / Eureka / Consul
208
+
209
+ All four follow the same pattern: gate behind reverse-proxy auth or
210
+ move to internal-network-only.
211
+
212
+ ### nginx reverse proxy with basic auth
213
+
214
+ ```nginx
215
+ server {
216
+ listen 443 ssl;
217
+ server_name internal-grafana.example.com;
218
+ location / {
219
+ auth_basic "Restricted";
220
+ auth_basic_user_file /etc/nginx/.htpasswd;
221
+ proxy_pass http://grafana:3000;
222
+ }
223
+ }
224
+ ```
225
+
226
+ ### Consul ACL bootstrap
227
+
228
+ ```bash
229
+ consul acl bootstrap
230
+ # Returns SecretID; store securely
231
+ # Create policy that denies anonymous access:
232
+ consul acl policy create -name "anonymous-deny" -rules='node_prefix "" { policy = "deny" } service_prefix "" { policy = "deny" }'
233
+ consul acl token update -id 00000000-0000-0000-0000-000000000002 -policy-name anonymous-deny
234
+ ```
235
+
236
+ ## phpMyAdmin
237
+
238
+ ### Disable / remove entirely (preferred)
239
+
240
+ ```bash
241
+ sudo apt-get remove phpmyadmin
242
+ sudo a2disconf phpmyadmin
243
+ sudo systemctl reload apache2
244
+ ```
245
+
246
+ If you can't remove it because legacy ops use it:
247
+
248
+ ### Restrict at the web server
249
+
250
+ ```apache
251
+ <Directory /usr/share/phpmyadmin/>
252
+ Require ip 10.0.0.0/8
253
+ # Or use IP-based ACL specific to ops jump hosts
254
+ </Directory>
255
+ ```
256
+
257
+ Or move it to a non-default path:
258
+
259
+ ```apache
260
+ Alias /admin-tools-only-internal-do-not-share/phpmyadmin /usr/share/phpmyadmin
261
+ ```
262
+
263
+ (Security by obscurity is not security, but combined with IP
264
+ restriction it's defense-in-depth.)
265
+
266
+ ## GraphQL Playground / GraphiQL
267
+
268
+ ### Apollo Server 4.x
269
+
270
+ ```typescript
271
+ const server = new ApolloServer({
272
+ typeDefs,
273
+ resolvers,
274
+ // Playground is OFF by default in production (NODE_ENV=production)
275
+ introspection: process.env.NODE_ENV !== 'production',
276
+ });
277
+ ```
278
+
279
+ ### graphql-yoga
280
+
281
+ ```typescript
282
+ import { createYoga } from 'graphql-yoga';
283
+ const yoga = createYoga({
284
+ schema,
285
+ graphiql: process.env.NODE_ENV !== 'production',
286
+ landingPage: false,
287
+ });
288
+ ```
289
+
290
+ ### Express + express-graphql (legacy)
291
+
292
+ ```javascript
293
+ app.use('/graphql', graphqlHTTP({
294
+ schema,
295
+ graphiql: false, // disable in production
296
+ }));
297
+ ```
298
+
299
+ ## Swagger UI / OpenAPI
300
+
301
+ ### Spring (springdoc-openapi)
302
+
303
+ ```yaml
304
+ springdoc:
305
+ swagger-ui:
306
+ enabled: false # disable in production
307
+ api-docs:
308
+ enabled: false
309
+ ```
310
+
311
+ Or via profile:
312
+
313
+ ```yaml
314
+ # application-prod.yml
315
+ springdoc:
316
+ swagger-ui:
317
+ enabled: false
318
+ ```
319
+
320
+ ### FastAPI
321
+
322
+ ```python
323
+ app = FastAPI(
324
+ docs_url=None if PRODUCTION else "/docs",
325
+ redoc_url=None if PRODUCTION else "/redoc",
326
+ openapi_url=None if PRODUCTION else "/openapi.json",
327
+ )
328
+ ```
329
+
330
+ ### Express + swagger-ui-express
331
+
332
+ Wrap with auth or skip mounting in production:
333
+
334
+ ```javascript
335
+ if (process.env.NODE_ENV !== 'production') {
336
+ app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(spec));
337
+ }
338
+ ```
339
+
340
+ ## Django
341
+
342
+ ### Production settings
343
+
344
+ ```python
345
+ # settings/production.py
346
+ DEBUG = False # CRITICAL — never True in prod
347
+
348
+ # Remove debug toolbar from INSTALLED_APPS and MIDDLEWARE for prod
349
+ if DEBUG:
350
+ INSTALLED_APPS.append('debug_toolbar')
351
+ MIDDLEWARE.append('debug_toolbar.middleware.DebugToolbarMiddleware')
352
+ ```
353
+
354
+ ## Go expvar / pprof
355
+
356
+ Don't import `_ "net/http/pprof"` in production. Pull the import into
357
+ a build tag:
358
+
359
+ ```go
360
+ // +build !production
361
+
362
+ package main
363
+
364
+ import _ "net/http/pprof"
365
+ ```
366
+
367
+ Or expose pprof on a separate internal-only mux:
368
+
369
+ ```go
370
+ go func() {
371
+ // Internal-network-only listener
372
+ log.Fatal(http.ListenAndServe("127.0.0.1:6060", nil))
373
+ }()
374
+ ```
375
+
376
+ ## CI integration
377
+
378
+ ```yaml
379
+ - name: Debug-endpoint posture gate
380
+ run: |
381
+ python3 plugins/security/penetration-tester/skills/detecting-debug-endpoints/scripts/probe_debug.py \
382
+ "${{ secrets.STAGING_URL }}" \
383
+ --authorized \
384
+ --min-severity high \
385
+ --format json \
386
+ --output debug-endpoint-report.json
387
+ - run: |
388
+ if jq 'any(.severity == "critical" or .severity == "high")' debug-endpoint-report.json | grep -q true; then
389
+ echo "::error::Debug endpoint posture regression"
390
+ exit 1
391
+ fi
392
+ ```
393
+
394
+ ## Verification after remediation
395
+
396
+ ```bash
397
+ python3 ${CLAUDE_PLUGIN_ROOT}/skills/detecting-debug-endpoints/scripts/probe_debug.py \
398
+ https://example.com --authorized --min-severity medium
399
+ ```
400
+
401
+ Expected: exit 0, zero MEDIUM-or-higher findings. INFO findings on
402
+ deliberately-public Swagger / OpenAPI docs are operational choices.
@@ -0,0 +1,218 @@
1
+ # Debug-Endpoint Theory
2
+
3
+ ## The recurring pattern
4
+
5
+ Modern application frameworks ship rich introspection by default
6
+ because developers need it to debug locally. The framework defaults
7
+ assume "this is running on my laptop in development mode." The
8
+ production deploy inherits the same defaults unless someone
9
+ explicitly disables them. The result is a class of finding that's
10
+ almost universal: any non-trivial Spring Boot / Apache / Prometheus /
11
+ ELK / Consul deployment exposes at least one of these endpoints
12
+ unless an operator went out of their way to disable them.
13
+
14
+ Each framework deserves its own short explanation.
15
+
16
+ ## Spring Boot Actuator
17
+
18
+ Actuator is Spring Boot's introspection module. By default (in
19
+ Spring Boot 2.x with `management.endpoints.web.exposure.include=*`),
20
+ it exposes a JSON-shaped tree at `/actuator/` with endpoints like:
21
+
22
+ - `/actuator/env` — every Spring configuration property and every
23
+ environment variable, including database URLs, API keys read from
24
+ env, and JVM args.
25
+ - `/actuator/heapdump` — a live JVM heap dump (HPROF binary).
26
+ Contains all in-memory state: connection pool internals, recent
27
+ request data, cached credentials, JWT signing keys if they're
28
+ string-allocated.
29
+ - `/actuator/jolokia` — JMX-over-HTTP. With write permissions, this
30
+ is pre-auth RCE: an attacker can invoke arbitrary JMX MBeans
31
+ including `javax.management.Diagnostic.threadDump` and (with the
32
+ right MBean) execute arbitrary code.
33
+ - `/actuator/loggers` — POST changes log level for any package at
34
+ runtime. An attacker can silence logs of their own activity by
35
+ setting `org.springframework.security` to OFF.
36
+ - `/actuator/threaddump` — current thread state. Reveals which
37
+ business operations are in flight + stack traces with method
38
+ names (informs targeted attacks).
39
+ - `/actuator/health` — dependency state ("UP" / "DOWN" per
40
+ database / cache / external service). Maps the internal topology.
41
+ - `/actuator/mappings` — full route table including paths the public
42
+ app doesn't expose anywhere else.
43
+
44
+ Spring Boot 2.x default was exposure-everything; Spring Boot 3.x
45
+ default narrowed to `/health` + `/info` only. Many deployments still
46
+ have legacy 2.x-era `management.endpoints.web.exposure.include=*`
47
+ overrides in `application-prod.yml` that wasn't audited at the 3.x
48
+ upgrade.
49
+
50
+ The combined finding chain: `/actuator/env` exposes the database
51
+ connection string + creds. Connect to the database directly. End.
52
+
53
+ ## Apache mod_status
54
+
55
+ `mod_status` exposes server runtime stats at `/server-status`:
56
+
57
+ - Apache version + OS
58
+ - Active worker count + idle workers
59
+ - **The URL of every active request** (the "Scoreboard" extended
60
+ view, enabled by `ExtendedStatus On`)
61
+ - The client IP of every active connection
62
+
63
+ The URL-disclosure axis is the operational risk: any session token,
64
+ OAuth code, or password-in-query-string that flows through Apache is
65
+ visible to anyone polling `/server-status`. A scraper hitting it
66
+ once a second can collect tokens at scale.
67
+
68
+ The default in older Apache versions was to allow `/server-status`
69
+ from localhost; many configs were edited to allow internal IP ranges,
70
+ then forgotten about as networks evolved.
71
+
72
+ ## nginx stub_status
73
+
74
+ `/nginx_status` exposes connection counts and request counts. Less
75
+ sensitive than Apache's mod_status (doesn't show URLs) but still
76
+ operational telemetry the attacker shouldn't have. Common on
77
+ deployments that copy-pasted `stub_status on;` from a tutorial.
78
+
79
+ ## Prometheus /metrics
80
+
81
+ Prometheus's `/metrics` endpoint is the data source for monitoring.
82
+ The exposed surface is the application's own metric series.
83
+
84
+ The non-obvious risk: metric LABELS often contain credentials by
85
+ accident. A "request count by endpoint" series might label requests
86
+ by full URL including query string. A "database connection state"
87
+ metric might label connections by full connection string. The
88
+ labels are designed for Grafana queries; they're not designed to be
89
+ adversarially scrutinized.
90
+
91
+ Common label-leak categories:
92
+
93
+ - `http_requests_total{path="/api/users?token=...", ...}`
94
+ - `database_connections_active{dsn="postgresql://user:pass@..."}`
95
+ - `external_api_calls_total{key="sk-..."}`
96
+
97
+ The fix is twofold: bring the endpoint behind auth (a static bearer
98
+ token is the conventional Prometheus pattern), AND audit the label
99
+ cardinality for accidental credential disclosure.
100
+
101
+ ## Elasticsearch _cat /_search
102
+
103
+ Elasticsearch endpoints under `/_cat/` and `/_cluster/` expose
104
+ cluster state, indices, document counts, and node metadata. The
105
+ `/_search` endpoint serves arbitrary queries against any visible
106
+ index without authentication if the cluster is unconfigured.
107
+
108
+ The historical pattern: Elasticsearch shipped with no auth defaults
109
+ until version 7.x (the Basic license added security in late 2020).
110
+ A cluster set up before that date and never upgraded with security
111
+ enabled is fully open to anyone who can reach port 9200.
112
+
113
+ The Shodan-style internet scan of exposed Elasticsearch clusters is
114
+ a recurring "another data breach" story; the underlying issue is
115
+ always this misconfiguration.
116
+
117
+ ## Kibana / Grafana / Eureka / Consul
118
+
119
+ Service-discovery and observability panels. Each can expose:
120
+
121
+ - Kibana: full search of Elasticsearch indices through the UI
122
+ - Grafana: dashboards that may include connection strings in
123
+ variable definitions
124
+ - Eureka: service registry with internal IPs + ports of every
125
+ microservice
126
+ - Consul: service catalog + agent checks with full topology
127
+
128
+ For Eureka and Consul specifically, the API is designed to be
129
+ read-mostly from inside the service mesh. Exposing it externally
130
+ hands an attacker the network map.
131
+
132
+ ## phpMyAdmin
133
+
134
+ GUI for MySQL/MariaDB administration. Many shared-hosting
135
+ installations include it at `/phpmyadmin/` by default; legacy LAMP
136
+ stacks deploy it next to the app. If reachable AND unauthenticated
137
+ (or with default credentials), it's full DB access via web GUI.
138
+
139
+ Fingerprint: HTML body containing "phpMyAdmin" + a login form with
140
+ `name="pma_username"`.
141
+
142
+ ## GraphQL Playground / GraphiQL
143
+
144
+ Interactive GraphQL UI for developers. Enabled by default in many
145
+ GraphQL server setups (Apollo Server, graphql-yoga). The risk has
146
+ two layers:
147
+
148
+ 1. **Schema introspection** — the playground reveals the full
149
+ schema, which informs every subsequent query/mutation attack.
150
+ 2. **Query execution** — if the GraphQL endpoint is publicly
151
+ reachable AND the playground is too, the attacker has both a
152
+ schema map AND an interactive interface to craft attacks against
153
+ it.
154
+
155
+ Best practice: disable introspection in production, disable the
156
+ playground in production. Apollo Server 4.x has both off by default
157
+ in `NODE_ENV=production`; older versions need explicit config.
158
+
159
+ ## Swagger UI / OpenAPI
160
+
161
+ Same pattern as GraphQL: the schema (OpenAPI spec) tells an attacker
162
+ what endpoints exist, what parameters they accept, what response
163
+ shapes look like. Exposing `/swagger-ui` or `/openapi.json` on
164
+ production isn't a critical vulnerability but it's free recon.
165
+
166
+ Some defensive postures keep Swagger publicly reachable as a feature
167
+ (public API docs). That's a deliberate choice; the finding is
168
+ informational unless the API itself has auth issues.
169
+
170
+ ## Django debug toolbar
171
+
172
+ If `DEBUG=True` shipped to production, the Django debug toolbar
173
+ exposes SQL queries, request env, settings, template context.
174
+ Effectively equivalent to `/actuator/env` for Django stacks.
175
+
176
+ ## Go expvar / pprof
177
+
178
+ Built-in Go stdlib endpoints:
179
+
180
+ - `/debug/vars` — JSON dump of expvar package: cmdline, memstats,
181
+ custom-registered metrics
182
+ - `/debug/pprof/` — pprof profiles for CPU, heap, goroutines
183
+
184
+ The pprof endpoints can be triggered to start CPU profiling that
185
+ slows the server, AND can be used to download heap profiles that
186
+ contain live memory state (similar risk to Spring Boot heapdump).
187
+
188
+ If Go's `net/http/pprof` package is imported anywhere in the app
189
+ (it auto-registers handlers on the default mux), and the default
190
+ mux is exposed externally, pprof is reachable.
191
+
192
+ ## Why fingerprint-checking matters
193
+
194
+ Same logic as `detecting-exposed-secrets-files` (#6). SPAs return
195
+ their `index.html` for any unknown route. Without fingerprinting,
196
+ every `/actuator/*` probe returns 200 against an SPA, all false
197
+ positives.
198
+
199
+ Each framework has a distinctive body fingerprint:
200
+
201
+ - Actuator: JSON `{"_links":...}` or `"propertySources"`
202
+ - mod_status: HTML containing "Apache Server Status"
203
+ - Prometheus: text starting with `# HELP` or `# TYPE`
204
+ - Elasticsearch: tabular text with status indicators
205
+ - phpMyAdmin: HTML containing "phpMyAdmin" + `pma_username`
206
+ - Jolokia: JSON `{"agent":"jolokia"}`
207
+
208
+ The fingerprint check is what separates a real finding from SPA
209
+ noise.
210
+
211
+ ## Primary sources
212
+
213
+ - [OWASP WSTG-CONF-05 — Enumerate Infrastructure and Application Admin Interfaces](https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/02-Configuration_and_Deployment_Management_Testing/05-Enumerate_Infrastructure_and_Application_Admin_Interfaces)
214
+ - [Spring Boot Actuator docs — Production-ready features](https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html)
215
+ - [Apache mod_status docs](https://httpd.apache.org/docs/2.4/mod/mod_status.html)
216
+ - [CWE-749 — Exposed Dangerous Method or Function](https://cwe.mitre.org/data/definitions/749.html)
217
+ - [CWE-285 — Improper Authorization](https://cwe.mitre.org/data/definitions/285.html)
218
+ - [Jolokia security advisory background](https://jolokia.org/reference/html/security.html)