Open Source im professionellen Einsatz

Shellskripte aus der Stümper-Liga - Folge 3: Passwörter und Race Conditions

Bash Bashing

Viele Entwickler stecken zwar viel Überlegung in die Sicherheitsfunktionen ihrer Programme, kümmern sich um Rechte und sorgen sich um den sicheren Umgang mit Passwörtern. Blöd nur, wenn Wrapperskripte all diese Überlegungen über den Haufen werfen.

Eine beliebte Lösungsstrategie kleiner Kinder ist das Schließen der Augen. Was sie nicht sehen, ist nicht da, weder für sie, noch für andere. Zum Beispiel das umgeschüttete Glas oder ein zerbrochenes Spielzeug der großen Geschwister. Wenige Jahre später holt die meisten ziemlich schnell eine brutale, andere Wirklichkeit ein, in der der Lider-zu-Ansatz nicht mehr klappt. Dennoch hofft eine kleine Gruppe weiterhin auf dessen Gültigkeit: naive Shellskript-Programmierer.

Passwörter im Klartext

Denn Geheimnisse gibt es viele zu hüten, aber manchmal sind sie auch lästig: Wer möchte eigentlich jedes Mal, wenn sich das Skript an die Datenbank wendet, neu das Passwort eingeben? Die Motivation eines Skripts ist schließlich meist, wiederkehrende Abläufe zu automatisieren. So landen immer wieder Passwörter im Klartext in Shellskripten oder in Cronjobs. Allein das stellt einem für die Sicherheit Verantwortlichen schon die Nackenhaare auf: Jeder, der Zugriff auf das Skript bekommt, kennt fortan auch das eigentlich geheimzuhaltende Passwort.

Immerhin muss eine zweite Bedingung erfüllt sein: die Möglichkeit, das Skript zu lesen. Solange das Skript ruht, lässt sich die Bedingung sogar halbwegs auf jedem Linux-System mittels »chmod og-r Datei« verhindern (sofern Anwender berücksichtigen, dass bekanntlich Root und indirekt alle Benutzer mit Zugang zu diesem Account jede Datei lesen dürfen). Das haben sich seinerzeit wohl auch jene SAP-Entwickler gedacht, die in ihrem stümperhaften Startskript für die SAP DB »/etc/init.d/sapdb74« das Codefragment aus Listing 1 stehen hatten [1].

Listing 1: Fehlerhaftes
Startskript für die SAP DB

01 DBMCLI=$X_PATH/dbmcli
02 if [ ! -x $DBMCLI ]; then
03     echo "dbmcli not found" >&2
04     exit 5
05 fi
06 $DBMCLI -d TST -u dbm,dbm db_warm > /dev/null &

Jeder Anwender, der auf derselben Maschine zur Laufzeit das Kommando »ps auxwww« startete, sah in der Prozessliste die Argumente und damit auch den Benutzernamen »dbm« und das gleichlautende Passwort. Dank des Tipps von Bash-Bashing-Leser Peter Conrad [2] haben die Entwickler den Code in die etwas sicherere Variante aus Listing 2 abgewandelt. Der dabei angewandte Übergabemechanismus über die Standardausgabe der Shell und die Standardeingabe der Datenbank ist ohne Root-Rechte von anderen Prozessen aus nicht abhörbar.

Listing 2: Korrigiertes
Startskript für die SAP DB

01 DBMCLI=$X_PATH/dbmcli
02 if [ ! -x $DBMCLI ]; then
03     echo "dbmcli not found" >&2
04     exit 5
05 fi
06 _o=`$DBMCLI -d TST74 << __EOD__ 2>&1
07     user_logon dbm,dbm
08     db_online
09 __EOD__`

Leider beherrscht nicht jedes Programm das Einlesen von Credentials über einen Filedescriptor. Manchmal benötigt es erst viel später nach seinem Aufruf ein Passwort oder möchte es nur bei Bedarf nachschlagen. Ein Beispiel ist ein Webbrowser, den Anwender normalerweise für das Intranet nutzen, der aber für den Zugriff auf das Internet einen Proxy benötigt. Viele Proxys wollen dann ein Passwort sehen - lästig für den Benutzer.

Umweltschutz

In einem Sun-Forum haben Programmierer den Code aus Listing 3 für die ».bashrc« vorgeschlagen [3]. Die Option »-e« von »read« schaltet die Readline-Funktionen ein, um die Eingabe bequem editierbar zu machen, »-s« in Zeile 4 unterdrückt das Echo auf dem Bildschirm bei der Passworteingabe. Danach speichert das Fragment die Angaben direkt in der Umgebungsvariablen »http_proxy«, die wie jede URL auch zwei Authentisierungsattribute enthalten darf, den Benutzernamen und das Passwort.

Listing 3: Passwort im
Environment

01 echo -n "Enter Proxy Username: "
02 read -e username
03 echo -n "Enter Proxy Password: "
04 read -es password
05 echo
06 export http_proxy="http://$username:$password@proxyserver:8080/"

Problematisch ist nur, dass die Autoren übersehen haben, dass das Environment ebenfalls für andere Anwender sichtbar ist. Bloß weil nur wenige Anwender die BSD-Option »e« des Kommandos »ps« häufig nutzen, heißt das nicht, dass die Information nicht vorhanden ist. Der Aufruf »ps auxe | tr ' ' ' ' | grep http_proxy | head -1« liefert nämlich:

http_proxy=magnus:dasIstNichtMeinPasswd@prx

Weil das Kommando die einzelnen Schlüssel-Wert-Paare alle in eine Zeile schreibt, nur durch Spaces getrennt, sorgt das »tr«-Kommando für einen Umbruch nach jedem Wort, damit das anschließende »grep« sich auf das Wesentliche konzentrieren kann.

Eine Idee wäre, das Passwort in Shellskripten zu verschlüsseln. Listing 4 implementiert einen einfachen involutorischen Verschiebe-Algorithmus, auch Caesar-M oder Rot13 genannt. Doch selbst wenn der Algorithmus ausgefuchster wäre, hilft das nicht weiter, denn zwangsläufig kann jeder, der Einblick in das Skript hat, die Entschlüsselungsfunktion ablaufen lassen, sodass sich das Problem in seinen eigenen Schwanz beißt. Man kann es drehen und wenden, wie man will: Auf Client-Seite ist ein Passwort am besten im Kopf seines Besitzers aufgehoben.

Listing 4:
Verschlüsselungsfunktion

01 function crypt() {
02     echo "$*" | tr 'A-Z' 'N-ZA-M'
03 }
04 
05 passwd=$(crypt "MVRZYVPU TRURVZ")

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 2 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Als digitales Abo

Als PDF im Abo bestellen

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook