Benutzer-Werkzeuge

Webseiten-Werkzeuge


dba:passwort_verschluesselt_hinterlegen

Wohin nur mit den Passwörtern in Windows und Linux Skripten? - Passwörter in Skripten verschlüsselt hinterlegen.

Veröffentlicht im Red Stack Magazin der DOAG, September 2018

Sourcecode Beispiele

Beispiele im Detail auf https://github.com/gpipperr/RedStack_Magazin_2018_encrypt_password


Das Problem:

In vielen Skripten rund um die tägliche Wartung unserer Systemumgebungen müssen Passwörter hinterlegt werden. Und nicht immer kann mit der Oracle Wallet oder SSL Zertifikaten bzw. Betriebssystem Rechten ganz auf Passwörter verzichtet werden.

Wie aber diese Passwörter so schützen, dass nicht jeder sofort die Passwörter auslesen und verwenden kann?

Wie die Skripte in einer Sourcecode Verwaltung so hinterlegen, dass dort sicher keine Passwörter mehr vorkommen? Wie Passwörter auf gehosteten Server Umgebungen hinterlegen und den Sicherheits-Regularien meines Unternehmens genügen?

Gerade in Umgebungen, die in die Jahre gekommen sind, wimmelt es nur so von Passwörtern. Jede Änderung bedingt meist umfangreiche Anpassungen an vielen Stellen. Werden Skripte kopiert und weitergegeben, besteht immer die Gefahr, dass ein Passwort in die falschen Hände gerät. Besonders in gehosteten Umgebungen, auf denen das Betriebssystem vom einen Hoster mit Root Rechten verwaltet wird, sollte sich der Kunde der Gefahr mit den offenen Passwörtern in Skripten sehr bewusst sein.

Diese Passwörter stellen trotz aller Bemühung auch heute noch eines der höchsten Sicherheitsrisiken für die meisten Systeme dar.

Um dieses Risiko zu bekämpfen, sollten die folgenden Vorgaben für alle Umgebungen gültig sein:

  • Kein Passwort kommt im Skript vor, nur eine Variable wird verwendet, die mit dem Passwort gefüllt wird.
  • Bei einer Passwort-Änderung muss das Skript nicht angepasst werden.
  • Die Passwörter sind auf dem System verschlüsselt hinterlegt.
  • Die verschlüsselten Passwörter können nur auf der Zielmaschine entschlüsselt gelesen werden.
  • Alles was für die Umsetzung des Konzepts benötigt wird, muss auch in veralteten, bzw. gehosteten Umgebungen ohne besondere Systemrechte möglich sein.

Und nebenbei werden so ohne großen Aufwand meist schon die wichtigsten Sicherheits-Regeln eingehalten, ohne den Betrieb mit zu hohen Aufwänden zu belasten.

Vor welchen Szenarien schützt uns die Umsetzung des Konzepts?

  • Skripte können nun problemlos per Mail / Git oder Web verteilt werden, keine Passwörter gehen aus Versehen verloren.
  • Die verschlüsselten Passwörter sind keinem von Nutzen, der keinen Zugriff auf dem Zielserver hat.
  • Unangenehme Gespräche mit dem Security Officer in der Kantine beim Mittagessen.

Vor welchen Szenarien schützt uns das NICHT?

  • Vor den neugierigen Blicken der Kollegen mit Root Zugriff auf das System! Während das Skript läuft, ist im Speicher oder der /proc Umgebung das Passwort meist mit etwas Geschick auffindbar.
  • Das Passwort lässt sich auf der Maschine per Skript auslesen, der Schlüssel für das Passwort lässt sich dort aber nie so verstecken, dass keiner den Schlüssel findet, das Skript benötigt diesen ja auch.

Denn wie bei jeder Verschlüsselung ist es eigentlich egal wie komplex oder sicher der Algorithmus ist, meist kann durch ein wenig Nachdenken und Ausprobieren der Schlüssel im System selber gefunden werden.

Den Schlüssel zu verstecken gelingt den wenigsten wirklich, denken wir nur an unsere Eltern, da liegt der Schlüssel auch immer hinten am Gartenzaun unter dem Blumentopf.

D.h. unser Ziel ist mit dieser Lösung nicht eine 100% Sicherheit, sondern das Begrenzen von Schaden und das Erfüllen von Sicherheitsvorgaben.

