Eloquia
Eloquia is a sanitized machine note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
Eloquia attack path
Eloquia is a sanitized machine note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Objective
Machine walkthrough focused on Machines evidence, validation, and reusable operator lessons.
Walkthrough flow
External scan exposed only IIS HTTP on 80 and WinRM...
HTTP redirect and vhost validation confirmed...
Eloquia used Qooqle OAuth without meaningful...
A reported article with a browser beacon caused the...
Logging in through Qooqle then granted Eloquia admin...
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>-Eloquia/walkthrough.md
- HTB/<TARGET>-Eloquia/notes.md
- HTB/<TARGET>-Eloquia/attack-map.md
- HTB/<TARGET>-Eloquia/memory-summary.md
- HTB/<TARGET>-Eloquia/session-resume.md
- HTB/<TARGET>-Eloquia/custom-exploit-notes.md
- HTB/<TARGET>-Eloquia/dead-ends.md
Technical Walkthrough
Eloquia Walkthrough
This file records the final reproducible path only after live validation. Keep speculative notes in research.md and rejected paths in dead-ends.md.
Phase 0: Setup
- Workspace initialized locally.
- Public research stored as advisory intelligence.
- Live validation matched public anchors: IIS 10.0, WinRM 5985,
eloquia.htb,qooqle.htb, Django CSRF, OAuth flow, SQL Explorer, SQLiteload_extension.
Phase 1: OAuth CSRF Admin Takeover
Created controlled Eloquia and Qooqle accounts. Eloquia's Qooqle OAuth flow used no meaningful state/PKCE protection. A reported article containing a meta-refresh plus image beacon caused the admin bot to request the Pwnbox /bait endpoint. The listener minted a fresh Qooqle authorization code and redirected the admin browser to Eloquia's callback, linking the admin Eloquia session to the attacker Qooqle account.
After the callback, logging into Eloquia through Qooqle returned HTTP 200 for /accounts/admin/.
Phase 2: SQLite RCE
Admin panel exposed SQL Explorer at /dev/sql-explorer/play/. select sqlite_version() confirmed SQLite, and load_extension() was enabled. Anonymous SMB loading failed because Windows blocked guest access, matching the expected dead end.
The intended path was admin Article banner upload: the admin form accepted DLL files and exposed the saved path under static/assets/images/blog/. Loading the uploaded DLL with:
select load_extension('static/assets/images/blog/wp2.dll');executed code as ELOQUIA\web, confirmed by writing a proof file under the web-served static path.
Phase 3: DPAPI To WinRM
Used RCE to copy Edge Login Data and Local State from the web profile. PowerShell was blocked by policy, so a native DPAPI DLL called CryptUnprotectData as web and wrote the decrypted Chromium AES key to the static path. Offline decryption of Login Data recovered a valid credential for Eloquia\Olivia.KAT, which was validated with WinRM.
User flag was copied from the live target into loot/user.txt.
Phase 4: Failure2Ban SYSTEM
WinRM enumeration showed:
HKLM\SYSTEM\CurrentControlSet\Services\Failure2Ban
ImagePath = C:\Program Files\Qooqle IPS Software\Failure2Ban - Prototype\Failure2Ban\bin\Debug\Failure2Ban.exeicacls confirmed ELOQUIA\Olivia.KAT had write permission on the SYSTEM service executable. A minimal payload copied the Administrator root flag to C:\Temp\root.txt. After staging the payload, a PowerShell overwrite loop won the service restart race. The payload executed as SYSTEM and root was copied into loot/root.txt.
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
- Platform: HackTheBox
- Machine: Eloquia
- Difficulty: Insane
- OS: Windows
- Creator: Spectra199
- Target IP: <TARGET>
- Pwnbox: <TARGET>
- Pwnbox user: profex0r
- Started: 2026-05-07 23:39:43 AEST
Operating Rules
- Public research is advisory only. Evidence requires live validation.
- Keep raw flags, reusable <password redacted>, tickets, cookies, private keys, and dumps in
loot/only. - Use Pwnbox for live testing and save command output to files.
- For state-mutating actions, snapshot current state and write rollback notes before execution.
- For Insane mode, stop at phase boundaries and update
attack-map.md,dead-ends.md,custom-exploit-notes.md, andsession-resume.md.
Evidence Ledger
| Time | Command | Output File | Finding | Confidence | Next Action |
|---|---|---|---|---|---|
| 2026-05-07 23:39 AEST | Local workspace initialization | local files | Workspace initialized for Eloquia; no local pre-research file was present, so fresh external pre-research was started. | High | Query CTF LightRAG and validate live target from Pwnbox. |
| 2026-05-07 23:43 AEST | python3 scripts/query_ctf_lightrag.py ... | enum/lightrag-start-summary.json | CTF LightRAG queried for advisory prior patterns. Returned broad methodology context; no Eloquia-specific ingested memory yet. | Medium | Use as advisory only; proceed to live validation. |
| 2026-05-07 23:45 AEST | ssh profex0r@<TARGET> | terminal output | Supplied Pwnbox timed out on SSH. Follow-up ping showed 100% packet loss. | High | Need live Pwnbox or direct HTB VPN route before target validation. |
| 2026-05-07 23:47 AEST | local route/ping/nc checks | terminal output | Local Mac has Wi-Fi and Tailscale routes only; no direct HTB target route. Ping and TCP/80 to target timed out locally. | High | Resume after Pwnbox respawn/new IP or local HTB VPN route. |
| 2026-05-08 00:51 AEST | nmap -Pn -p<redacted> --min-rate 5000 | nmap/full-tcp.*, enum/pwnbox-baseline.txt | New Pwnbox valid; target reachable; only TCP 80 and 5985 open. | High | Fingerprint services and validate research anchors. |
| 2026-05-08 00:52 AEST | nmap -sC -sV -p<redacted> | nmap/service-80-5985.* | IIS 10.0 on 80, HTTPAPI/WinRM on 5985, Windows Server CPE. | High | Add hostnames and map web apps. |
| 2026-05-08 01:15 AEST | curl host baseline | enum/http-hostname-baseline.txt | eloquia.htb and qooqle.htb both live; Django-style CSRF cookies/forms present. | High | Map OAuth flow. |
| 2026-05-08 01:22 AEST | python3 exploits/oauth_takeover.py | enum/oauth-takeover-run3-public-img.txt | OAuth CSRF takeover succeeded; target hit /bait; Qooqle login yielded admin panel access. | High | Enumerate SQL Explorer. |
| 2026-05-08 01:30 AEST | SQL Explorer probe | enum/sql-playground-test.txt | SQLite backend confirmed; load_extension() enabled. | High | Upload DLL through admin Article banner field. |
| 2026-05-08 01:42 AEST | load_extension('static/assets/images/blog/wp2.dll') | enum/sql-load-writeproof.txt | RCE confirmed as web by writing static proof file. | High | Extract Edge artifacts. |
| 2026-05-08 01:51 AEST | DPAPI/Edge extraction | enum/cmdrunner-profile-search.txt, remote loot/edge-decrypted.txt | Edge Login Data and Local State extracted; DPAPI decrypted in web context; Olivia credential recovered. | High | Validate WinRM. |
| 2026-05-08 01:52 AEST | nxc winrm ... Olivia.KAT | enum/winrm-olivia-check.txt | WinRM as Eloquia\\Olivia.KAT confirmed Pwn3d. | High | Enumerate Failure2Ban. |
| 2026-05-08 01:56 AEST | Failure2Ban ACL/race | enum/winrm-failure2ban-enum.txt, enum/winrm-f2b-overwrite-race2.txt | Olivia has write permission on SYSTEM service binary; overwrite race succeeded. | High | Poll copied root flag. |
| 2026-05-08 01:57 AEST | Root flag poll | enum/winrm-root-poll.txt, loot/root.txt | Payload executed as SYSTEM and copied root flag to readable location. | High | Finalize notes and propose sanitized memory ingestion. |
Live Access State
| Item | Value | Status |
|---|---|---|
| Target reachability | <TARGET> | Pending |
| Pwnbox SSH | <TARGET> | Unreachable from local network |
| VPN IP | Unknown | Pending |
| Hostnames | eloquia.htb, qooqle.htb | Advisory, pending validation |
| User flag | None | Not captured |
| User flag | loot/user.txt | Captured |
| Root flag | loot/root.txt | Captured |
Attack Map
Current Graph
Pwnbox
|
| pending validation
v
<TARGET>
|
+-- HTTP/80 [advisory: IIS + Eloquia web app]
| |
| +-- eloquia.htb [advisory: Django app]
| | |
| | +-- article/report/admin bot [unvalidated]
| | +-- OAuth callback/account linking [unvalidated]
| | +-- admin SQL Explorer [unvalidated]
| |
| +-- qooqle.htb [advisory: OAuth provider]
|
+-- WinRM/5985 [advisory: credential pivot]Verified Chain
Pwnbox
-> HTTP/80 IIS + Django apps
-> eloquia.htb / qooqle.htb OAuth flow
-> OAuth CSRF account linking through reported article/admin bot
-> Eloquia admin panel
-> SQL Explorer SQLite load_extension()
-> Admin Article banner upload of DLL
-> RCE as ELOQUIA\web
-> Edge Login Data + Local State DPAPI extraction
-> WinRM as ELOQUIA\Olivia.KAT
-> Failure2Ban writable SYSTEM service executable
-> service restart race overwrite
-> root flag copied to C:\Temp\root.txtHypothesis Ranking
| Rank | Path | Why It Matters | Status |
|---|---|---|---|
| 1 | OAuth CSRF/account linking to admin | Multiple sources converge on this as the initial breakthrough. | Advisory |
| 2 | SQLite load_extension() DLL RCE from admin panel | Expected route from admin web access to Windows shell as web user. | Advisory |
| 3 | Edge DPAPI saved credential extraction | Expected bridge from web shell to WinRM user. | Advisory |
| 4 | Failure2Ban service binary/race hijack | Expected SYSTEM route. | Advisory |
All four ranked hypotheses were live-validated and used.
Transition Proof Requirements
| Transition | Proof Required Before Advancing |
|---|---|
| Pre-research to exploit | 4+ validation anchors match live target. |
| Web user to admin web access | Authenticated UI shows admin-only functionality from attacker-controlled login. |
| Admin web access to RCE | Command output or callback from live target, with uploaded DLL path and SQL query logged. |
| RCE to WinRM user | Credential source identified and WinRM auth succeeds live. |
| WinRM user to SYSTEM | Service ACL/restart behavior captured before modification; SYSTEM execution confirmed. |
Memory Summary
Status: Approved and ingested into private CTF LightRAG.
Metadata
- Platform: HackTheBox
- Content type: Machine
- Name: Eloquia
- OS: Windows
- Difficulty: Insane
- Workspace:
<local workspace><TARGET>-Eloquia
Verified Chain
- External scan exposed only IIS HTTP on 80 and WinRM on 5985.
- HTTP redirect and vhost validation confirmed
eloquia.htbandqooqle.htb. - Eloquia used Qooqle OAuth without meaningful state/PKCE protection.
- A reported article with a browser beacon caused the admin bot to visit a Pwnbox listener, receive a fresh Qooqle authorization code, and hit Eloquia's OAuth callback in the admin session.
- Logging in through Qooqle then granted Eloquia admin panel access.
- SQL Explorer exposed SQLite query execution and allowed
load_extension(). - Anonymous SMB DLL loading failed because Windows blocked guest access.
- Admin Article banner upload accepted a DLL and exposed the relative path under
static/assets/images/blog/. - Loading the uploaded DLL gave RCE as
web. - Edge
Login DataandLocal Stateunder thewebprofile were extracted; a native DPAPI DLL decrypted the Chromium master key in the livewebcontext. - Offline Edge password decryption recovered a WinRM-valid user credential.
- The WinRM user had write permission on the SYSTEM
Failure2Ban.exeservice binary. - An overwrite loop won the service restart race and replaced the service binary with a minimal copy-flag payload.
Reusable Lessons
- For OAuth CSRF/admin-bot chains, make the callback server mint authorization codes on demand; short-lived codes make pre-generation unreliable.
- Treat listener hits carefully: ignore unrelated paths to avoid mistaking public crawler traffic for admin-bot success.
- Use image beacons alongside meta-refresh when article HTML injection needs reliable browser delivery.
- If SQLite UNC
load_extension()reaches SMB but Windows blocks guest access, pivot to local upload paths instead of cracking captured NetNTLM immediately. - Admin forms may have weaker file validation than public user-facing forms.
- When PowerShell is blocked by policy, native DLLs can still call DPAPI APIs directly in the target user's context.
- For Windows service restart races, run an overwrite loop and poll for payload effects rather than trying to stop/start the service without rights.
Do Not Ingest
- Raw flags
- Recovered <password redacted>
- Admin cookies
- DPAPI key material
- Browser credential database contents
Session Resume
Current Status
- Phase: Complete
- User flag: captured in
loot/user.txt - Root flag: captured in
loot/root.txt - Current access: WinRM credential for
Eloquia\Olivia.KATrecovered from Edge DPAPI and validated live - Last confirmed action: Failure2Ban executable overwrite race succeeded and SYSTEM payload copied root flag
Known Advisory Intelligence
- Expected hostnames:
eloquia.htb,qooqle.htb - Expected ports:
80/tcp,5985/tcp - Expected chain: OAuth CSRF/account takeover -> SQLite DLL RCE -> Edge DPAPI credential extraction -> WinRM -> Failure2Ban service hijack/race -> SYSTEM
Post-Solve Tasks
- Keep raw flags and recovered credentials in
loot/only. - Prepare sanitized memory summary for user approval before LightRAG ingestion.
- Do not ingest raw cookies, flags, <password redacted>, DPAPI key material, or credential dump output.
Notes
State Mutations
| Time | Target | Attribute/File | Old State | New State | Rollback |
|---|---|---|---|---|---|
| 2026-05-08 01:22 AEST | Eloquia Article | New reported article | Did not exist | OAuth callback article created for admin-bot flow | Delete created article from admin panel if cleanup is required |
| 2026-05-08 01:38 AEST | Admin Article upload | New DLL-backed article | Did not exist | DLL files uploaded under static/assets/images/blog/ for RCE | Delete created admin article/uploaded file if cleanup is required |
| 2026-05-08 01:56 AEST | Failure2Ban.exe | Service executable | Original 13 KB service binary | Replaced with minimal copy-flag payload during race window | Restore original binary from backup/source if required |
Custom Tooling
| Tool | Purpose | Inputs | Output | Status |
|---|---|---|---|---|
oauth_takeover.py | Automate Qooqle OAuth CSRF/admin-bot race | Test Eloquia/Qooqle account, listener IP/port | Admin web session cookies in loot/ | Worked |
sqlite_cmd_runner.py | One-shot command execution through SQL Explorer DLL upload/load | Command string, admin cookies | Command output written to static path and copied to loot/ | Worked |
sqlite_edgekey.c | Native DPAPI decryption of Edge Chromium master key | web user's Local State | Base64 AES key written to static path | Worked |
failure2ban_copyflag.c | Minimal SYSTEM payload | Service restart execution | Root flag copied to C:\Temp\root.txt | Worked |
Windows Payload Requirements
- SQLite extension DLL must match target architecture.
- Prefer a minimal proof payload first, then a controlled file-copy or shell payload after validation.
- Record compile command, hash, upload path, and trigger query.
- For service replacement, snapshot original binary hash, ACL, path, and service state before writing.
Dead Ends
Record abandoned paths with proof and reason so later agents do not repeat them.
| Time | Path | Evidence | Reason Rejected | Revisit Condition |
|---|