// HackTricks · Network Services

69 - UDP TFTP

69 - UDP TFTP

Basic Information

Trivial File Transfer Protocol (TFTP) is a small UDP-based file-transfer protocol. A client sends its initial read or write request to UDP port 69, after which the transfer uses negotiated transfer identifiers (UDP ports). TFTP provides neither user authentication nor directory listing, so server-side file permissions and path restrictions are its primary access controls.[1]

TFTP is still commonly encountered on internal networks for bootstrapping devices—including VoIP handsets—and transferring firmware, ROM images, or configuration files. Those files can reveal credentials and network topology, so test both readable and writable paths within the authorized scope.[1]

Default Port: 69/UDP

PORT   STATE SERVICE REASON
69/udp open  tftp    script-set

Enumeration

Because TFTP does not provide directory listings, Nmap’s tftp-enum script requests names from a list of common files. It is categorized as intrusive; use it only against systems you are authorized to test.[2]

nmap -n -Pn -sU -p69 -sV --script tftp-enum <IP>

The NSE script also generates Cisco-style A.B.C.X-confg candidates from the target address. Supply a target-specific list built from observed boot filenames, device models and provisioning conventions instead of relying only on its generic list.[2]

nmap -n -Pn -sU -p69 --script tftp-enum \
  --script-args tftp-enum.filelist=./tftp-files.txt <IP>

TFTP error packets distinguish conditions such as file not found (code 1), access violation (2), file already exists (6) and an unknown transfer ID (5). Treat the exact mapping as implementation-specific, but preserve responses while enumerating because a policy rejection is more informative than a timeout.[1]

The server’s first response comes from a new UDP source port, not necessarily 69. If a scanner finds port 69 but transfers time out, capture all UDP traffic to the host and check whether a firewall/NAT is dropping the negotiated flow.[1][3]

sudo tcpdump -ni any "udp and host <IP>"

Download/Upload

Use Metasploit’s transfer utility or a TFTP client to test explicitly authorized reads and writes. Uploads succeed only when the server permits writing to the requested location.[1][3]

msfconsole -q
use auxiliary/admin/tftp/tftp_transfer_util
set ACTION Download
set RHOST <IP>
set REMOTE_FILENAME <remote-file>
run

A native client is useful for sending an exact remote pathname. Always use binary (octet) mode for firmware, archives and other non-text files.[1][3]

tftp <IP>
tftp> mode binary
tftp> verbose
tftp> get <remote-file> /tmp/downloaded-file
tftp> put /tmp/local-canary <unique-remote-name>
tftp> quit

Or automate exact filenames with tftpy:

import tftpy
client = tftpy.TftpClient("192.0.2.10", 69)
client.download("filename in server", "/tmp/filename", timeout=5)
client.upload("remote-filename", "/local/path/file", timeout=5)

A failed new-file upload does not prove that the service is entirely read-only. For example, tftpd-hpa normally permits writes only to files that already exist and are publicly writable; its --create option enables creation. Test a unique new name first and, only with the system owner’s coordination, an existing disposable canary. TFTP has no delete request, so plan cleanup separately.[1][5]

If writable provisioning, boot or firmware files are found, determine which client consumes each file and whether it verifies authenticity before modifying anything. For protocol-specific pivots, see Cisco SNMP configuration copy abuse, SCCM PXE boot artifacts and bootloader testing.

Path traversal and root confinement

Do not assume a configured TFTP root is a security boundary. Test canonicalization with a harmless, known file outside the intended root using OS-appropriate separators (for example ../ versus ..\) and both relative and absolute names. The 2026 Erlang/OTP advisory is a recent example: its root_dir handling concatenated attacker-controlled filenames without preventing .. components, allowing unauthenticated reads or writes with the TFTP process privileges.[4]

tftp <IP>
tftp> mode binary
tftp> get ../../etc/hostname /tmp/tftp-hostname

A secure implementation should canonicalize the requested path and reject any result outside its export. Server-side containment such as tftpd-hpa --secure (chroot), a dedicated low-privilege account, read-only exports and network allowlisting limit the impact if validation fails.[4][5]

Shodan

  • port:69

References