Werden diese einfachen Vorgaben konsequent umgesetzt, bedeutet dies für das Unternehmen meist schon eine dramatische Verbesserung der Sicherheitslage ohne großen Aufwand und viele Schwierigkeiten im Betrieb

Wie lässt sich das ganze nun aber unter Windows und Linux so bequem wie möglich umsetzen?

Unser Werkzeugkasten:

  • Das Microsoft Credential Objects in der Windows PowerShell
  • Verschlüsseltes Hinterlegen von Passwörtern auf Linux Systemen mit openssl
  • Oracle Features wie der Oracle Wallet

Die ideale Lösung - Keine Passwörter verwenden .-)

Und nun zuerst die ideale Lösung für das Problem, wir verwenden gar keine Passwörter mehr.

D.h. in der Regel delegieren wir diese Aufgabe einfach an das Betriebssystem der Datenbank und überlassen diesem, bzw. dem Systemadministrator der Umgebung, die ganze Verantwortung, dass alles sicher betrieben wird.

Nachteil: Wer sich am System anmelden kann kommt nun ganz ohne Passwort aus.

Sehr einfach

Sehr einfach lässt sich das Umsetzen, wenn der OS User in der DBA Gruppe ist und alle Aufgaben mit dem SYS User durchgeführt werden können.

Geht aber nur, wenn der OS User in der DBA Gruppe ist und alles mit SYS auch durchgeführt werden kann/darf/will.

Etwas besser

Etwas sicherer ist es, „External authentification“ für die Datenbankzugänge einzusetzen.

Das heißt aber das auch etwas Technik dahinter funktionieren muss, oft schwer umzusetzen in gehostenen Umgebungen in denen jeder ja froh ist das es überhaupt noch irgendwie läuft.

Siehe ⇒ https://oracle-base.com/articles/misc/os-authentication

Oracle Wallet- Secure External Passwort Store

Sehr komfortabel ist die Oracle Wallet als Secure External Passwort Store Lösung, mehr dazu unter

Secure External Passwort Store


Passwörter unter Windows schützen

Unter Windows ist das verschlüsselte Hinterlegen der Passwörter so trivial, dass jeder der es nicht nützt, sich eigentlich fast grob fahrlässig verhält.

Das Erstellen eines Passwort-Containers inkl. des Aufrufes der Pflegeoberfläche sind im Prinzip nur 2 Zeilen Code.

# PWD
$db_user     = "system"
$oracle_credential = "$scriptpath\ORACLE_CREDENTIAL.xml"
 
#
# To store the password we use  the PSCredential object
# if the serialized object of the password not exists
# prompt the user to enter the password
#
 
if (!(test-path -path $oracle_credential)) {
	$user_credential=GET-CREDENTIAL -credential "$db_user"  
	export-clixml -InputObject $user_credential -Path $oracle_credential
}
else {
   $user_credential=Import-Clixml -Path $oracle_credential
}
 
#get the clear type password
 
$db_password=$user_credential.GetNetworkCredential().Password

Source Code ⇒ https://github.com/gpipperr/RedStack_Magazin_2018_encrypt_password/blob/master/ms_powershell/simpleExample.ps1

Ein praktisches Beispiel siehe hier ⇒ Oracle Apex Source Code automatisch exportieren und einchecken mit Git unter Windows mit der PowerShell

Passwort über GET-CREDENTIAL eingeben

GET-CREDENTIAL -credential "oralce"

 Den Windos Password Dialog in der Powershell aufrufen

Mit

$user_credential=GET-CREDENTIAL -credential "$db_user"

erzeugen wir uns in der Variablen user_credential ein Credential Object mit unsern Password. Der Schlüssel das ganzen ist die eindeutige ID des OS.

Serialisern des Objektes mit export-clixml

Um nun unseren Passwort Store auf der Platte abzulegen (wir wollen ja nicht bei jedem Skript Aufruf das Passwort neu eingeben), serialisieren wir das Objekt mit „export-clixml -InputObject $user_credential -Path $oracle_credential”. Es entsteht eine XML Datei mit dem Objekt in einer Art BASE64 Codierung.

export-clixml -InputObject $user_credential -Path $oracle_credential

Es entsteht eine XML Datei mit den Objekt in einer Art BASE64 Codierung.

Einlesen des Passworts aus dem Store

Beim nächsten Lauf ist das Passwort bereits hinterlegt, und das Objekt wird wieder in den Speicher geladen mit „$user_credential=Import-Clixml -Path $oracle_credential„”.

