Skip to content

Commit 941f3f3

Browse files
authored
Update redoc_exposed.md
1 parent 43526ee commit 941f3f3

File tree

1 file changed

+39
-91
lines changed

1 file changed

+39
-91
lines changed
Lines changed: 39 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,39 @@
1-
##
2-
# This module requires Metasploit: https://metasploit.com/download
3-
# Current source: https://github.com/rapid7/metasploit-framework
4-
##
5-
6-
class MetasploitModule < Msf::Auxiliary
7-
include Msf::Auxiliary::Scanner
8-
include Msf::Exploit::Remote::HttpClient
9-
10-
def initialize(info = {})
11-
super(
12-
update_info(
13-
info,
14-
'Name' => 'ReDoc API Docs UI Exposed',
15-
'Description' => %q{
16-
Detects publicly exposed ReDoc API documentation pages.
17-
The module performs safe, read-only GET requests and reports likely
18-
ReDoc instances based on HTML markers.
19-
},
20-
'Author' => [
21-
'Hamza Sahin (@hamzasahin61)'
22-
],
23-
'License' => MSF_LICENSE,
24-
'Notes' => {
25-
'Stability' => [CRASH_SAFE], # GET requests only; should not crash or disrupt the target service
26-
'Reliability' => [], # Does not establish sessions; leaving this empty is acceptable
27-
'SideEffects' => [] # Add IOC_IN_LOGS if server logs may record these requests
28-
}
29-
)
30-
)
31-
32-
register_options(
33-
[
34-
Opt::RPORT(80),
35-
OptBool.new('SSL', [true, 'Negotiate SSL/TLS for outgoing connections', false]),
36-
OptString.new('REDOC_PATHS', [
37-
false,
38-
'Comma-separated list of paths to probe (overrides defaults)',
39-
nil
40-
])
41-
]
42-
)
43-
end
44-
45-
# returns true if the response looks like a ReDoc page
46-
def redoc_like?(res)
47-
return false unless res && res.code.between?(200, 403)
48-
49-
# Prefer DOM checks
50-
doc = res.get_html_document
51-
if doc
52-
return true if doc.at_css('redoc, redoc-, #redoc')
53-
return true if doc.css('script[src*="redoc"]').any?
54-
return true if doc.css('script[src*="redoc.standalone"]').any?
55-
end
56-
57-
# Fallback to body/title heuristics
58-
title = res.get_html_title.to_s
59-
body = res.body.to_s
60-
61-
return true if title =~ /redoc/i
62-
return true if body =~ /<redoc-?/i
63-
return true if body =~ /redoc(\.standalone)?\.js/i
64-
65-
false
66-
end
67-
68-
def check_path(path)
69-
res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(path) })
70-
redoc_like?(res)
71-
end
72-
73-
def run_host(ip)
74-
vprint_status("#{ip} - scanning for ReDoc")
75-
76-
paths =
77-
if (ds = datastore['REDOC_PATHS']) && !ds.empty?
78-
ds.split(',').map(&:strip)
79-
else
80-
['/redoc', '/redoc/', '/docs', '/api/docs', '/openapi']
81-
end
82-
83-
hit = paths.find { |p| check_path(p) }
84-
if hit
85-
print_good("#{ip} - ReDoc likely exposed at #{hit}")
86-
report_service(host: ip, port: rport, proto: 'tcp', name: 'http')
87-
else
88-
vprint_status("#{ip} - no ReDoc found")
89-
end
90-
end
91-
end
1+
## Summary
2+
This module detects publicly exposed **ReDoc** API documentation pages.
3+
It performs safe, read-only HTTP GET requests and reports likely ReDoc instances based on common HTML markers.
4+
5+
## Module name
6+
`auxiliary/scanner/http/redoc_exposed`
7+
8+
## Options
9+
* **RPORT** – Target TCP port (default: 80)
10+
* **SSL** – Enable TLS (default: false)
11+
* **REDOC_PATHS** – Optional comma-separated list of paths to probe. When unset, the module probes: `/redoc, /redoc/, /docs, /api/docs, /openapi`.
12+
13+
## Verification steps
14+
1. Start `msfconsole`
15+
2. `use auxiliary/scanner/http/redoc_exposed`
16+
3. `set RHOSTS <target or file:/path/to/targets.txt>`
17+
4. (Optional) `set REDOC_PATHS /redoc,/docs`
18+
5. (Optional) `set RPORT <port>` and/or `set SSL true`
19+
6. `run`
20+
21+
### Expected
22+
23+
`[+] <ip> - ReDoc likely exposed at <path>`
24+
25+
### Scanning notes
26+
- DOM-driven checks via `get_html_document`:
27+
- `<redoc>` / `redoc-` custom elements
28+
- `#redoc` container
29+
- `<script src="...redoc(.standalone).js">`
30+
- Falls back to body/title heuristics if DOM parsing is unavailable.
31+
- No intrusive actions; **read-only** HTTP GET requests only.
32+
33+
### Example session
34+
35+
use auxiliary/scanner/http/redoc_exposed
36+
set RHOSTS 127.0.0.1
37+
set RPORT 8001
38+
set SSL false
39+
run

0 commit comments

Comments
 (0)