Inhaltsverzeichnis

Update auf benno-web 2.10.11 und benno-rest 2.10.9: Änderungen am REST-Zugriff über rest.php

Dieses Update schließt eine Sicherheitslücke im REST-Proxy von benno-web (FS#1506, FS#1507, FS#1508). Über https://<server>/benno/rest.php sieht jedes Konto jetzt genau die Mails, die es auch in der Weboberfläche sieht. Das gilt auch für den Abruf einzelner Mails und Anhänge.

Einordnung der Lücke:

Wen betrifft das?

Zugriff Änderung nötig?
Weboberfläche, Permalinks Nein
benno-client und Skripte, die direkt gegen benno-rest gehen (Port 21080, Shared Secret aus rest.conf) Nein
Eigene Skripte, Fremdsysteme und Integrationen, die https://<server>/benno/rest.php/... aufrufen Ja, prüfen (Abschnitte 2–6)
Kopano-WebApp-Plugin (bennopath = .../benno/rest.php) Nach dem Update testen (Abschnitt 7)
Docker-Appliance Fix ab Version 2.10.11 enthalten

1. Beide Pakete gemeinsam aktualisieren

Der Fix besteht aus zwei Teilen: benno-web übergibt den Benutzerfilter, benno-rest setzt ihn beim Mailabruf durch. Wer nur eines der beiden Pakete aktualisiert, ist nicht geschützt.

Vorher

benno-web 2.10.10, benno-rest 2.10.8 (oder älter)

Nachher

apt-get update
apt-get install benno-web benno-rest
dpkg -l benno-web benno-rest     # erwartet: 2.10.11 bzw. 2.10.9 (oder neuer)

Das Paket benno-rest startet den Dienst benno-rest selbst neu.

Docker-Appliance: Der Fix ist ab Version 2.10.11 der Appliance enthalten.

2. Gesperrte Endpunkte: direkt gegen benno-rest gehen

Über rest.php sind nur noch diese Endpunkte erreichbar:

Endpunkt Zweck
/search Suche
/kopano Suche für das Kopano-Plugin
/mail einzelne Mail abrufen
/attachment Anhang abrufen
/logout Sitzung beenden

Alle anderen Endpunkte antworten für jede Rolle, auch für ADMIN, mit HTTP 403.

Vorher (Lizenzabfrage über den Proxy)

curl -u api:Passwort 'https://benno.example.com/benno/rest.php/license?archive=BennoContainer'
# HTTP 200, Lizenzdaten

Nachher

curl -u api:Passwort 'https://benno.example.com/benno/rest.php/license?archive=BennoContainer'
# HTTP 403

Stattdessen direkt gegen benno-rest gehen. Adresse, Benutzer und Secret stehen in /etc/benno-web/rest.conf (BASE_URL, REST_USER, SHARED_SECRET; fehlen die ersten beiden, gelten http://localhost:21080 und benno2):

curl -u benno2:<SHARED_SECRET> 'http://localhost:21080/license'
# HTTP 200, Lizenzdaten als JSON

Lauscht benno-rest nur auf 127.0.0.1:21080, geht der direkte Aufruf nur vom Server selbst aus. Von einem anderen Rechner aus ist benno-rest nur erreichbar, wenn es auf einer Netzwerkadresse lauscht.

Docker-Appliance: benno-rest lauscht im Container nur auf 127.0.0.1:21080. Der docker run-Aufruf der Appliance veröffentlicht nur die Ports 22, 80 und 22500, Port 21080 also nicht. Der direkte Aufruf geht deshalb nur im Container. Dort ist kein curl installiert, aber wget. Das Secret steht in /etc/benno-web/rest.conf, dem eingebundenen Volume /etc/benno-web:

docker exec bma wget -qO- --user=benno2 --password='<SHARED_SECRET>' http://localhost:21080/license
# Lizenzdaten als JSON

Das Shared Secret hat Vollzugriff auf alle Container. Es gehört nicht in Skripte auf Arbeitsplatzrechnern.

3. Das richtige Konto für den REST-Zugriff wählen

rest.php wendet jetzt bei jedem Endpunkt den Filter des angemeldeten Kontos an, auch bei /mail und /attachment. Eine Mail außerhalb des Filters beantwortet benno-rest mit HTTP 404, also wie eine unbekannte ID. Welche Mails ein Konto sieht, hängt von der Rolle ab:

Rolle Sichtbare Mails über rest.php Eigener filterQuery-Parameter
USER, USERADMIN Mails zu den eigenen Adressen, eingeschränkt durch die globalen und die eigenen Filter. Alle Filter gelten; vorher galt nur der letzte. wird ignoriert
REVISOR alle Mails der zugewiesenen Container wird ignoriert
ADMIN wie USER, also die eigenen Adressen und Filter erlaubt, z. B. filterQuery=* für alle Mails
SITEADMIN wie USER wird ignoriert
Konto ohne Adresse und ohne Filter (auch ADMIN ohne filterQuery) keine (0 Treffer, /mail 404) –

Ein Integrationskonto, das auf alle Mails zugreifen soll, braucht deshalb eine dieser Konfigurationen:

  1. Rolle REVISOR (empfohlen für reinen Lesezugriff): Das Konto sieht automatisch alle Mails, ohne zusätzlichen Parameter.
  2. Rolle ADMIN und bei jedem Aufruf filterQuery=* mitschicken. Ohne den Parameter gilt der eigene Filter.
  3. Adresse *@* am Konto, bei jeder Rolle. Der daraus erzeugte Filter trifft jede Mail mit Absender oder Empfänger.

Vorher (Konto api mit Rolle USER und einer Adresse holt eine beliebige Mail per ID)

curl -u api:Passwort 'https://benno.example.com/benno/rest.php/mail' \
  -d archive=BennoContainer -d id=2026:8B708B8C8A5C331...
# HTTP 200, auch wenn die Mail nicht zur Adresse von api gehört

Nachher

# dasselbe Konto: HTTP 404, die Mail liegt außerhalb seines Filters
 
# Variante 1: Konto auf REVISOR umstellen
benno-useradmin -u api -r REVISOR
 
# Variante 2: Konto mit Rolle ADMIN, Filter ausdrücklich mitschicken
curl -u api-admin:Passwort 'https://benno.example.com/benno/rest.php/mail' \
  -d archive=BennoContainer -d id=2026:8B708B8C8A5C331... -d 'filterQuery=*'
# HTTP 200

Ein Konto mit Rolle ADMIN ohne Adresse, das bisher kein filterQuery mitgeschickt hat, findet nach dem Update nichts mehr. In diesem Fall Variante 1 oder Variante 2 umsetzen.

4. Nur noch bekannte Parameter

rest.php leitet je Endpunkt nur die Parameter weiter, die benno-rest dort auswertet. Alle anderen fallen ohne Fehlermeldung weg. GET- und POST-Parameter funktionieren beide weiterhin.

Endpunkt Weitergeleitete Parameter
/search, /kopano query, full, sort, sortAsc, start, limit
/mail id, format, header, skipUTF8Recode
/attachment id, attachmentId, attachment
/logout –

Dazu kommen immer:

Vorher

curl -u api:Passwort 'https://benno.example.com/benno/rest.php/search' -d 'query=Rechnung'
# HTTP 404, ohne archive fand benno-rest keinen Container

Nachher

curl -u api:Passwort 'https://benno.example.com/benno/rest.php/search' -d 'query=Rechnung'
# HTTP 200, Suche im zuletzt zugewiesenen Container des Kontos

5. Strengere Pfadprüfung

Der Pfad hinter rest.php/ darf nur Buchstaben, Ziffern, _, - und / enthalten. URL-kodierte Zeichen (%3F, %23, …), Punkte und ein leerer Pfad werden mit HTTP 400 abgelehnt.

Vorher

curl -u api:Passwort 'https://benno.example.com/benno/rest.php/search%3Fquery=Rechnung&archive=BennoContainer'
# wurde durchgereicht

Nachher

curl -u api:Passwort 'https://benno.example.com/benno/rest.php/search?query=Rechnung&archive=BennoContainer'
# HTTP 200; die kodierte Variante oben: HTTP 400

6. Antwortcodes und Protokoll

Code Bedeutung
401 nicht angemeldet bzw. falsches Passwort
400 Pfad leer oder mit unzulässigen Zeichen
403 Endpunkt nicht freigegeben oder Container nicht zugewiesen
404 Mail oder Anhang unbekannt oder außerhalb des Filters (bewusst nicht unterscheidbar)

Abgelehnte Zugriffe protokolliert benno-web über das PHP-Fehlerlog:

Beispiele:

[0:rest_backend] WARNING REST access of api to forbidden endpoint license
[0:rest_backend] WARNING REST access of api to disallowed container FremderContainer
[0:rest_backend] WARNING REST request of api with invalid path search?query=...

7. Kopano-WebApp-Plugin

Das Plugin geht standardmäßig über rest.php (/etc/benno-kopano-webapp-plugin/settings.ini, bennopath) und schickt einen eigenen filterQuery mit. Nach dem Update gilt bei Nicht-ADMIN-Konten der Filter von benno-web. Das Plugin zeigt also dieselben Mails wie die Weboberfläche. Nach dem Update kurz prüfen: Suche, Mail öffnen, Anhang öffnen.

8. Nach dem Update