$user_credential=Import-Clixml -Path $oracle_credential" geladen.

Nun kann das Passwort im Script in Klarschrift ausgelesen werden über „$db_password=$user_credential.GetNetworkCredential().Password“.

$db_password=$user_credential.GetNetworkCredential().Password

Password Dialog in der Konsole starten

Wer lieber das Password über die Console setzt, kann mit dem Registry Eintrag (HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds\ConsolePrompting) =$True den graphischen Dialog vermeiden.

Key setzen:

$key = “HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds”
Set-ItemProperty $key ConsolePrompting True

Password in der Console hinterlegen:

Get-Credential
 
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential
User: oracle
Password for user oracle: ******
 
 
UserName                     Password
--------                     --------
oracle   System.Security.SecureString

 cmdlet Get-Credential at command  line to enter password

siehe auch:


Passwörter unter Linux sicher ver­wah­ren

Unter Linux wird das ganze etwas schwieriger. Gerade in gehosteten Umgebungen muss der Kunde mit dem Vorlieb nehmen, was der Dienstleister unter Sicherheit versteht. Das heißt meistens rein kosten optimiert zu arbeiten und wenig flexibel auf besondere Softwarewünsche wie ein aktuelles Java oder einen gcc einzugehen.

SSH und damit „openssl“ steht hier aber überwiegend zur Verfügung, bzw. es spricht sehr wenig dagegen das kostenfrei installieren zu lassen.

Damit haben wir mit „openssl“ auf Linux ein Werkzeug zur Verfügung das die kompliziertesten Verschlüsselungs-Verfahren sehr sicher beherrscht.

Jetzt müssen wir nur noch einen Schlüssel finden, der möglichst länger ist als das Passwort, um das Entschlüsseln für den Angreifer spannender zu gestalten.

Der Schlüssel muss erfüllen:

  • Muss auf jeden Server dieser Welt eindeutig sein.
  • Länger als das Passwort sein.
  • Sollte sich nicht auf den ersten Blick erkennen lassen.
  • Einfaches erzeugen/auslesen unter Linux.

Solche Schlüssel können sein:

  • WWN oder UUID einer Devices, dass sich nicht so schnell ändert
  • Hardware ID wie die MAC Adresse oder die Prozessor ID.
  • Eine eigene Routine in c die eine eindeutige ID erzeugt.

Meist verwende ich einfach die UUID von /dev/sda1 als Schlüssel oder die Seriennummer des OS unter HP UX.

Hier ist es der Phantasie des Entwicklers überlassen durch Obfuscation das Ganze noch etwas intransparenter zu gestalten. Die Kollegen vom Support aus fernen Ländern sollten das am Ende aber noch bedienen und warten können.

Wie funktioniert das Ganze im Detail?

Das Passwort wird zu Beginn in einer Datei in Klarschrift hinterlegt und dann verschlüsselt. Das kann im Skript gleich beim nächsten Aufruf oder mit einem kleinen Hilfsskript vorab erfolgen.

„openssl“ dient im folgenden dazu die Konfigurationsdatei mit dem Passwort Store zu verschlüsseln und stellt den kompliziertesten Teil des Ganzen dar. Über folgenden Aufruf „openssl des3 -salt -in ${PWDFILE} -out ${PWDFILE}.des3 -pass pass:„${SYSTEMIDENTIFIER}„“ wird die Passwort Datei dabei verschlüsselt.

openssl des3 -salt -in  ${PWDFILE} -out ${PWDFILE}.des3 -pass pass:"${SYSTEMIDENTIFIER}" 

Auch hier lässt sich dann mit ein paar Zeilen Code ein Ergebnis erzielen

# password.conf.des3
PWDFILE=.password.conf
export PWDFILE
 
 
# etwas Eindeutiges aus der Umgebung der Maschine auslesen
# Linux 
SYSTEMIDENTIFIER=`ls -l /dev/disk/by-uuid/ | awk '{ print $9 }'  | tail -1`
export SYSTEMIDENTIFIER
 
 
#
# Password verschlüsseln
encryptPWDFile () {
    /usr/bin/openssl des3 -salt -in  ${PWDFILE} -out ${PWDFILE}.des3 -pass pass:"${SYSTEMIDENTIFIER}" > /dev/null
    # Remove orignal file
    rm ${PWDFILE} 
}
 
