Post

DC-2 (VulnHub) — black-box penetration test, recon to root

DC-2 (VulnHub) — black-box penetration test, recon to root

My second VulnHub box, and a completely different lesson from the first. DC-1 fell because its software was ancient. DC-2 had nothing old to exploit — every step was just a weak password or a lazy config, and it only fell because all of them happened to line up. Two things stuck with me. The way in was an SSH server hiding on a strange high port that a normal scan skips straight past. And the “restricted” shell that was supposed to trap the first user let me open a text editor, which is all you need to climb right back out of it. The full engagement report is below; if you only want the highlights, they’re in the executive summary.


Engagement type: Network penetration test (black-box, single host) Tester: Self-study lab (solo) Date: 2026-08-27 Target: 192.168.56.104 (VulnHub DC-2), isolated host-only network 192.168.56.0/24 Attacker host: Kali Linux, same isolated 192.168.56.0/24 segment (DHCP-assigned) Authorization: Self-owned lab VMs on an isolated, internet-less network. No third-party systems in scope.

1. Executive summary

A single web-server host on the internal lab network was assessed with no prior knowledge and no credentials (black-box). The host was fully compromised: starting from nothing but network access, the tester recovered login credentials, used them to obtain a remote shell, and then escalated to complete administrative (root) control of the machine.

Unlike a typical “old software” compromise, no single software vulnerability was exploited here. Every step abused a weak password or a misconfiguration:

  • Two accounts used passwords that were ordinary words taken from the website’s own content, making them guessable in seconds once a wordlist was built from the site.
  • The remote-access service (SSH) was reachable with those passwords, on a non-standard port that a routine scan would miss.
  • One account was fenced into a “restricted shell” that was trivial to escape, so the fence gave a false sense of security while providing none.
  • A second account was allowed to run a common developer tool (git) as the administrator without a password, and that tool can be trivially made to launch an administrator shell.

In business terms: an anonymous attacker on this network could guess their way in and become full administrator of the server and all its data, using only free tools and no exploit code. Each individual weakness looks minor; chained together they produce total compromise.

The root cause is not obsolete software but a systemic failure of credential hygiene and least privilege — weak passwords, an ineffective shell restriction, and an over-broad sudo grant. Remediation is a set of configuration and policy fixes, not a patch cycle.

Overall risk rating: CRITICAL (full administrative compromise was achieved end-to-end).

SeverityCount
Critical0
High2
Medium2
Low0

No finding is individually Critical, yet the host was fully rooted. That gap is the lesson of this engagement: defence that relies on each weakness being “only High/Medium” fails when the weaknesses chain.

2. Scope & rules of engagement

  • In scope: the single host 192.168.56.104 on the isolated 192.168.56.0/24 network.
  • Out of scope: any other host; the internet (the lab has no route out by design).
  • Window: single session, 2026-08-27.
  • Methods allowed: full active scanning, credential brute-forcing, and exploitation (owned lab).
  • Knowledge level: black-box — the tester began with only an IP range, no credentials and no documentation.
  • Constraint honoured: all activity confined to the authorized, isolated lab; no real or third-party systems touched. Root was proven by reading the target’s marker file, not by installing any persistent backdoor. The VM can be restored from snapshot.

3. Methodology

Standard penetration-test lifecycle:

  1. Reconnaissance / host discovery — nmap -sn to locate the live host (DHCP-assigned).
  2. Scanning & enumeration — nmap -sV -sC for services; then a full-range nmap -p- after the default scan proved incomplete; wpscan to enumerate the web application.
  3. Vulnerability analysis — assessed the WordPress install for a software exploit, then pivoted (as the target’s own hints suggested) to credential attack plus local misconfiguration.
  4. Credential access — built a target-specific wordlist with cewl and brute-forced WordPress logins with wpscan.
  5. Exploitation / foothold — reused recovered credentials against SSH on the non-standard port.
  6. Post-exploitation / privilege escalation — escaped a restricted shell, moved laterally to a second local account, and abused a sudo misconfiguration to reach root.
  7. Reporting — this document.

Tools: nmap, wpscan, cewl, OpenSSH client, vi (restricted-shell escape), su, sudo, GTFOBins (technique reference), standard Linux shell utilities.

4. Findings

Severities use CVSS v3.1 base-metric reasoning. These findings are configuration and credential weaknesses, not catalogued CVEs, so every score is marked assessed — the vector is the tester’s judgement for this specific environment.

