DevHub
Completion state: COMPLETE. DevHub exposed a static nginx site on port 80 and MCPJam Inspector v1.4.2 on port 6274. The MCPJam Inspector /api/mcp/connect endpoint accepted unauthenticated stdio MCP server configs, allowing command execution as mcp-dev. Local...
Scenario
DevHub attack path
Completion state: COMPLETE. DevHub exposed a static nginx site on port 80 and MCPJam Inspector v1.4.2 on port 6274. The MCPJam Inspector /api/mcp/connect endpoint accepted unauthenticated stdio MCP server configs, allowing command execution as mcp-dev. Local...
Objective
Machine walkthrough focused on Machines evidence, validation, and reusable operator lessons.
Walkthrough flow
Confirmed services and versions:
Hostnames and artifacts:
Primary vector:
Backup vector:
Cross-service connection:
Source coverage
Moderate source coverage
Status: partial. This article is generated from 2 sanitized Markdown sources and keeps raw flags, credentials, keys, cookies, and reusable secrets out of the rendered blog.
Moderate confidence: the page is useful for review, but it should be treated as partial because the available source material is thinner or less narrative-complete.
- <TARGET>-DevHub/walkthrough.md
- HTB/<TARGET>-DevHub/notes.md
Technical Walkthrough
DevHub Walkthrough
Raw flags and reusable secrets are stored only under loot/ and are intentionally not printed here.
Summary
Completion state: COMPLETE.
DevHub exposed a static nginx site on port 80 and MCPJam Inspector v1.4.2 on port 6274. The MCPJam Inspector /api/mcp/connect endpoint accepted unauthenticated stdio MCP server configs, allowing command execution as mcp-dev. Local enumeration found an analyst-owned Jupyter Lab service and a root-run OpsMCP service. Jupyter provided lateral execution as analyst; OpsMCP exposed a hidden authenticated admin dump function that returned root SSH material.
Recon
nmap/initial.txt: SSH 22 and HTTP 80.nmap/allports.txt: additional TCP 6274.nmap/6274-version.txt: HTTP-like service servingMCPJam Inspector.enum/http80_ip_headers.txt: IP requests to port 80 return a 302 redirect tohttp://devhub.htb/.enum/http6274_api_strings.txt: frontend references/api/mcp/connectand other MCP API routes.enum/proc_interesting.txt: confirms@mcpjam/inspector@1.4.2during post-foothold enumeration.
Foothold
- Confirmed
/api/mcp/connectaccepted JSON withserverConfigandserverId. - Sent a harmless stdio config executing a callback command and observed the callback in
enum/http_callback_after_stdio_proof.txt. - Started a listener on the Pwnbox and triggered a reverse shell using the same endpoint.
- Baseline output as
mcp-devwas saved inenum/foothold_*.
User path
ss -lntupshowed local-only Jupyter on<TARGET>:8888and OpsMCP on<TARGET>:5000.- Process arguments showed Jupyter running as
analystwith a token; token saved only toloot/jupyter-token.txt. - Used the Jupyter API to create a Python kernel and execute commands as
analyst. - Captured
/home/analyst/user.txttoloot/user.txt; format verified as 32-character hex.
Root path
- As
analyst, read/home/analyst/.opsmcp_keyand/opt/opsmcp/server.py. - Source review showed hidden tool
ops._admin_dumpon root-run Flask service<TARGET>:5000, gated byX-API-Key. - Called
/tools/callwithname=ops._admin_dump,arguments.target=ssh_keys, andarguments.confirm=true. - Saved root SSH material under
loot/, extracted it toloot/root_id_rsa, then authenticated to SSH as root. - Captured
/root/root.txttoloot/root.txt; format verified as 32-character hex.
Evidence
- Notes:
notes.md - Foothold:
enum/http_callback_after_stdio_proof.txt,enum/devhub_shell.log,enum/foothold_* - Lateral:
enum/jupyter_,enum/analyst_ - Privilege escalation:
enum/opsmcp_source_redacted_range.txt,enum/root_ssh_test.txt,enum/root_baseline.txt - Flags and secrets:
loot/only
Source-Backed Dossier
The sections below are merged from companion Markdown notes for the same case. They are rendered after sanitization so the article stays precise without publishing raw flags, credentials, or target-specific secrets.
Notes
Scope
| Field | Value |
|---|---|
| Platform | Hack The Box / simulated lab |
| Target | DevHub |
| Difficulty | Medium |
| OS | Linux |
| Active target IP | <TARGET> |
| Hostname/domain | devhub.htb |
| Pwnbox | <TARGET> |
| Attacker/VPN IP | <TARGET> |
| Local workspace | <local workspace><TARGET>-DevHub |
| Pwnbox workspace | ~/htb/<TARGET>-DevHub |
| Started | 2026-06-06T00:54:22Z |
Evidence Ledger
| Time UTC | Phase | Command/Action | Output file | Finding | Confidence | Next action |
|---|---|---|---|---|---|---|
| 2026-06-06T00:54:22Z | setup | htbctl init | target-state.json | Workspace initialized by deterministic harness. | High | Validate route and start baseline recon. |
Synthesis
Current completion state: COMPLETE.
Pre-exploitation synthesis — 2026-06-06T01:18:00Z
- Confirmed services and versions:
- 22/tcp: OpenSSH 8.9p1 Ubuntu 3ubuntu0.15.
- 80/tcp: nginx 1.18.0, static DevHub - Internal Development Platform page.
- 6274/tcp: HTTP service serving MCPJam Inspector; nmap cannot name the service, but the frontend title, icon, and JS routes confirm MCPJam Inspector behavior.
- Hostnames and artifacts:
- <TARGET> redirects to http://devhub.htb/ on port 80.
- Pwnbox /etc/hosts has <TARGET> devhub.htb.
- Port 6274 frontend bundle references /api/mcp/connect plus multiple /api/mcp/* endpoints.
- Primary vector:
- Validate and attempt the suspected MCPJam Inspector unauthenticated /api/mcp/connect vector because the endpoint exists, accepts POST JSON, and the app can connect to attacker-controlled MCP server configuration.
- Backup vector:
- Continue port 80 web enumeration if MCPJam exploitation fails; current quick-win checks show robots.txt and .git/HEAD return 404, and the visible page appears static.
- Cross-service connection:
- Port 80 mainly exposes hostname/service hints; port 6274 is the active development tooling surface and likely initial access path.
Raw flags and reusable secrets must be stored only under loot/.
Foothold and Privilege Escalation Evidence — 2026-06-06T01:33:00Z
Current completion state: COMPLETE.
Validated pre-research intel
| Item | Result | Evidence |
|---|---|---|
Port 80 redirects to devhub.htb | MATCHED | enum/http80_ip_headers.txt shows 302 with Location: http://devhub.htb/. |
| Port 6274 is MCPJam Inspector | MATCHED | nmap/6274-version.txt and enum/http6274_index.js; frontend title is MCPJam Inspector. |
| MCPJam Inspector version v1.4.2 / vulnerable line | MATCHED | Process enumeration shows npx @mcpjam/inspector@1.4.2; saved in enum/proc_interesting.txt. |
/api/mcp/connect unauthenticated RCE with attacker-controlled MCP server config | MATCHED | Benign callback proof saved in enum/http6274_connect_stdio_proof_response.json and enum/http_callback_after_stdio_proof.txt. |
Exploitation path
- POSTed a stdio MCP server config to
http://devhub.htb:6274/api/mcp/connectand confirmed command execution asmcp-devvia callback to the Pwnbox. - Triggered a reverse shell to
<TARGET>:4444; shell evidence inenum/reverse_shell_initial_capture.txtandenum/devhub_shell.log. - Ran required foothold baseline commands as
mcp-dev; outputs saved inenum/foothold_*. - Found local-only Jupyter Lab on
<TARGET>:8888running asanalyst; token saved only toloot/jupyter-token.txt. - Used the Jupyter REST/WebSocket API to run a Python kernel as
analyst; analyst outputs saved inenum/analyst_*. - Captured
user.txtfrom/home/analyst/user.txt; raw flag saved only toloot/user.txtand verified as 32-character hex.
Privilege escalation path
- As
analyst, read/home/analyst/.opsmcp_keyand/opt/opsmcp/server.py; secret material saved only toloot/. - Source review showed root-run OpsMCP on
<TARGET>:5000with hidden toolops._admin_dump; redacted source evidence inenum/opsmcp_source_redacted_range.txt. - Authenticated to OpsMCP with the analyst API key and called
ops._admin_dumpwith targetssh_keys, retrieving root SSH material intoloot/opsmcp-emergency-ssh_keys.json. - Extracted the root key to
loot/root_id_rsa, SSHed as root, and saved root baseline inenum/root_baseline.txt. - Captured
root.txtfrom/root/root.txt; raw flag saved only toloot/root.txtand verified as 32-character hex.
Key evidence files
- Recon:
nmap/initial.txt,nmap/allports.txt,nmap/6274-version.txt. - Web/API:
enum/http80_ip_headers.txt,enum/http6274_api_strings.txt,enum/http6274_fetch_contexts.txt. - Foothold:
enum/http_callback_after_stdio_proof.txt,enum/reverse_shell_initial_capture.txt,enum/foothold_*. - Lateral/privesc:
enum/jupyter_,enum/analyst_,enum/opsmcp_source_redacted_range.txt,enum/root_baseline.txt. - Flags/secrets:
loot/only.