Open Source im professionellen Einsatz

Shellskripte aus der Stümper-Liga – Folge 13: Passwörter nicht entkommen lassen

Bash Bashing

Gerade für die lästigen Einzelschritte von Installationsroutinen größerer Softwarepakete bietet die Bash jede Menge Vereinfachungen. Vorsicht ist jedoch geboten, wenn es um Datenbank- und Applikationspasswörter geht. Die sind nämlich schnell futsch.

Für den Admin folgt die Installation von Webanwendungen immer dem gleichen Muster: Paket herunterladen und auspacken, Datenbank vorbereiten und dann beide Komponenten wechselseitig bekannt machen, meist durch eine Konfigurationsdatei. Welche Einträge in welcher Syntax in welche Datei gehören, erklärt traditionell die Datei »README« . Schneller (und manchmal auch weniger fehlerträchtig) gestaltet sich für den Admin die Installation, wenn die Entwickler ein Shellskript beilegen, das den Systemverwalter an der Hand nimmt und ihn durch die Einstellungen führt.

Diesen Weg geht auch eine Community für Magento, einer beliebten E-Commence-Plattform für PHP. Sie bietet auf ihrer Website einen Installer als Bash-Skript an [1]. Einen Auszug des Skripts zeigt Listing  1. Es folgt einem ganz schlichten Muster: Es fragt ab, ob schon die benötigte MySQL-Datenbank vorhanden ist, erkundigt sich nach einer Reihe von Verbindungsdetails zur Datenbank und lädt dann die benötigten Pakete mit »wget« herunter. Anschließend setzt es einige Zugriffsrechte und füttert die Datenbank mit einem Schema, sodass die Webapplikation starten kann.

Listing 1

Magento-Installer

01 #!/bin/bash
02
03 clear
04
05 echo "To install Magento, you will need a blank database ready with a user assigned to it."
06
07 echo -n "Database Host (usually localhost): "
08 read dbhost
09
10 echo -n "Database Name: "
11 read dbname
12
13 echo -n "Database User: "
14 read dbuser
15
16 echo -n "Database Password: "
17 read dbpass
18
19 echo -n "Store URL: "
20 read url
21
22 echo -n "Admin Username: "
23 read adminuser
24
25 echo -n "Admin Password: "
26 read adminpass
27 [...]
28 echo "Downloading and extracting packages ..."
29
30 wget http://www.magentocommerce.com/downloads/assets/1.4.1.1/magento-1.4.1.1.tar.gz
31 wget http://www.magentocommerce.com/downloads/assets/1.2.0/magento-sample-data-1.2.0.tar.gz
32 tar -zxvf magento-1.4.1.1.tar.gz
33 tar -zxvf magento-sample-data-1.2.0.tar.gz
34 [...]
35 echo "Importing sample products ..."
36 mysql -h $dbhost -u $dbuser -p$dbpass $dbname < data.sql
37 [...]
38 echo "Installing Magento ..."
39
40 php-cli -f install.php -- \
41     --license_agreement_accepted "yes" \
42     --db_host "$dbhost" \
43     --db_name "$dbname" \
44     --db_user "$dbuser" \
45     --db_pass "$dbpass" \
46 [...]
47 echo "Finished installing Magento"

Sichtbare Geheimnisse

Sicherheitsbewussten Admins fallen dabei allerdings einige Details auf. In Zeile 16 und später noch einmal in Zeile 25 erzeugt das Skript mit »echo -n "Passwort: **"« zunächst einen Prompt, der keinen Zeilenumbruch verursacht. Durch die Option »-n« bleibt der Cursor hinter der Ausgabe stehen. Anschließend fragt das Skript nach dem Passwort für die Datenbank. Einige Zeilen später wiederholt sich dieses Muster für den Administratorzugang des Webshops selbst.

Wer in einem Großraumbüro sitzt oder auch sonst Karotten knabbernde Kollegen hinter seinem Monitor wähnt, wird nicht erfreut sein, wenn er bei der Eingabe der Passwörter diese auf dem Bildschirm entdeckt. Der Bash-Befehl »read« wiederholt nämlich im Normalfall alle Eingaben auf der Standardausgabe.

An dieser Stelle ist es vielleicht nützlich, einmal nachzuverfolgen, wie diese Zeichen eigentlich dorthin gelangen: Sitzt ein Anwender direkt vor seinem Rechner, leitet die physikalische Tastatur Anschlagereignisse an den Kernel weiter. Der reicht sie, eine X11-Oberfläche vorausgesetzt, an den X-Server weiter, der sie in X-Events wandelt und an das richtige Fenster schickt, beim Admin wohl eine Terminalemulation wie »xterm« oder »konsole« .