F-01 — Privilege escalation to root via misconfigured sudo (git) (HIGH)

  • CVSS: 7.8 assessed — AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
  • Affected: user jerry’s sudo policy — (root) NOPASSWD: /usr/bin/git.
  • Description: jerry may run git as root without a password. git is not a self-contained command: for long output it invokes a pager (less/more), and that pager — because git was launched via sudo — runs with root privileges. Most pagers can execute an arbitrary shell command from within themselves, so the attacker escapes the pager into a root shell. This is a classic “living-off-the-land” sudo abuse (GTFOBins git).
  • Evidence: sudo -l as jerry returned (root) NOPASSWD: /usr/bin/git. sudo git -p help config opened the pager as root; !/bin/bash from the pager prompt spawned a shell where id returned uid=0(root) gid=0(root) groups=0(root). /root/final-flag.txt was then read (captured in the figure in §5).
  • Remediation: Remove the git entry from jerry’s sudo rules. Grant sudo only to specific, non-shell-spawning commands under least privilege; never NOPASSWD on tools that can execute sub-processes (git, vi, find, less, awk, tar, …). Audit /etc/sudoers and /etc/sudoers.d/* against a known-good baseline.

F-02 — Weak, guessable credentials permitting SSH foothold (HIGH)

  • CVSS: 7.3 assessed — AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L
  • Affected: WordPress / system accounts tom and jerry; SSH service on tcp/7744.
  • Description: Both accounts used passwords that were plain words present in the website’s own page content (tom:parturient, jerry:adipiscing). A wordlist generated directly from the site with cewl recovered them almost immediately — standard wordlists (rockyou) would not have, but the site handed the attacker its own dictionary. tom’s password was additionally valid for SSH, converting a web-app credential into an interactive remote shell.
  • Evidence: cewl http://dc-2/ -w cewl.txt built the wordlist; wpscan --url http://dc-2/ -U users.txt -P cewl.txt returned valid credentials for tom and jerry; ssh tom@192.168.56.104 -p 7744 authenticated with parturient. (jerry was not permitted to log in over SSH — see the narrative.)
  • Remediation: Enforce a strong-password policy and screen against site-derived and breached wordlists. Prefer SSH key authentication and disable password authentication (PasswordAuthentication no). Add rate-limiting / lockout (fail2ban) to blunt brute-forcing. Do not reuse web-application passwords for system/SSH accounts.

F-03 — Ineffective restricted shell (rbash trivially escaped) (MEDIUM)

  • CVSS: 5.3 assessed — AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L
  • Affected: tom’s login shell — rbash (restricted bash).
  • Description: tom is confined to rbash, which blocks cd, commands containing /, PATH changes and redirection, exposing only a handful of binaries (ls, less, pwd, vi). The restriction is cosmetic: an allowed program that can spawn a sub-shell defeats it. From vi, setting the shell and invoking it drops the user into an unrestricted bash; repairing PATH then restores su, sudo, and everything else. The control provides a false sense of containment.
  • Evidence: as tom, cat/nano/vim/su/sudo/cd were blocked while ls/less/pwd/vi worked. Escape: vi → :set shell=/bin/bash → :shell, then export PATH=/usr/bin:/bin:$PATH — after which arbitrary commands ran normally.
  • Remediation: Do not rely on rbash as a security boundary. If a user must be confined, remove shell-spawning binaries from their allowed set, or use a proper mechanism (ForceCommand, a locked-down chroot/jail, or no interactive shell at all). Treat any restricted shell that exposes an editor or pager as already broken.

F-04 — WordPress username enumeration (MEDIUM)

  • CVSS: 5.3 assessed — AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
  • Affected: WordPress 4.7.10 on Apache httpd 2.4.10 (tcp/80) — author archives / REST author listing.
  • Description: The site freely disclosed valid usernames (admin, jerry, tom) through author enumeration. This is not itself a breach, but it converts the login page from an unknown-username guessing problem into a known-username password-only problem, directly enabling F-02. (One account, tom, did not surface in the same author listing but was still discoverable, showing that partial hardening does not close the gap.)
  • Evidence: wpscan --url http://dc-2/ --enumerate u,p,t listed the users and surfaced xmlrpc.php and wp-cron.php; the author-archive search independently confirmed a username.
  • Remediation: Suppress author enumeration (block ?author= redirects and the REST /wp-json/wp/v2/users listing), avoid using login names as public display names, and consider a security plugin that hides user enumeration and rate-limits xmlrpc.php.

5. Attack narrative (the chain)

  1. Discovery — nmap -sn 192.168.56.0/24 located the target at 192.168.56.104.
  2. Enumeration (initial) — nmap -sV -sC 192.168.56.104 showed a single open port, tcp/80: Apache httpd 2.4.10 (Debian) serving WordPress 4.7.10. The site redirected to the hostname dc-2, so 192.168.56.104 dc-2 was added to /etc/hosts to reach it.
  3. Web enumeration — the site content carried a hint (Flag 1) that a standard wordlist would fail and pointed at cewl. wpscan --url http://dc-2/ --enumerate u,p,t enumerated the users admin, jerry, tom (with tom behaving differently from the other two) and the endpoints xmlrpc.php / wp-cron.php. A second hint (Flag 2) advised abandoning a WordPress exploit — “take a shortcut … another entry point” — steering the engagement toward credentials and a service not yet found.
  4. Credential access — cewl http://dc-2/ -w cewl.txt scraped a target-specific wordlist from the site’s own words. wpscan --url http://dc-2/ -U users.txt -P cewl.txt recovered jerry:adipiscing and tom:parturient.
  5. Finding the real door — the default scan’s “only port 80” was treated with suspicion given Flag 2’s “another entry point.” A full-range scan, nmap -p- 192.168.56.104, revealed SSH on tcp/7744 (OpenSSH 6.7p1) — hidden on a high, non-standard port that the top-1000 default scan never touched.
  6. Foothold — ssh tom@192.168.56.104 -p 7744 authenticated with parturient. jerry’s credentials did not grant SSH access; only tom could log in.
  7. Restricted-shell escape — tom landed in rbash: cd, cat, su, sudo and any /-path command were blocked; only ls, less, pwd, vi worked. A home-directory flag (Flag 3) hinted that the path forward was to su to jerry. Using the allowed editor, vi → :set shell=/bin/bash → :shell produced an unrestricted shell; export PATH=/usr/bin:/bin:$PATH restored normal command resolution.
  8. Lateral movement — su jerry with adipiscing succeeded. jerry’s home flag (Flag 4) pointed at sudo.
  9. Privilege escalation — sudo -l showed (root) NOPASSWD: /usr/bin/git. Per GTFOBins, sudo git -p help config opened the pager as root and !/bin/bash broke out into a root shell: id → uid=0(root).
  10. Loot — read /root/final-flag.txt (a congratulatory completion banner), confirming full administrative control.

Root shell on DC-2 — the sudo git pager escape lands as root: id returns uid=0(root), androot/final-flag.txt is read.

No software exploit was used at any point. Entry was achieved by guessing site-derived passwords; root was reached by chaining a broken shell restriction, a reused/adjacent account, and an over-broad sudo grant.

6. Conclusion & prioritized remediation

DC-2 fell without a single CVE. It fell to weak credentials and least-privilege failures — the kind of findings a scanner rarely flags and a patch cycle never fixes. Each weakness, taken alone, is a High or Medium; taken together they are a straight line from anonymous network access to root.

Priority order:

  1. Immediate: remove git from jerry’s sudo rules (F-01) — this alone breaks the escalation to root. Force password resets for tom/jerry to strong, non-site-derived values (F-02).
  2. Short term: switch SSH to key-based auth, disable password login, and add fail2ban (F-02); stop relying on rbash as a boundary and confine tom properly or not at all (F-03).
  3. Ongoing: suppress WordPress user enumeration and rate-limit xmlrpc.php (F-04); audit all sudo grants against a least-privilege baseline; adopt a password policy that screens against site-derived and breached wordlists.

Defence-in-depth note: any one control done properly would have broken the chain — a strong password (no foothold), a real shell restriction (no escape), or a scoped sudo grant (no root). The compromise required all of them to be weak at once, which is exactly why layered controls matter: no single lapse should be game-over.

Appendix A — Host service inventory

PortServiceVersion
80/tcphttpApache httpd 2.4.10 (Debian) — hosting WordPress 4.7.10
7744/tcpsshOpenSSH 6.7p1 Debian (protocol 2.0); host keys: RSA, DSA, ECDSA, ED25519

Note the non-standard SSH port (7744) — invisible to a default top-1000 nmap scan and only found via nmap -p-.

Appendix B — MITRE ATT&CK mapping

StepTacticTechnique
nmap -sn, -sV -sC, -p-Reconnaissance / DiscoveryT1595 Active Scanning · T1046 Network Service Discovery
wpscan --enumerate uDiscoveryT1087 Account Discovery · T1589 Gather Victim Identity Information
cewl + wpscan -P brute forceCredential AccessT1110.001 Password Guessing · T1110 Brute Force
SSH login as tom on 7744Initial Access / Lateral MovementT1078 Valid Accounts · T1021.004 Remote Services: SSH
vi → :shell rbash escapeExecutionT1059.004 Command and Scripting Interpreter: Unix Shell
su jerryPrivilege EscalationT1078 Valid Accounts
sudo git → root shellPrivilege EscalationT1548.003 Abuse Elevation Control Mechanism: Sudo and Sudo Caching
read /root/final-flag.txtCollectionT1005 Data from Local System
This post is licensed under CC BY 4.0 by the author.