Abuse rpcbind

Diesen Beitrag schrieb ich 6 Jahre und 11 Monate zuvor; die nachfolgenden Ausführungen müssen heute weder genau so nach wie vor funktionieren, noch meiner heutigen Meinung entsprechen. Behalte das beim Lesen (und vor allem: beim Nachmachen!) bitte stets im Hinterkopf.

Geschätzte Lesezeit: 3 Minuten

Es war ein relativ frisch installiertes Debian-System: dummerweise lief der Dienst rpcbind, per Default auf Port 111 TCP und UDP – und er lässt sich für DDoS-Attacken heranziehen.

Genau genommen ist das nicht einmal etwas Neues – dieser Artikel hier ist von August 2015. Doch wie es halt so ist: hat man ein Thema auf dem Radar, ist alles okay. Hat man es nicht, meldet sich irgendwann der äußerst unerfreute Hoster, weil ein Host mit voller Bandbreite irgendwelche Ziele anzugreifen versucht – und das ist unschön, immer. Deshalb notiere ich es hier, für euch und die Nachwelt – auch auf die Gefahr hin, dass ihr das alle schon wisst und mich auslacht ;-) rpcbind ist nicht auf jedem System erforderlich – aber er kommt zwingend ins Spiel, wenn beispielsweise GlusterFS- oder auch NFS-Shares eingebunden werden sollen. Auf Hosts, die nichts dergleichen tun wollen, würde ich den Dienst einfach abschalten und per systemctl disable rpcbind rauswerfen. Doch alle anderen können nicht ohne, die manpage fasst das folgendermaßen zusammen:

DESCRIPTION The rpcbind utility is a server that converts RPC program numbers into universal addresses. It must be running on the host to be able to make RPC calls on a server on that machine.

Hier die Ausgabe eines Servers, auf dem der Dienst läuft as it is, also mit Default-Konfiguration; auf privilegiertem Port ballert er TCP und UDP raus, und das (zwingend!) als root… Puh.

$ rpcinfo
   program version netid     address                service    owner
    100000    4    tcp6      ::.0.111               portmapper superuser
    100000    3    tcp6      ::.0.111               portmapper superuser
    100000    4    udp6      ::.0.111               portmapper superuser
    100000    3    udp6      ::.0.111               portmapper superuser
    100000    4    tcp       0.0.0.0.0.111          portmapper superuser
    100000    3    tcp       0.0.0.0.0.111          portmapper superuser
    100000    2    tcp       0.0.0.0.0.111          portmapper superuser
    100000    4    udp       0.0.0.0.0.111          portmapper superuser
    100000    3    udp       0.0.0.0.0.111          portmapper superuser
    100000    2    udp       0.0.0.0.0.111          portmapper superuser
    100000    4    local     /run/rpcbind.sock      portmapper superuser
    100000    3    local     /run/rpcbind.sock      portmapper superuser

Nicht nur von localhost aus lässt sich diese Information abrufen – jeder Rechner im (Inter)Netz kann versuchen, sie sich zu krallen:

# rpcinfo -p a.b.c.d
   program vers proto   port  service
    100000    4   tcp    111  portmapper
    100000    3   tcp    111  portmapper
    100000    2   tcp    111  portmapper
    100000    4   udp    111  portmapper
    100000    3   udp    111  portmapper
    100000    2   udp    111  portmapper

Es gibt sicher viele Wege, das zu umgehen – der Trick ist halt einfach, dass man es irgendwie machen muss. Eine Möglichkeit wäre, den Zugriff auf rpcbind in /etc/hosts.deny generell zu verbieten…

rpcbind: ALL

… und über die /etc/hosts.allow ausschließlich für localhost und den GlusterFS/ NFS/ whatever-Server zu erlauben:

rpcbind: ip.of.ser.ver
rpcbind: 127.0.0.1

Versucht man nun von extern die rpcinfo-Abfrage erneut, erhält man eine Fehlermeldung – die Information kann nicht länger abgerufen werden. Die Shares hingegen funktionieren weiterhin wie gewünscht.

$ rpcinfo -p a.b.c.d
rpcinfo: can't contact portmapper: RPC: Authentication error; why = Client credential too weak

DDoS rpcbind Grafana Werft mal einen Blick in die /etc/init.d/rpcbind – der Dienst würde /etc/default/rpcbind bzw. /etc/rpcbind.conf auswerten, wenn es sie denn gäbe. In der Default-Installation existieren jedoch beide nicht. Denkbar wäre beispielsweise eine /etc/rpcbind.conf mit folgendem Inhalt – UDP wird hier auf localhost beschränkt, das muss die eigene Umgebung natürlich hergeben.

OPTIONS=""

# Cause rpcbind to do a "warm start" by read a state file when rpcbind starts up.
# The state file is created when rpcbind terminates.
# OPTIONS="-w "

# Specify specific IP addresses to bind to for UDP requests using -h
# The following line restricts rpcbind to localhost only for UDP requests
OPTIONS="${OPTIONS} -h 127.0.0.1"

# Turn on libwrap connection logging.
# OPTIONS="${OPTIONS} -l"

Icinga2 eth0 check Grafana Betrachtet ihr die Screenshots, so dürftet ihr sehr leicht erkennen können, seit wann dass geänderte Regelwerk greift… Tja, doofe Sache, das. Ungeklärter terrabyteweiter Traffic, vorzugsweise nach China, lässt sich so jedoch ganz gut erklären – in Abhängigkeit davon, wie lange die Sache unbemerkt blieb. Und gerade heute gab es auf Debian-Systemen ein rpcbind-Update, da es auch möglich war, einem Ziel das RAM (im schlimmsten Falle bis zum Zusammenbruch des Systems hin) vollzuballern – da scheint insgesamt was im Gange. Der nächste Schritt war relativ klar: endlich mal einen Check ins Monitoring einbauen, der den Traffic auf dem Netzwerkport im Auge behält und gegebenenfalls Alarm schlägt… Mit check_snmp_int und über den Director ist das keine Zauberei, eher Fleißarbeit, und ich bin jetzt etwas genervt, dass ich das nicht schon früher gemacht habe – auf meiner (ellenlangen und ständig wachsenden) ToDo-Liste stand es nämlich schon lange…

Also schaut mal, welche eurer Kisten ebenfalls betroffen sind – eine kleine Firewall-Regel ist schnell eingerichtet und erspart euch eine Menge Rennerei ;)

„We recommend disabling Portmapper along with NFS, NIS and all other RPC services across the open Internet as a primary option. In situations where the services must remain live, firewalling which IP addresses can reach said services and, subsequently, switching to TCP-only are mitigations to avoid becoming an unknowing participant in DDoS attacks in the future.“ – Read whole article here.

Alle Bilder dieser Seite: © Marianne Spiller – Alle Rechte vorbehalten
Hintergrundbild: 1378x 531px, Bild genauer anschauen – © Marianne Spiller – Alle Rechte vorbehalten

Eure Gedanken zu „Abuse rpcbind“

Ich freue mich über jeden Kommentar, es sei denn, er ist blöd. Deshalb behalte ich mir auch vor, die richtig blöden kurzerhand wieder zu löschen. Die Kommentarfunktion ist über GitHub realisiert, weshalb ihr euch zunächst dort einloggen und „utterances“ bestätigen müsst. Die Kommentare selbst werden im Issue-Tracker und mit dem Label „✨💬✨ comment“ erfasst – jeder Blogartikel ist ein eigenes Issue. Über GitHub könnt ihr eure Kommentare somit jederzeit bearbeiten oder löschen.