Als Partner des Terminalprogramms läuft meist eine Shell wie die Bash. Beide Programme verbindet eine Pipe, die seitens des Terminals ein Pseudo-Terminaldevice wie »/dev/pts/0« und seitens der Shell die Standardeingabe repräsentiert. Braucht ein Bash-Anwender dafür eine Datei, darf er »/proc/self/fd/0« verwenden. Zwei weitere Pipes mit den Nummern 1 und 2 verbinden in gleicher Weise die beiden Seiten für die Standardausgabe und die Standardfehlerausgabe (siehe Abbildung  1).

Abbildung 1: Das Terminalprogramm konsole ist mit vier Shells über Pipes verbunden.

Das Terminalprogramm ist auch dafür verantwortlich, die gedrückten Tasten im Terminal anzuzeigen, nicht die Shell. Um das auszuprobieren, können Interessierte einmal das Kommando

stty -echo

in der Shell eingeben. Der Befehl schickt daraufhin per »ioctl()« eine Änderung an den Terminaltreiber, der fortan gedrückte Tasten nicht mehr anzeigt. Eingegebene Befehle verarbeitet die Shell jedoch weiter und erzeugt auch normale Ausgaben. Um den Normalzustand wieder herzustellen, genügt der komplementäre Befehl »stty echo« .

Neugierige Augen

Auf diese Weise lässt sich also auch in Shellskripten das Echo der Tastatureingaben deaktivieren und nach der Eingabe des Passworts wieder aktivieren. Um nicht auf diesen externen Befehl zurückgreifen zu müssen, bietet die Bash jedoch auch eingebaute Funktionen an, die ähnlich arbeiten. Mit der Option »-s« von »read« unterdrückt die Shell ebenfalls das Echo.

Die Bash kennt noch ein paar andere nützliche Optionen: So legt der Schalter »-n Anzahl« die Zahl der Zeichen fest, die »read« einliest. Dazu ist nicht einmal ein Newline notwendig, das die Shell sonst ja immer fordert, um eine Eingabe zu terminieren. Benutzt man die Kombination »read -n1 x« , wartet die Bash auf einen einzelnen Tastendruck und speichert ihn in der Variablen »x« .

Manchmal – in wilden Arcade-Shootern etwa – möchten Programmierer aber auch nur eine begrenzte Zeit auf eine Eingabe warten. Dazu dient die Option »-t Sekunden« . Nach der spezifizierten Zeit verarbeitet die Bash das folgende Kommando. Ob es eine Eingabe gab, müssen Entwickler dann über den Exit-Status des Kommandos mit »$?« auslesen. Listing  2 implementiert als Proof of Concept ein kleines Weltraumrennen im Retro-Look. Der Anwender steuert über die Tasten [G] und [H] sein kleines Raumschiff durch einen Asteroidengürtel und hinterlässt dabei einen Schweif an Antriebsgasen.

Listing 2

Weltraumrennen in Bash

01 #!/bin/bash
02
03 pos=40
04 width=80
05
06 while true; do
07     read -t1 -s -n1 x
08     case "$x" in
09         g) pos=$(($pos - 1)) ;;
10         h) pos=$(($pos + 1)) ;;
11     esac
12     for ((i=0; i < $width; i++))
13     do
14         if [ $i -eq $pos ]; then
15             echo -n 'V'
16         elif [ $(($RANDOM % 9)) -eq 0 ]; then
17             echo -n '*'
18         else
19             echo -n ' '
20         fi
21     done
22     echo
23 done

Der mit »read -s« verbesserte Magento-Installer hat aber noch weitere Makel. In Zeile  36 ruft das Skript MySQL auf, um die Datenbank zu initialisieren, und übergibt der Datenbank per Option »-p$dbpass« das zuvor erfragte Passwort. Andere Anwender, die zur Laufzeit des Skripts auf demselben Rechner eingeloggt sind, sehen diese Angaben mit »ps auxwww« in der Prozessliste im Klartext.

Daher gehören Passwörter niemals in Kommandozeilen-Argumente. Eine Alternative für die Datenübergabe wären Umgebungsvariablen, die sich jedoch in gleicher Weise mit »ps aueww« anzeigen lassen. Absurderweise implementieren viele Programme diese unsichere Methode, MySQL über die Umgebungsvariable »MYSQL_PWD« [2]. Der beste Weg, ein Klartextpasswort zu übertragen, sind daher Konfigurationsdateien, die die Software ausliest, oder alternativ Pipes wie die Standardeingabe. Puristen werden noch anmerken, dass Passwörter im Klartext eigentlich niemals gespeichert werden sollen, und verweisen dazu auf Hashwerte oder Token wie bei Kerberos. Die lassen sich allerdings kaum noch mit der Bash alleine implementieren.

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