Connected
<secret redacted> reached. The live chain was: 1. Enumerate the validated FreePBX <TARGET> admin surface at /admin/. 2. Prove that same-origin browser headers remove the generic AJAX referrer
Scenario
Connected attack path
reached. The live chain was: 1. Enumerate the validated FreePBX admin surface at /admin/. 2. Prove that same-origin browser headers remove the generic AJAX referrer
Objective
Machine walkthrough focused on Machines evidence, validation, and reusable operator lessons.
Walkthrough flow
FreePBX with the commercial endpoint module exposed...
A clean request to...
The matched CVE chain provided transient command...
The asterisk foothold could directly read...
Restore the live transport path: regain Pwnbox SSH or...
Source coverage
High source coverage
Status: complete. This article is generated from 7 sanitized Markdown sources and keeps raw flags, credentials, keys, cookies, and reusable secrets out of the rendered blog.
High confidence: the page is reconstructed from a primary walkthrough plus multiple supporting notes or evidence sources. Treat the chain as source-backed, while still checking the listed source files for sensitive values.
- <TARGET>-Connected/walkthrough.md
- HTB/<TARGET>-Connected/notes.md
- HTB/<TARGET>-Connected/attack-map.md
- HTB/<TARGET>-Connected/session-resume.md
- HTB/<TARGET>-Connected/dead-ends.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/machine__<TARGET>-Connected__attack-map.md.53c4e0a462.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/machine__<TARGET>-Connected__memory-summary.md.5139810e01.md
Technical Walkthrough
Connected Walkthrough
Raw flags and reusable secrets are stored only under loot/.
Summary
<secret redacted> reached.
The live chain was:
- Enumerate the validated FreePBX <TARGET> admin surface at
/admin/. - Prove that same-origin browser headers remove the generic AJAX referrer gate.
- Match the exact <secret redacted> route family from public CVE research against the live host:
- module=FreePBX\\modules\\endpoint\\ajax
- command=model
- template=x&model=model&brand=x
- Use the matched endpoint chain to gain transient command execution as
asterisk. - Read
/home/asterisk/user.txtfrom that foothold and store it underloot/user.txt. - Remove the transient webshell and stop before privilege escalation.
Evidence
- State:
target-state.json - Notes:
notes.md - CVE route validation:
enum/endpoint-watchtowr-shape-probe.txt - Exploit run:
exploits/watchtowr-run.txt - Foothold baseline:
loot/webshell-baseline.txt,loot/post-foothold-baseline.txt - User flag:
loot/user.txt
Stop Point
This run intentionally stops at <secret redacted> per operator instruction. Root/privesc work was not started.
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 | Connected |
| Difficulty | Easy |
| OS | Linux |
| Active target IP | <TARGET> |
| Hostname/domain | connected.htb |
| Pwnbox | <TARGET> |
| Attacker/VPN IP | <TARGET> |
| Local workspace | <local workspace><TARGET>-Connected |
| Pwnbox workspace | ~/htb/<TARGET>-Connected |
| Started | 2026-06-08T11:40:26Z |
Evidence Ledger
| Time UTC | Phase | Command/Action | Output file | Finding | Confidence | Next action |
|---|---|---|---|---|---|---|
| 2026-06-08T11:40:26Z | setup | htbctl init | target-state.json | Workspace initialized by deterministic harness. | High | Validate route and start baseline recon. |
| 2026-06-08T11:40:26Z | setup | Fresh Connected workspace created for new target IP | target-state.json, session-resume.md, research.md, manual-runbook.md | New active IP is <TARGET>; prior <TARGET> workspace is stale context only. | High | Run Pwnbox preflight and minimal baseline from Pwnbox. |
| 2026-06-08T11:40:26Z | research | Official metadata boundary recorded | research.md | Use official metadata and service/version research only; machine-specific writeups are spoiler material while the box is active/seasonal. | High | Let live enumeration drive the next research queries. |
| 2026-06-08T11:55:24Z | <secret redacted> | htbctl run --remote 'date -u; pwd; echo HOME=$HOME; id; ip -br addr; ip route get <TARGET>' | enum/pwnbox-preflight.txt | Pwnbox SSH is working; attacker VPN IP is <TARGET>; tun0 is present; route to <TARGET> is via <TARGET> on tun0. | High | Run minimal reachability and common-port baseline. |
| 2026-06-08T11:55:45Z | <secret redacted> | htbctl run --remote 'ping -c 3 <TARGET>; sudo nmap -Pn -n --reason -p 22,80,443,8080,8000,3000,5000 -oA nmap/common <TARGET>' | enum/ping-common.txt | Target responds to ICMP; common-port scan shows 22/tcp, 80/tcp, and 443/tcp open, with higher web-adjacent ports filtered. | High | Run full TCP to confirm the exposed surface. |
| 2026-06-08T11:56:32Z | <secret redacted> | htbctl run --remote 'sudo nmap -Pn -n -T4 --min-rate 5000 -p<redacted> -oA nmap/allports <TARGET> && ...' | nmap/allports-driver.txt | Full TCP agrees with the common-port view: only 22, 80, and 443 are open. | High | Run service/version scan against the confirmed open set. |
| 2026-06-08T11:57:30Z | <secret redacted> | htbctl run --remote 'sudo nmap -Pn -n -sCV -O -p 22,80,443 <TARGET>' | nmap/services.txt | SSH is OpenSSH 7.4; web stack is Apache 2.4.6 on CentOS with PHP 7.4.16; HTTP redirects to http://connected.htb/; HTTPS answers on the same Apache stack and returned a 404 when Nmap requested config.php; TLS cert CN is pbxconnect. | High | Stop at synthesis, add connected.htb to Pwnbox hosts on the next pass, and start focused web enumeration. |
| 2026-06-08T12:16:22Z | <secret redacted> | `htbctl run --remote 'printf "<TARGET> connected.htb pbxconnect\n" | sudo tee -a /etc/hosts && ...'` | enum/hosts-add-connected.txt | Pwnbox host mapping for connected.htb and pbxconnect is active. | High |
| 2026-06-08T12:16:36Z | <secret redacted> | htbctl run --remote '{ curl ... }' | enum/web-base-curl.txt | http://<TARGET>/ and http://pbxconnect/ canonically redirect to http://connected.htb/; http://connected.htb/ and all HTTPS variants return 302 Location: /admin. | High | Probe /admin and known web paths before any fuzzing. |
| 2026-06-08T12:16:54Z | <secret redacted> | htbctl run --remote 'for path in / /robots.txt /config.php /index.php /login /admin /api ...' | enum/web-known-paths.txt | /robots.txt is the stock FreePBX robots file; /config.php, /login, /api, /assets/, /js/, and /css/ are direct 404s; /admin is the only clear app branch. | High | Pull /admin/ source and identify the product before deciding on research or fuzzing. |
| 2026-06-08T12:17:15Z | <secret redacted> | htbctl run --remote 'curl -k -sS -i -L https://connected.htb/admin/ ...' | enum/admin-source.txt | /admin/ is a FreePBX administration login page. The source explicitly identifies FreePBX <TARGET>, references /ucp, cxpanel, and config.php?display=cxpanel_menu, and leaks a live PHP session value in both a cookie and page DOM; the local artifact was sanitized after capture. | High | Stop and synthesize again around the validated FreePBX surface before product research or exploitation. |
| 2026-06-08T12:41:56Z | <secret redacted> | htbctl run --remote 'for path in /ucp /ucp/ /ucp/index.php ... /admin/modules/userman/... /admin/modules/endpoint/... ' | enum/freepbx-surface-validation.txt | /ucp is a real routed surface: /ucp redirects to /ucp/, but /ucp/ and /ucp/index.php hang for at least 10 seconds. The userman asset /admin/modules/userman/assets/js/adminPwdExpReminder.js is directly readable, proving that module is present. Endpoint module presence is also supported because /admin/modules/endpoint/module.xml exists behind a 403, while /admin/modules/endpointman/module.xml is a 404. | High | Recheck the hanging UCP/cxpanel behavior with a longer timeout and then reassess the exploit gate. |
| 2026-06-08T12:44:43Z | <secret redacted> | htbctl run --remote 'curl -k -sS -i -L --max-time 30 https://connected.htb/ucp/ ...' | enum/ucp-cxpanel-probe.txt | /ucp/ and /ucp/index.php still time out after 30 seconds with zero bytes, while /admin/cxpanel/ returns a real application message: Offline system! Resolving timed out after 5516 milliseconds. | High | Record the product-gate evaluator: both branches are real, but the next auth/exploit step still needs a more concrete, source-backed action. |
| 2026-06-08T12:46:36Z | evaluator | htbctl evaluate --before exploit --decision "Validate first" | enum/evaluator-exploit-20260608T124636Z.txt | Live evidence is sufficient to validate the userman and endpoint branches, but not yet sufficient to justify a PoC or auth attempt without a tighter next step. | High | Stop at synthesis and choose the next bounded product-specific branch. |
| 2026-06-08T13:02:16Z | <secret redacted> | `htbctl run --remote 'curl -k -sS -i -X POST https://connected.htb/admin/ajax.php?module=userman&command=<password redacted> ... loginpanel=admin | ucp ...'` | enum/userman-ajax-controls.txt | All harmless userman AJAX controls returned the same 403 JSON error, ajaxRequest declined - Referrer, for both loginpanel=admin and loginpanel=ucp, with both empty and bogus placeholders. | High |
| 2026-06-08T13:02:49Z | <secret redacted> | htbctl run --remote 'curl -k -sS -i https://connected.htb/admin/ajax.php?module=endpoint... && ... modular.php ...' | enum/endpoint-route-controls.txt | Endpoint controls are not uniform: module=endpoint&command= reaches backend parsing and throws a structured Ajax.class.php exception, while other endpoint probes fall back to known 403 control responses. | High | Treat endpoint as the stronger next branch, but still require exact source-backed request-shape validation before any PoC. |
| 2026-06-08T12:58:46Z | evaluator | htbctl evaluate --before exploit --decision "Validate first" | enum/evaluator-exploit-20260608T125846Z.txt | userman remains blocked behind a referrer gate and does not justify bounded auth testing; endpoint now shows differentiated backend behavior but still lacks a concrete exploit/auth shape. | High | Stop at synthesis again and choose between source-backed endpoint request-shape validation or a tighter harmless userman control that proves the missing referrer/session requirement. |
| 2026-06-08T13:48:59Z | <secret redacted> | Browser-shaped AJAX controls with same-origin headers | enum/ajax-referrer-shape-probe.txt | The missing request shape was just browser context: userman bogus credentials now reach real auth logic and return Invalid Login Credentials, while endpoint command=model switches from generic referrer denial to 401 Not Authenticated. | High | Reassess both branches with source-backed credential and endpoint route evidence rather than the earlier generic 403 controls. |
| 2026-06-08T13:51:15Z | evaluator | htbctl evaluate --before exploit --decision Proceed | enum/evaluator-exploit-20260608T135115Z.txt | The exact <secret redacted> route family is validated enough to justify one bounded exploit step. | High | Match the public/NVD-referenced endpoint route shape harmlessly, then use the smallest reliable foothold path. |
| 2026-06-08T13:55:07Z | <secret redacted> | Clean CVE route validation using module=FreePBX\\modules\\endpoint\\ajax&command=model&template=x&model=model&brand=x | enum/endpoint-watchtowr-shape-probe.txt | The exact endpoint exploit route is live: the clean request reaches /admin/modules/endpoint/views/model.php and throws an application exception, while a bad module path dies earlier in BMO module loading. | High | Use the matched CVE chain for a bounded foothold. |
| 2026-06-08T13:56:12Z | EXPLOIT | Public CVE technique script staged on Pwnbox and executed against https://connected.htb/ | exploits/watchtowr-run.txt | The endpoint CVE chain is exploitable and dropped transient command execution via a webshell path under /var/www/html/. | High | Use the short-lived foothold for Linux baseline and user flag capture, then clean the shell. |
| 2026-06-08T13:56:49Z | FOOTHOLD | Command execution as asterisk; home and flag probe | loot/webshell-baseline.txt | Foothold runs as uid=999(asterisk), and /home/asterisk/user.txt is group-readable by asterisk. | High | Read user.txt, run a fuller baseline, then remove the webshell and stop at <secret redacted>. |
| 2026-06-08T13:56:49Z | <secret redacted> | Captured user flag from live target | loot/user.txt | user.txt captured from the live target and stored under loot/ only. | High | Update state to <secret redacted> and stop before privesc per operator instruction. |
| 2026-06-08T13:57:02Z | FOOTHOLD | Post-foothold Linux baseline and webshell cleanup | loot/post-foothold-baseline.txt, loot/webshell-cleanup-2.txt, loot/webshell-post-clean-status.txt | Post-foothold baseline confirms the shell runs as asterisk on <TARGET> with localhost-only MongoDB/MySQL/Redis/AMI services; the transient webshell was removed and now returns 404. | High | Preserve <secret redacted> state and stop before root work. |
| 2026-06-08T21:37:23Z | BLOCKER | Local transport recheck: route -n get <TARGET>, direct HTTPS probe, ping/nc/ssh to Pwnbox <TARGET> | enum/local-route-recheck.txt, enum/pwnbox-transport-recheck.txt | Coordinator still has no direct HTB route, and the current Pwnbox is unreachable over ICMP and TCP/22. Live root work is blocked by transport, not by exploit selection. | High | Resume from the root branch once Pwnbox access returns or the active Pwnbox details change. |
| 2026-06-08T21:37:23Z | PRIVESC | Local evidence review of prior root branches | enum/privesc-amportal-deep-check.txt, enum/privesc-cve-2025-67722-validation.txt, enum/privesc-amportal-paths-live.txt, enum/privesc-trigger-postfire.txt | amportal remains a valid secondary branch but its root-side trigger is weaker after the bounded failure; the strongest next root lead is the root-owned localhost aiovega service on <TARGET>:4000. | High | Re-establish asterisk foothold and inspect aiovega.web before revisiting amportal. |
Synthesis
Current completion state: <secret redacted>.
Validated service surface:
22/tcp: OpenSSH 7.480/tcp: Apache httpd 2.4.6 on CentOS, redirecting tohttp://connected.htb/443/tcp: Apache httpd 2.4.6 on CentOS, TLS certCN=pbxconnect,http-robots.txtshows/disallowed, Nmap observed404 Not Foundfor a request toconfig.php/admin/over HTTPS is aFreePBX Administrationlogin page with version stringFreePBX <TARGET>/ucp/is not a dead path; it is a real routed surface that hangs for at least 30 seconds/admin/cxpanel/is also real and returns an application-level timeout messageusermanis live-proven by the accessible asset/admin/modules/userman/assets/js/adminPwdExpReminder.jsendpointis likely installed because/admin/modules/endpoint/module.xmlexists but is access-controlled (403)- Harmless
usermanAJAX controls are uniform and blocked byajaxRequest declined - Referrer, even whenloginpanelchanges betweenadminanducp - Harmless endpoint controls are differentiated:
module=endpoint&command=reaches the backend parser and returns a structuredAjax.class.phpexception instead of the usual generic403 - Browser-shaped headers remove the front-end gate:
usermanandendpointboth reach real auth/module logic when the request looks like a same-origin AJAX call - The exact <secret redacted> route family
module=FreePBX\\modules\\endpoint\\ajax&command=model...is live and reaches/admin/modules/endpoint/views/model.php - Bounded exploitation of that route yielded transient command execution as
asterisk /home/asterisk/user.txtis readable from theasteriskfoothold and has been captured underloot/user.txt
Validated foothold chain:
- FreePBX <TARGET> with the commercial
endpointmodule exposed the exact <secret redacted> route family. - A clean request to
module=FreePBX\\modules\\endpoint\\ajax&command=model&template=x&model=model&brand=xproved the vulnerable path against the live host. - The matched CVE chain provided transient command execution as
asterisk. - The
asteriskfoothold could directly read/home/asterisk/user.txt, which completed the<secret redacted>objective.
If resumed beyond <secret redacted>:
- Re-establish the transient endpoint foothold if needed.
- Start local privesc from the
asteriskcontext, prioritizing localhost-only services (3306,27017,6379,5038) and system/service config review. - Do not treat
<secret redacted>asCOMPLETE; root work has not been started in this run.
Raw flags and reusable secrets must be stored only under loot/.
Attack Map
Completion State
<secret redacted>
Known Facts
| Fact | Evidence | Confidence |
|---|---|---|
Machine is Connected. | Operator scope and official HTB metadata. | High |
Current target IP is <TARGET>. | Operator scope for this run. | High |
Prior target IP <TARGET> is stale. | Previous workspace stalled on unreachable surface. | High |
| OS/difficulty are Linux / Easy. | Operator scope and official metadata. | High |
Current Pwnbox is profex0r@<TARGET>. | Operator scope. | High |
The web product is FreePBX <TARGET>. | enum/admin-source.txt | High |
The commercial endpoint module is present enough for the CVE route family to resolve. | enum/freepbx-surface-validation.txt, enum/endpoint-watchtowr-shape-probe.txt | High |
The exact <secret redacted> module path reaches endpoint/views/model.php on the live target. | enum/endpoint-watchtowr-shape-probe.txt | High |
The matched endpoint chain yielded transient command execution as asterisk. | exploits/watchtowr-run.txt, loot/webshell-baseline.txt | High |
user.txt is readable from the asterisk foothold and has been captured. | loot/user.txt, loot/webshell-baseline.txt | High |
amportal resolves freepbx_engine from /var/lib/asterisk/bin first, and that path is writable by asterisk. | enum/privesc-cve-2025-67722-validation.txt, enum/privesc-amportal-paths-live.txt | High |
The prior amportal/incrond trigger attempt did not yield a root-readable copy before the engine was restored. | enum/privesc-trigger-postfire.txt, enum/evaluator-privesc-20260608T142730Z.txt, telemetry.jsonl | Medium |
A root-owned localhost service exists on <TARGET>:4000: python3.6 -m aiohttp.web aiovega.web:app_factory. | enum/privesc-amportal-deep-check.txt | High |
| Coordinator-to-Pwnbox transport is currently down, and the local Mac still has no HTB route. | enum/pwnbox-transport-recheck.txt, enum/local-route-recheck.txt | High |
Ranked Hypotheses
| Rank | Path | Evidence | Missing proof | Cheapest validation | Status |
|---|---|---|---|---|---|
| 1 | Endpoint <secret redacted> to transient asterisk code execution. | enum/endpoint-watchtowr-shape-probe.txt, exploits/watchtowr-run.txt, loot/webshell-baseline.txt | None for <secret redacted>; foothold is proven. | Completed. | Proven |
| 2 | Read user.txt directly from the asterisk foothold. | /home/asterisk/user.txt is group-readable by asterisk. | None; flag captured. | Completed. | Proven |
| 3 | Exploit or abuse the root-owned localhost aiovega proxy service on <TARGET>:4000. | enum/privesc-amportal-deep-check.txt proves the process is root-owned and bound to loopback. | aiovega.web request shape and whether it exposes SSRF, file, or command side effects. | Re-establish asterisk foothold and dump/import aiovega.web, then probe <TARGET>:4000 with the discovered parameters. | Priority root branch |
| 4 | Revisit <secret redacted> / amportal only if a stronger root-run trigger is proven. | enum/privesc-cve-2025-67722-validation.txt, enum/privesc-amportal-paths-live.txt, enum/privesc-trigger-postfire.txt, telemetry.jsonl | A reliable root-side trigger that actually executes the planted wrapper. | Re-establish foothold, prove the root trigger path end to end without mutating the engine first, then reassess. | Weakened after bounded failure |
| 5 | Local privilege escalation from asterisk using other localhost-only services or configs. | loot/post-foothold-baseline.txt shows local MongoDB, MySQL, Redis, and AMI listeners plus the asterisk shell. | A concrete root transition. | Re-establish foothold and validate service-specific abuse only if aiovega and amportal close. | Active fallback |
| 6 | UCP/userman fallback. | userman is present and browser-shaped auth checks work. | Source-backed valid account on this host. | Only revisit if endpoint chain becomes unavailable or if user explicitly wants the alternate path documented further. | Deprioritized |
Decision Rule
The user objective is now <secret redacted>. Continue privesc only after re-establishing asterisk access and recording a privesc evaluator. Prefer the root-owned aiovega localhost service first; keep amportal as a secondary branch unless a stronger trigger is proven.
Session Resume
Last updated: 2026-06-08T21:37:23Z
Current Access
- Completion state:
<secret redacted>. - Machine:
Connected. - Category/status: seasonal active HTB machine.
- Difficulty/OS: Easy / Linux.
- Active target IP:
<TARGET>. - Prior stale target IP:
<TARGET>. - Current local workspace:
<local workspace><TARGET>-Connected. - Stale prior workspace:
<local workspace><TARGET>-Connected. - Pwnbox:
profex0r@<TARGET>. - Pwnbox password is intentionally not stored. Use
<secret redacted>only at runtime. - Attacker/VPN IP:
<TARGET>. - Hostname/domain:
connected.htbdiscovered from the live HTTP redirect. - Route to
<TARGET>is validated viatun0. - Live service map is validated:
22/tcp,80/tcp,443/tcp. /admin/is a validated FreePBX admin login page.- Product/version anchor:
FreePBX <TARGET>. - Related exposed routes seen in source:
/ucp,cxpanel,config.php?display=cxpanel_menu. /ucp/is a real routed surface, but it hangs for at least 30 seconds with no bytes returned./admin/cxpanel/is also real and responds with an application message:Offline system! Resolving timed out after 5516 milliseconds.usermanis present, proven by a directly accessible JS asset under/admin/modules/userman/.endpointis likely installed because/admin/modules/endpoint/module.xmlexists and returns403, while/admin/modules/endpointman/module.xmlis404.- Harmless
usermanAJAX controls are uniform and blocked byajaxRequest declined - Referrerfor bothloginpanel=adminandloginpanel=ucp. - Harmless endpoint route controls are differentiated:
module=endpoint&command=reaches backend parsing and throws a structuredAjax.class.phpexception, while adjacent endpoint controls fall back to generic403responses. - Browser-shaped headers remove the front-end AJAX gate and reach real auth/module logic.
- The exact <secret redacted> route family
module=FreePBX\\modules\\endpoint\\ajax&command=model...is live and reachesendpoint/views/model.php. - The endpoint chain yielded transient command execution as
asterisk. user.txthas been captured from/home/asterisk/user.txtand stored asloot/user.txt.- The transient webshell has been removed and now returns
404. - The prior
amportal/ incrond branch was validated further:amportalresolves the first writablefreepbx_enginefrom/var/lib/asterisk/bin, but the bounded trigger attempt did not yield a readable root copy before restore. - A stronger root lead exists locally:
enum/privesc-amportal-deep-check.txtshows a root-owned loopback service,/usr/bin/python3.6 -m aiohttp.web aiovega.web:app_factory -H <TARGET> -P 4000. - Current live blocker: the coordinator cannot reach the Pwnbox (
<TARGET>) over ICMP or TCP/22, and the local Mac still has no direct route to<TARGET>.
Prior Context To Avoid Repeating
The previous Connected workspace targeted <TARGET> and stalled before service enumeration because the target had no reachable service surface:
- ping failed or returned no replies,
- common ports stayed filtered/no-response,
- full TCP produced no open ports,
- HTB UI verification was inconclusive.
Treat that as stale spawn/IP/lab-state context only. Do not reuse it as evidence for <TARGET>.
Immediate Objective
Resume from <secret redacted> to <secret redacted> once transport is restored.
Next Three Actions
- Restore the live transport path: regain Pwnbox SSH or update the active Pwnbox details if HTB reassigned it.
- Re-establish the endpoint foothold as
asterisk, then dump or inspectaiovega.webfrom the live target. - Record a new privesc evaluator before probing the root-owned localhost
aiovegaservice; fall back toamportalonly if a real root-side trigger is proven.
Stop Conditions
Stop and report instead of continuing if:
- Pwnbox SSH to
<TARGET>remains unreachable and no replacement Pwnbox details are available. - Target IP in HTB UI differs from
<TARGET>. connected.htb/pbxconnectbehavior diverges from the currently captured FreePBX admin and UCP/cxpanel surfaces.- Product-specific research claims do not match the validated FreePBX <TARGET> plus
userman/endpointevidence, or do not explain the observed referrer/parser behavior. - A public research claim cannot be validated against live target evidence.
Session Registry
| Name | Owner | Host | Command | Status | Evidence |
|---|---|---|---|---|---|
| pwnbox-ssh | coordinator | <TARGET> | htbctl run --remote plus direct ssh/scp for secret-safe exploit execution | blocked | enum/pwnbox-preflight.txt, enum/ping-common.txt, nmap/allports-driver.txt, nmap/services.txt, enum/web-base-curl.txt, enum/web-known-paths.txt, enum/admin-source.txt, enum/freepbx-surface-validation.txt, enum/ucp-cxpanel-probe.txt, enum/userman-ajax-controls.txt, enum/endpoint-route-controls.txt, enum/ajax-referrer-shape-probe.txt, enum/endpoint-watchtowr-shape-probe.txt, enum/evaluator-exploit-20260608T135115Z.txt, exploits/watchtowr-run.txt, loot/webshell-baseline.txt, loot/post-foothold-baseline.txt, enum/pwnbox-transport-recheck.txt, enum/local-route-recheck.txt |
Dead Ends
Stale Prior IP Branch
| Branch | Evidence | Reason closed | Revisit condition |
|---|---|---|---|
Treat <TARGET> findings as current Connected evidence. | <local workspace><TARGET>-Connected shows unreachable target behavior and old Pwnbox details. | Target IP has changed to <TARGET>; old reachability failures are not evidence for the new target. | Only revisit if HTB UI reassigns <TARGET> again. |
Active Dead Ends
| Branch | Evidence | Reason closed | Revisit condition |
|---|---|---|---|
Pre-header userman AJAX controls as a meaningful auth oracle. | enum/userman-ajax-controls.txt | Without browser-shaped headers, every harmless control collapsed to ajaxRequest declined - Referrer, so those early results were only front-gate behavior. | Revisit only if a future branch needs the exact same-origin request shape again. |
| Source-backed generic template username as a ready-made foothold. | loot/userman-auth-check.txt, /tmp/userman16-htb/Userman.class.php, /tmp/userman16-htb/install.php, /tmp/userman16-htb/Console/Userman.class.php | The historic userman source identified the legacy generic-template account pattern, but the bounded live credential test did not resolve that username as a valid UCP account on this host. | Revisit only if later authenticated access exposes an existing template-creator user in the database. |
Generic module=endpoint probing as the exploit path. | enum/endpoint-route-controls.txt, enum/endpoint-browser-auth-probe.txt | module=endpoint reached only auth-gated module logic; the live exploit route was the fully qualified module=FreePBX\\modules\\endpoint\\ajax path instead. | Revisit only to contrast pre-exploit controls with the proven CVE route. |
Attack Map
Completion State
COMPLETE
Known Facts
| Fact | Evidence | Confidence |
|---|---|---|
Machine is Connected. | Operator scope and official HTB metadata. | High |
Current active target IP is <TARGET>. | Operator update plus enum/pwnbox-preflight-respawn.txt. | High |
Prior stale target IPs are <TARGET> and <TARGET>. | Historical workspaces and operator update. | High |
Current Pwnbox is <<secret redacted>>@<TARGET>. | Operator update plus enum/pwnbox-preflight-respawn.txt. | High |
The new Pwnbox has tun0 and a valid route to <TARGET>. | enum/pwnbox-preflight-respawn.txt | High |
The respawn exposes 22/tcp, 80/tcp, and 443/tcp. | enum/ping-common-respawn.txt | High |
connected.htb still redirects to /admin. | enum/web-base-curl-respawn.txt | High |
The web product on the respawn is still FreePBX <TARGET>. | enum/admin-source-respawn.txt | High |
/ucp, cxpanel, and the userman asset reference are still present. | enum/admin-source-respawn.txt | High |
| The exact <secret redacted> endpoint route still resolves on the respawn. | enum/endpoint-watchtowr-shape-probe-respawn.txt | High |
The respawned foothold again lands as asterisk. | loot/webshell-baseline.txt, loot/post-foothold-baseline.txt, loot/user.txt | High |
incrond runs as root and watches /usr/local/asterisk/incron with <secret redacted>. | enum/incron-watcher-source.txt, enum/local-incron-path-check.txt | High |
sysadmin_manager passes watched-filename params into system("$hookfile $params") and does not block pipe ` | `. | enum/sysadmin-hook-sources-live.txt, enum/sysadmin-contents-pipe-manual-asterisk.txt |
| A watched filename `sysadmin.dump-iptables. | touch <secret redacted> created /<secret redacted> as root`. | enum/local-incron-filename-pipe-marker.txt |
| A watched filename `sysadmin.dump-iptables. | tar cf ROOTTAR root created /ROOTTAR` as a readable root-owned tar archive. | enum/root-tar-seed.txt |
root/root.txt was extracted from /ROOTTAR into local loot/root.txt. | loot/root.txt | High |
The final webshell file was removed and the old URL returns 404 Not Found. | loot/webshell-post-clean-status.txt, enum/webshell-body-after-cleanup.txt | High |
asterisk.cron_jobs has zero remaining watchTowr rows. | enum/cron-jobs-cleanup-check.txt | High |
Ranked Hypotheses
| Rank | Path | Evidence | Missing proof | Cheapest validation | Status |
|---|---|---|---|---|---|
| 1 | Reuse the validated endpoint <secret redacted> chain to regain transient asterisk execution on <TARGET>. | enum/endpoint-watchtowr-shape-probe-respawn.txt, enum/admin-source-respawn.txt, enum/ping-common-respawn.txt | Actual foothold and recaptured user.txt on the respawn. | Run the same public CVE chain from the new Pwnbox and confirm id; hostname; pwd as asterisk. | Closed - succeeded |
| 2 | Abuse the root-side sysadmin_manager watcher through watched-filename params that include an unfiltered shell pipe. | enum/incron-watcher-source.txt, enum/sysadmin-hook-sources-live.txt, enum/sysadmin-contents-pipe-manual-asterisk.txt, enum/local-incron-filename-pipe-marker.txt | A safe copy-out form that creates a readable root-owned artifact from /root. | Use a single-command payload ` | tar cf ROOTTAR root, then read root/root.txt from the archive through the asterisk` foothold. |
| 3 | If the pipe injection failed, revisit the dnsmasq/sysadmin mutation branch for a copy-out primitive. | enum/sysadmin-selected-hooks.txt, enum/dnsmasq-hook-rootwatch-current-post.txt | Proof that a root-side restart path can execute a readable copy-out rather than only mutate permissions. | Only revisit on a fresh respawn if the stronger filename-pipe branch no longer works. | Closed - superseded |
| 4 | Revisit aiovega, amportal, or localhost services only if the root-side filename injection disappears on a later respawn. | Historical workspace plus local source-backed root hook evidence | Fresh live proof on the active respawn that the stronger branch is gone. | Keep as fallback only on future respawns. | Closed - unnecessary |
Decision Rule
The current target is the respawned <TARGET> instance. Historical work from <TARGET> remained advisory only until revalidated. The final active chain on <TARGET> was:
- Revalidate FreePBX endpoint route anchors.
- Reuse the endpoint CVE to regain transient
asteriskexecution. - Prove the root-side
sysadmin_managerwatched-filename pipe injection with a harmless marker. - Use the same root-side filename pipeline to create
/ROOTTARfrom/root. - Read
root/root.txtfrom that archive intoloot/root.txt. - Remove
/ROOTTARand validation artifacts. - Verify there are no remaining watchTowr cron rows and remove the active webshell.
Memory Summary
Connected (<TARGET> respawn) reached COMPLETE by revalidating the FreePBX <TARGET> endpoint CVE foothold and then pivoting to a stronger local privesc than the earlier amportal/dnsmasq ideas. The durable lesson is that /usr/bin/sysadmin_manager on this image concatenates watched-filename params into system("$hookfile $params") while missing pipe |, and root-owned incrond watches /usr/local/asterisk/incron with <secret redacted>. A harmless watched filename proved root-side command execution, and a watched filename |tar cf ROOTTAR root produced a readable root-owned tar archive that allowed root/root.txt recovery through the existing asterisk foothold. Cleanup mattered: remove /ROOTTAR and validation markers, confirm no leftover watchTowr cron rows, delete the active webshell, and verify the old URL returns 404.