DEV Community

yutianle
yutianle

Posted on

Port 873 lists its modules before it asks who you are

Port 873 lists its modules before it asks who you are

ZoomEye returns 1,689,755 results for port="873", the TCP port the rsync daemon listens on. The daemon is a different program from the rsync client, and the difference is the point: the client is an authenticated file transfer over SSH, and the daemon is a standalone service that speaks the rsync protocol directly on the network.

The module list is the invitation

An rsync daemon is configured with modules. Each module names a path on disk and a set of options, and the daemon answers a request for the module list before it asks for a credential. That behaviour is documented in rsyncd.conf(5), and it means an unauthenticated client can enumerate the exports the way an SMB client enumerates shares.
The list is not a file disclosure on its own. It is a map. A module named backup, www, home or dbdump tells an attacker which path is worth authenticating against, and the answer to whether authentication is required is in the same configuration file.

Where the daemon is weaker than the client

Three options decide how much a module exposes. read only = true prevents writes, and it is the default for a reason. auth users plus secrets file requires a username and password for the module. hosts allow restricts the source addresses that may connect at all.
A module without those three is a directory published to anyone who can reach the port. The rsync documentation also covers use chroot and munge symlinks, which matter when a module is writable: a writable export that follows symlinks out of the module root is a path traversal primitive, and the munge symlinks option exists to blunt it.
The measurement cannot tell which of the 1,689,755 hosts is in which state. A port match is a listener, not a configuration. What it does establish is the size of the population where the question is worth asking.

A check that answers the question first

Ask the daemon for its module list, then ask a specific behaviour question about the same module:

rsync rsync://<host>/
rsync rsync://<host>/<module>/
rsync -av --dry-run rsync://<host>/<module>/ /tmp/module-listing/
Enter fullscreen mode Exit fullscreen mode

The first command is the enumeration. The second shows whether the module requires a password. The third is a dry run that reports what a read would copy without copying it, and a module that returns a tree for that command is readable without a credential.
On the defender side, the configuration is auditable with the same file the daemon reads. A module that needs to accept writes from another host should have hosts allow scoped to that host, auth users set, and a secrets file with restrictive permissions. A module that has none of those three should be reviewed against the question of who was supposed to reach it.

What the number does not say

1,689,755 is a count of hosts that answered on the port on 2026-10-25 with sub_type=all. It is not a count of open exports, and the rsync daemon is also used on internal networks where a public listener is exactly the design. The finding is the fraction of that population whose module list is readable and whose exports are writable, and that fraction requires a second measurement the index cannot make.

References

Top comments (0)