Eine Sicherheitslücke im Debian-Paket des minimalistischen PDF-Viewers Xpdf hat zur Folge, dass ein entfernter Angreifer Dateien mit den Rechten des Anwenders löschen und auch bestimmte Befehle ausführen kann.
Debians Xpdf-Paket verwendet einen Skript-Wrapper, bevor das eigentliche Executable “xpdf.real” aufgerufen wird. Dieser Wrapper kümmert sich beispielsweise darum, dass der Anwender gepackte Dateien wie “*.pdf.gz” direkt mit dem Xpdf-Kommando anzeigen kann, ohne diese erst umständlich per Hand entpacken zu müssen. Zum Verarbeiten solch Gzip-gepackter Dateien wird im Wrapper-Skript die Datei zunächst mit “zcat” entpackt und in eine temporäre Datei geschrieben. Das erledigt das Skript in folgenden wenigen Zeilen:
tmp=$(tempfile -p "$(basename "$file")" -s .pdf) $cat "$file" > "$tmp" trap "rm -f \"$tmp\"" EXIT HUP INT QUIT TERM $cmd -title "$title" "$tmp" $pages || true
Die erste Zeile erzeugt zunächst einen temporären Dateinamen. In die so benannte Datei wird in der zweiten Zeile dann der entpackte PDF-Dateiinhalt geschrieben – die Variable “$cat” ist an dieser Stelle bereits auf “zcat” gesetzt. Das Erzeugen temporärer Dateinamen ist eine Standardaufgabe unter Linux und tritt immer wieder auf. Das “/tmp”-Verzeichnis ist voll solcher Dateien, die teilweise in verschiedenen Unterverzeichnissen angelegt sind und oftmals recht kryptische Namen tragen. Der Zweck der seltsam anmutenden Dateinamen ist es, zu verhindern, dass zwei Programme den gleichen temporären Dateienamen generieren.
Da temporäre Dateien so häufig gebraucht werden stellt Linux einen eigenen Befehl namens “tempfile” dafür bereit. Damit lassen sich insbesondere sichere temporäre Dateien erzeugen. Tempfile verwendet den Bibliotheksaufruf “tempnam()”, um einen Namen zu erzeugen und öffnet diese Datei dann mit den Attributen “O_RDWR | O_CREAT | O_EXCL”, wobei der Dateiname auf “stdout” zurückgegeben wird. Mit ein paar wenigen Kommandozeilenoptionen lassen sich noch Feinheiten wie beispielsweise Pfad (“-d”), Präfix (“-p”) und Suffix (“-s”) bestimmen. Das Präfix kann dabei bis zu fünf Zeichen lang sein:
mark@tux:~$ tempfile -p MyTempFile /tmp/MyTemv8sB8v mark@tux:~$ ls /tmp/MyTemv8sB8v /tmp/MyTemv8sB8v
Nachdem die temporäre Datei so angelegt wurde, schreibt “$cat” die entpackte PDF-Datei dort hinein. Um eventuelle Fehler hierbei abzufangen kommt das Tool “trap” zum Einsatz. Trap fängt verschiedene Linux-Signale ab und ruft einen entsprechende Befehl auf. Folgendes einfaches Beispiel zeigt wie “trap” ein “exit 0”-Signal erkennt und als Reaktion darauf einen Text mit “echo” ausgibt:
trap 'echo "Exit 0 signal detected..."' 0 echo "This is a trap test" exit 0
Diese Befehle, in ein Skript namens “trap.sh” geschrieben und aufgerufen, zeigen dann folgenden Text an:
mark@tux:~$ bash test.sh This is a trap test Exit 0 signal detected...
Zunächst wird die “echo”-Testnachricht angezeigt, und dann der durch “exit 0” ausgelöste “echo”-Befehl aufgerufen.
Das Wrapper-Skript für Xpdf löscht die temporäre Datei mit “rm -rf”, falls etwas schief geht, und Trap ein entsprechendes Signal abfängt. Im letzten Schritt wird schließlich “$cmd” aufgerufen, wobei diese Variable “xpdf.real” mit etwaigen Kommandozeilenparametern enthält.
Die Sicherheitslücke in Xpdf hat sich in genau diesen vier Zeilen versteckt. Das eigentliche Problem liegt dabei in der Konstruktion des temporären Dateinamens. Er wird zwar vorbildlich mit “tempfile” erzeugt, doch spielt hier die Variable “$file” als Teil des Präfixes mit hinein. Basename ist ein weiterer Linux-Befehl, der aus einem Dateinamen die Verzeichnis-Strings entfernt:
mark@tux:~$ basename /usr/bin/test test
Die “$file”-Variable enthält den an Xpdf übergebenen Dateinamen, das heißt, der Angreifer hat Kontrolle über diesen Namen. Ein wenig Shell-Erfahrung zeigt, dass man damit leicht Dateien mit den Rechten des Xpdf-Anwenders löschen kann, wie es am 29. Juli Chung-chieh Shan demonstriert hat:
$ touch y # The unrelated victim file $ gzip -c </dev/null >'" y ".pdf.gz' # Create a .pdf.gz file $ xpdf '" y ".pdf.gz' # View it using xpdf
Anschließend ist die Datei “y” gelöscht. Das Problem besteht darin, dass das Präfix so gebaut ist, dass “y” als eigene Datei interpretiert wird. Durch die Längenbegrenzung des mit “-p” spezifizierten Präfix lassen sich nicht beliebig lange Dateinamen löschen, aber das Wildcard “*” löscht unmittelbar alle Dateien im aktuellen Verzeichnis. Auf ähnliche Weise lassen sich auch bis zu drei Zeichen lange Befehle mit den Rechten des Anwenders ausführen:
$ gzip -c </dev/null >'`env`.pdf.gz' $ xpdf '`env`.pdf.gz'
Das Patch für diese Schwachstelle besteht darin, komplett auf das Präfix im temporären Dateinamen zu verzichten, da dieses ohnehin für die Xpdf-Anwendung nicht benötigt wird:
tmp=$(tempfile -s .pdf)
Dieser Patch ist in Version 3.02-19 des Debian-Pakets enthalten, die Vorgängerversion 3.02-18 ist anfällig für die obige Attacke. Mit dem Kommando “dpkg -l xpdf” lässt sich die installierte Version unter Debian abfragen. Bei Bedarf spielt “apt-get update” das Update ein.