# Password wieder auslesen
dencryptPWDFile() {
    /usr/bin/openssl des3 -d -salt -in ${PWDFILE}.des3 -out ${PWDFILE} -pass pass:"${SYSTEMIDENTIFIER}" > /dev/null
}
 
 
# Password in den Speicher laden
# Falls verschlüsselte Datei vorliegt 
if [ -f "${PWDFILE}.des3" ]; then
    dencryptPWDFile
    # in die Umgebung einlesen
    . ${PWDFILE}
    # Klarschrift Datei wieder entfernen
    rm ${PWDFILE}
else
     # Falls unverschlüsselt vorliegt, Datei verschlüsslen
	if [ -f "${PWDFILE}" ]; then
        . ${PWDFILE}
        encryptPWDFile		
    else
		echo "no preconfiguration file =>password.conf<= found"
		echo "export DB_PWD=" > ${PWDFILE}
		echo "no preconfiguration password.conf found - edit the file =>password.conf<= and set password and start again"
		exit 1
    fi
fi
 
# Password auf eine interne Variable kopieren und überschreiben
# siehe Kasten zu den environ Problem
INTERNAL_PWD=${DB_PWD}
export DB_PWD=“DU_SOLLST_DAS_NICHT_LESEN“
 
echo "Info --  read encrypted password  =>> ${INTERNAL_PWD} <<=="

siehe auch https://github.com/gpipperr/RedStack_Magazin_2018_encrypt_password/blob/master/linux_bash/simpleExample.sh

Um die Sicherheit noch weiter zu erhöhen und um Spuren in der Umgebung so weit wie möglich zu verschleiern, kann das Passwort in der Datei beim Verschlüsseln zuvor noch mit einem symmetrischen Algorithmus so verschlüsselt werden, dass erst zur Laufzeit im Skript an den jeweiligen Stellen das echte Passwort daraus extrahiert daraus wird. Diese sollte dann ohne Umwege in das aufzurufende Programm hinein „gepiped“ werden. Dies ist zwar nicht deutlich sicherer, dient aber dazu auf den ersten Blick den Angreifer etwas mehr zu verwirren.


Sourcecode Beispiele

Härten

Ist das nicht genug kann die Zielumgebung über Techniken wie einen Logon Trigger natürlich zusätzlich gehärtet werden.


Fazit

Auch mit diesem Konzept lässt sich in unserer Welt keine endgültige Sicherheit herstellen. Es ist aber ein wichtiger Schritt sensitiver und vor allem proaktiv mit dem Passwortproblem umzugehen.

Und das Ganze ohne besonderem Aufwand für den Betrieb mit dem Vorteil die Passwortänderungen zu zentralisieren.

Den vollständigen Source Code finden Sie auf Github unter https://github.com/gpipperr/RedStack_Magazin_2018_encrypt_password

Besonders möchte ich mich bei Martina Pippèrr und Sebastian Geddes bedanken, die geduldig geholfen haben diesen Text zu überabeiteten.



Über das Auslesen von Umgebung-Variablen in Linux

Über /proc die Laufzeit Umgebung eines Linux Prozesses auslesen

Mit entsprechenden Rechten (denken sie dabei an ihren Kollegen oder Ihren Dienstleister) kann über das /proc Dateisystem und die „environ“ Datei die gesetzte Umgebung eines Scripts ausgelesen werden. D.h. sensitive Daten wie Passwörter sollten nur so kurz wie möglich in diesem Bereich sichtbar sein!

Über diesen Weg lässt sich auch sehr einfach überprüfen, welche Umgebungs-Variablen ein Prozess (wie zum Beispiel ein Oracle Hintergrund Prozess) wirklich sieht und verwendet.

Anwendungsbeispiel:

  • Prozess ID ermitteln mit „ps uafx | grep sqlplus”
  • In das Proc File System wechseln „cd /proc/<processid>/“
  • Über die Datei „environ“ kann nun die Umgebung des Prozesses ausgelesen werden „strings environ | grep NLS_LANG“


Quellen

Cookies helfen bei der Bereitstellung von Inhalten. Durch die Nutzung dieser Seiten erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Rechner gespeichert werden. Weitere Information
"Autor: Gunther Pipperr"
dba/passwort_verschluesselt_hinterlegen.txt · Zuletzt geändert: 2018/09/05 09:58 von Gunther Pippèrr