Skip to content

Finger User Enumeration

5 min read Created Jan 3, 2026 Last updated Mar 29, 2026

Finger User Enumeration

Finger on port 79 leaks detailed user information on older Unix/Linux systems. You find it running on Solaris, AIX, legacy Linux boxes, and sometimes misconfigured modern systems. Valid responses confirm usernames and expose GECOS fields, home directories, shells, last logins, and idle times. The GECOS field often contains the user's full name, office location, phone number, and other contact details. Invalid users return a short "not known" error or an empty response, which lets you enumerate accounts one by one.

Single User Query

Target a specific username to confirm whether the account exists:

  • Single User Query
  • List All Users
  • Manual Connection
  • Automated Username Validation
  • Pentestmonkey Finger Enum
  • Nmap Finger Probes
┌──(kali㉿kali)-[~]
└─$ finger $USERNAME@$TARGET_IP

A valid hit shows Login, Name, Directory, Shell, last login time, and sometimes office or phone number from the GECOS field. The home directory path reveals the naming convention used on the system. The shell field confirms the account is active and not locked. "Not known" responses vary by daemon: some say "no such user", others return nothing at all. Test against a known-valid username first to confirm which response means success on this target.

Common defaults to test:

┌──(kali㉿kali)-[~]
└─$ finger root@$TARGET_IP
┌──(kali㉿kali)-[~]
└─$ finger admin@$TARGET_IP
┌──(kali㉿kali)-[~]
└─$ finger test@$TARGET_IP
┌──(kali㉿kali)-[~]
└─$ finger guest@$TARGET_IP

Valid usernames and their GECOS full names are immediately useful. Feed confirmed usernames into password spraying and brute force on SSH, FTP, or any other exposed service. The full name in GECOS often reveals the naming convention used across the organisation: first.last, flast, or initials only. Use that pattern to generate additional usernames beyond what finger returns directly.

List All Users

Dump all accounts if the daemon allows wildcard queries:

┌──(kali㉿kali)-[~]
└─$ finger @$TARGET_IP
┌──(kali㉿kali)-[~]
└─$ finger ""@$TARGET_IP

Full user table appears on permissive servers. Not all finger daemons allow the wildcard query. Some require at least a partial username to respond. Others log the empty query and may alert defenders. The grep filter pulls the key fields so you do not miss accounts buried in verbose output:

┌──(kali㉿kali)-[~]
└─$ finger @$TARGET_IP | grep -E "Login|Name|Directory|Shell"

Naming conventions extracted here guide username generation for all other services on the target. An active account with a recent login is higher value than one idle for months. Idle accounts are still worth testing: they often carry weak or default passwords and generate fewer monitoring alerts.

Manual Connection

Raw query for banner or leakage:

┌──(kali㉿kali)-[~]
└─$ nc $TARGET_IP 79

Type a username and press enter. The daemon reads one line and returns its output. Some daemons accept a carriage return alone and dump all logged-in users. Others interpret an empty query as a list-all request. The raw connection also exposes the daemon banner, giving you the software name and version for CVE matching. Send an empty line to test:

┌──(kali㉿kali)-[~]
└─$ echo "" | nc $TARGET_IP 79

The finger protocol supports forwarding queries through an intermediary host. If the target daemon allows it, this reveals internal hostnames and confirms accounts not reachable from your position directly. Most modern configurations disable forwarding, but older setups leave it enabled. Forwarding test for internal hosts:

┌──(kali㉿kali)-[~]
└─$ echo "user@internalhost" | nc $TARGET_IP 79

A successful forward confirms the internal hostname exists and that the daemon trusts the forwarding path. Use discovered internal usernames as seeds for lateral movement planning. The bash loop below is faster than manual queries when working through a large wordlist.

Automated Username Validation

Bash loop against wordlist:

for u in $(cat users.txt); do out=$(finger $u@$TARGET_IP 2>/dev/null); [ -n "$out" ] && echo "$u: $out"; done

Non-empty output flags valid users. Some daemons return a partial response even for invalid accounts, which produces false positives. The grep filter on "not known" handles those cases. Test both scripts against a known-valid and a known-invalid username before running the full wordlist. This confirms which behaviour this daemon uses and avoids building a list full of false hits.

Alternative grep filter:

for u in $(cat users.txt); do finger $u@$TARGET_IP | grep -v "not known"; done

Pentestmonkey Finger Enum

finger-user-enum.pl wraps the single-user query in a Perl script with threading support. It handles timeouts, retries, and logs all responses in a format easier to parse than raw finger output. Download it from the Pentestmonkey GitHub repository. Bulk validation:

┌──(kali㉿kali)-[~]
└─$ perl finger-user-enum.pl -U users.txt -t $TARGET_IP

The script logs each query and its full response. Extract confirmed accounts by grepping for "Login:" in the output file. Cross-reference results against usernames from other enumeration sources to build a consolidated account list. Extract valids:

┌──(kali㉿kali)-[~]
└─$ grep "Login:" finger_enum_log.txt | cut -d ' ' -f 3

The tool performs well on large lists against responsive services. Rate limiting is rarely enforced on finger daemons. If the daemon stops responding mid-scan, check whether it enforces a connection limit and restart with the remaining usernames.

Nmap Finger Probes

Service version:

┌──(kali㉿kali)-[~]
└─$ nmap -p 79 -sV $TARGET_IP

Version details guide CVE matching. Some older finger daemon versions have known buffer overflow and information disclosure vulnerabilities. Check the version string against known-vulnerable releases before moving on. User info script:

┌──(kali㉿kali)-[~]
└─$ nmap -p 79 --script finger $TARGET_IP

Nmap formats returned user fields in its structured output. If the script returns nothing, try the target hostname instead of the IP address: some daemons reject queries without a resolvable name. If the query fails silently, the daemon may be filtering by source port or access control list. Fall back to the direct nc approach or verify that port 79 is reachable from your position.

References