Under Construction
Schritt 6: Implementieren von Undo
Für die Implementierung der Undo-Funktionalität gibt es drei Möglichkeiten:
- Ein Undo wird nicht unterstützt und daher auch nicht im Skript implementiert. (Einige Standard-Skripte wie validate_check, rmdotfrmpathnroot und weitere unterstützen ebenfalls kein Undo.)
- Das Skript zum Setzen und Überprüfen der Sicherheitseinstellung erzeugt ein Skript das den Undo der Sicherheitseinstellung implementiert. (Einige Standard-Skripte wie loginherald, rmrhostsnetrc und weitere machen dies so.)
- Das Skript zum Setzen und Überprüfen der Sicherheitseinstellung implementiert selbst den Undo. (Einige Standard-Skripte wie chusrattr, nfsopts und andere implementieren selbst den Undo.)
In vielen Fällen besteht das Setzen einer Sicherheitseinstellung darin einer Variablen oder einem Attribut in einer Konfigurationsdatei einen Wert zuzuweisen. Die entsprechenden Skripte zur Umsetzung erwarten dann in der Regel als Argument beim Skript-Aufruf den zu setzenden Wert (AIXPertArgs). Fragt man den ursprünglichen Wert vor der Änderung ab, ergibt sich ein Undo indem das Skript einfach mit dem ursprünglichen Wert als Argument gestartet wird. Es muss also häufig keine großartige Extra-Funktionalität programmiert werden.
Da unser bisheriges Skript keine Argumente unterstützt, zeigen wir zunächst die Möglichkeit 2.
Unabhängig davon welche der beiden Möglichkeiten implementiert werden soll, muss das Skript beim Setzen der Sicherheitseinstellung einen Eintrag in der Datei /etc/security/aixpert/core/undo.xml für den Undo hinzufügen. Der Eintrag hat fast das gleiche Format wie Einträge in /etc/security/aixpert/core/appliedaixpert.xml. Der Eintrag benötigt einen Namen, dieser wird immer von aixpert über die Variable AIXPERT_NAME übergeben.
Alle Standard-Skripte, die ein Undo unterstützen, erwarten immer als letztes Argument den Namen einer Regel. Da wir bisher keine Argumente haben, erweitern wir unser Skript und fügen zunächst am Anfang einen Kommentar zu Kommandozeilen-Argumente, Ausgabe und Beschreibung des Skripts hinzu:
# Command Line Arguments : This script expects exactly one command line argument.
# This argument should be the rulename.
# Syntac - local_chsshdconf rulename
#
# OUTPUT : None
#
# Description : This script sets the value of PermitRootLogin in /etc/ssh/sshd_config
# to 'no'.
# It dynamically generates the undo rules and scripts.
# This script should be run with superuser privileges.
#
Die Überprüfung der Argumente und die Meldung zur Benutzung muss entsprechend auch abgeändert werden:
if [ $# -ne 1 ]
then
echo "Usage : local_chsshdconf rulename\n"
exit 1
fi
Da das Skript über einen AIXPertEntry der XML-Datei custom/sshd.xml aufgerufen wird, müssen wir diesen XML-Eintrag auch entsprechend um das Argument erweitern:
/etc/security/aixpert # cat custom/sshd.xml
<?xml version="1.0" encoding="UTF-8"?>
<AIXPertSecurityHardening>
<AIXPertEntry name="test_permitrootlogin" function="permitrootlogin">
<AIXPertRuleType type="TEST"/>
<AIXPertDescription>Ensure that PermitRootLogin is False.</AIXPertDescription>
<AIXPertPrereqList>openssh.base.server</AIXPertPrereqList>
<AIXPertCommand>/etc/security/aixpert/bin/local_chsshdconf</AIXPertCommand>
<AIXPertArgs>test_permitrootlogin</AIXPertArgs>
<AIXPertGroup>SSH policy rules</AIXPertGroup>
</AIXPertEntry>
</AIXPertSecurityHardening>
/etc/security/aixpert #
Der Name des AIXPertEntry wird als Argument für den Skript-Aufruf verwendet. Im Skript steht dieser Name dann über die Variable „$1“ zur Verfügung.
Ob ein Undo-Eintrag generiert werden soll, oder nicht wird bei allen Standard-Skripten über das Setzen der Variablen mit Namen undo implementiert. Am Anfang des Skriptes wird der Wert dieser Variablen auf den Wert „0“ (kein Undo-Eintrag generieren) gesetzt:
# A value of 0 indicates that Undo rule need not be created.
# This variable will be set later in the script if there is anything to be undone
undo=0
Findet eine Überprüfung der Sicherheitseinstellung statt (AIXPERT_CHECK=1), dann wird kein Undo-Eintrag generiert und die Variable undo behält den Wert „0“. Wird die Sicherheitseinstellung gesetzt, wird die Variable undo auf den Wert „1“ gesetzt:
# Generate a dynamic undo rule
undo=1
Am Ende des Skripts (nach den Teilen für Überprüfung und Setzen der Sicherheitseinstellung) wird dann die Variable undo geprüft, und falls diese den Wert „1“ hat, wird ein XML-Eintrag für den Undo in /etc/security/aixpert/core/undo.xml hinzugefügt. Für den Fall das das Skript die Möglichkeit 2 von oben realisiert, wird zusätzlich ein Undo-Skript im Verzeichnis /etc/security/aixpert/undo angelegt. Der XML-Eintrag referenziert dann dieses generierte Skript.
if [ $undo -eq 1 ]
then
time=`date +%s`
# Create Undo script $SCPTDIR/Undo$1$time
…
fi
Da das Undo bei AIX Security Expert mehrstufig funktioniert, wird über „date +%s“ ein eindeutiger Zeitstempel generiert. Die Variable SCPTDIR besitzt den Wert /etc/security/aixpert/undo (dies ist in /etc/security/aixpert/bin/initialize_variables festgelegt). Die Variable „$1“ beinhaltet den Regelnamen der beim Aufruf des Skripts als letztes Argument mitgegeben wird.
Das Abändern von PermitRootLogin auf „yes“ machen wir wir nicht ganz elegant mit dem folgenden Zweizeiler:
sed -e 's/\(PermitRootLogin\) \(no\)/\1 yes/' /etc/ssh/sshd_config >/etc/ssh/sshd_config.new
mv /etc/ssh/sshd_config.new /etc/ssh/sshd_config
Hinweis: Wir werden später noch die (bessere) Möglichkeit 3 implementieren und bemühen uns daher hier nicht um eine gute Lösung.
Wie bei dem Skript für die Sicherheitseinstellungen local_chsshdconf soll das ganze mitprotokolliert werden. Wir übernehmen daher wieder ein paar Zeilen aus den Standard-Skripten. Insgesamt sollte dann das folgende Skript automatisch in /etc/security/aixpert/undo erzeugt werden:
#!/usr/bin/ksh
export PATH=/usr/bin:/usr/sbin:$PATH
exec 1>>$LOG
exec 2>&1
set -x
date
echo $0
sed -e 's/\(PermitRootLogin\) \(no\)/\1 yes/' /etc/ssh/sshd_config >/etc/ssh/sshd_config.new
mv /etc/ssh/sshd_config.new /etc/ssh/sshd_config
Dazu bauen wir die folgenden Zeilen in unser Skript local_chsshdconf ein:
echo "#!/usr/bin/ksh\nexport PATH=/usr/bin:/usr/sbin:\$PATH\n" >$SCPTDIR/Undo$2$time
echo "exec 1>>\$LOG\nexec 2>&1\nset -x\ndate\necho" '$0' >>$SCPTDIR/Undo$2$time
echo "sed -e 's/\\(PermitRootLogin\\) \\(no\\)/\\1 yes/' /etc/ssh/sshd_config >/etc/ssh/sshd_config.new\n" >$SCPTDIR/Undo$2$time
echo "mv /etc/ssh/sshd_config.new /etc/ssh/sshd_config\n" >>$SCPTDIR/Undo$2$time
chmod ug+x $SCPTDIR/Undo$2$time
Als nächstes muss ein Eintrag in /etc/security/aixpert/core/undo.xml erzeugt werden. Der Dateipfad ist in der Variablen UNDOXML hinterlegt. Ist unser Skript das erste Skript das bei der Anwendung aufgerufen wird, dann gibt es die Datei undo.xml noch nicht. Dieser Fall muss überprüft werden, und falls dies der Fall ist, muss eine minimale Version der Datei angelegt werden. Dazu verwenden die Standard-Skripte die folgenden Zeilen:
# Check if UNDOXML file has <AIXPertUndo> tag or not
empty=`grep "^<AIXPertUndo>" $UNDOXML`
if [ "$empty" = "" ]
then
echo "\n<AIXPertUndo>\n</AIXPertUndo>" >> $UNDOXML
fi
Regeln die in /etc/security/aixpert/core/appliedaixpert.xml und /etc/security/aixpert/core/undo.xml eingetragen werden, haben einen leicht abgeänderten Regelnamen gegenüber den in der ursprünglichen XML-Datei verwendeten Namen. Der AIX Security Expert genieriert bei der Anwendung eines Profils oder Sicherheitslevels auf ein System eine eindeutige 8 stellige hexadezimale ID, die mit einem Unterstrich getrennt an den ursprünglichen Regelnamen angefügt wird. Aus test_permitrootlogin wird dann z.B. test_permitrootlogin_C515EA26. Dieser verlängerte Regelname wird in der Variablen AIXPERT_NAME abgespeichert. Die Beschreibung der Regel (AIXPertDescription) wird in AIXPERT_DESC abgespeichert und Informationen für sprachabhängige Meldungen in AIXPERT_DESC_CATMSGINFO. Diese drei Variablen werden über das Environment an das Skript übergeben. Typischerweise werden diese 3 Variablen dann wie folgt neuen Variablen zugewiesen:
# Get the rulename and put it in undo rule
name=`echo $AIXPERT_NAME`
# Get the rule description & pass it to undo rule
desc=`echo $AIXPERT_DESC`
desc_catmsginfo=`echo $AIXPERT_DESC_CATMSGINFO`
undomsg=`/usr/bin/dspmsg -s 49 aixpert.cat 1 "Undo action for: "`
Nun kann der notwendige XML-Eintrag in /etc/security/aixpert/core/undo.xml vorgenommen werden. Der Eintrag sollte in etwa so aussehen:
<AIXPertEntry name="test_permitrootlogin_C515EA26">
<AIXPertRuleType type="Undo"/>
<AIXPertDescription catalog="aixpert.cat" setNum="101" msgNum="15">Undo action for: " Ensure that PermitRootLogin is False."</AIXPertDescription>
<AIXPertPrereqList/>
<AIXPertCommand>/etc/security/aixpert/bin/local_chsshdconf</AIXPertCommand>
<AIXPertArgs> </AIXPertArgs>
<AIXPertGroup>SSH policy rules</AIXPertGroup>
</AIXPertEntry>
Die Standard-Skripte fügen den Eintrag mit Hilfe des folgenden awk-Kommandos der XML-Datei hinzu:
# Add an undo XML rule to the file $UNDOXML
awk -v rulepart1="\t<AIXPertEntry name=\"$name\">\n\
\t\t<AIXPertRuleType type=\"Undo\"/>\n"\
-v rulepart2="\t\t<AIXPertDescription ${desc_catmsginfo}>$undomsg \"$desc\"</AIXPertDescription>\n\
\t\t<AIXPertPrereqList/>\n"\
-v rulepart3="\t\t<AIXPertCommand>$SCPTDIR/Undo$2$time</AIXPertCommand>\n\
\t\t<AIXPertArgs/>\n\t\t<AIXPertGroup>Miscellaneous Rules</AIXPertGroup>\n\
\t</AIXPertEntry>" '{if(match($0,"^[\t ]*</AIXPertUndo>")==0) print $0;
else print rulepart1 rulepart2 rulepart3 "\n" $0}' $UNDOXML >$TMP$PID
if [ $? -eq 0 ] ; then
mv $TMP$PID $UNDOXML
fi
Die beiden Variablen TMP und PID werden typischerweise am Anfang des Skripts gesetzt, direkt nachdem die Datei /etc/security/aixpert/bin/initialize_variables eingelesen wurde:
TMP=/etc/security/aixpert/tmp/permitrootlogin
PID=$$
Insgesamt ergibt sich dann die folgende Version des Skripts:
/etc/security/aixpert # cat bin/local_chsshdconf
#! /bin/ksh
#
# Command Line Arguments : This script expects exactly one command line argument.
# This argument should be the rulename.
# Syntac - local_chsshdconf rulename
#
# OUTPUT : None
#
# Description : This script sets the value of PermitRootLogin in /etc/ssh/sshd_config
# to 'no'.
# It dynamically generates the undo rules and scripts.
# This script should be run with superuser privileges.
#
export PATH=/usr/bin:/usr/sbin:$PATH
# Initialize variables AIXPERT_FIFO, LOG, REPORT, SCPTDIR and UNDOXML
. /etc/security/aixpert/bin/initialize_variables
TMP=/etc/security/aixpert/tmp/permitrootlogin
PID=$$
# Log output and errors to /etc/security/aixpert/log/aixpert.log
exec 1>>$LOG
exec 2>&1
# echo all the commands and the current time and date to the AIXpert log
set -x
date
echo $0 $@ AIXPERT_CHECK_REPORT=$AIXPERT_CHECK_REPORT BASE_REPT=$BASE_REPT DETAILED_REPT=$DETAILED_REPT
if [ $# -ne 1 ]
then
echo "Usage : local_chsshdconf rulename\n"
exit 1
fi
# A value of 0 indicates that Undo rule need not be created.
# This variable will be set later in the script if there is anything to be undone
undo=0
# Check whether AIXPERT_CHECK_REPORT environment variable is set or not.
report=`echo $AIXPERT_CHECK_REPORT`
BrType=`echo $BASE_REPT`
DrType=`echo $DETAILED_REPT`
if [ "$report" = "1" ]
then
ret=1
permit=$( awk '$1 ~ /^PermitRootLogin$/ { print $2; }' /etc/ssh/sshd_config 2>/dev/null | tail -n 1 )
case "${permit}" in
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]) ret=0 ;;
esac
if [ $ret = 1 ]
then
if [ "$BrType" = "1" ]
then
echo "Base Compliance Report\n";
printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" PermitRootLogin no $permit >>$TMPREPT
elif [ "$DrType" = "1" ]
then
echo "Description Report\n";
printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" PermitRootLogin no $permit >>$TMPREPT
else
printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" PermitRootLogin no $permit >>$REPORT
printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" PermitRootLogin no $permit >>$AIXPERT_FIFO
fi
fi
exit $ret
fi
# Generate a dynamic undo rule
undo=1
firstOccurrence=true
while read -r line
do
case "$line" in
PermitRootLogin*)
if $firstOccurrence
then
print "PermitRootLogin no"
firstOccurrence=false
fi
;;
*)
print $line ;;
esac
done </etc/ssh/sshd_config >/etc/ssh/sshd_config.new
$firstOccurrence && print "PermitRootLogin no" >>/etc/ssh/sshd_config.new
cp /etc/ssh/sshd_config.new /etc/ssh/sshd_config
rm /etc/ssh/sshd_config.new
if [ $undo -eq 1 ]
then
time=`date +%s`
# Create Undo script $SCPTDIR/Undo$1$time
echo "#!/usr/bin/ksh\nexport PATH=/usr/bin:/usr/sbin:\$PATH\n" >$SCPTDIR/Undo$2$time
echo "exec 1>>$LOG\nexec 2>&1\nset -x\ndate\necho" '$0' >>$SCPTDIR/Undo$2$time
echo "sed -e 's/\\(PermitRootLogin\\) \\(no\\)/\\1 yes/' /etc/ssh/sshd_config >/etc/ssh/sshd_config.new\n" >>$SCPTDIR/Undo$2$time
echo "mv /etc/ssh/sshd_config.new /etc/ssh/sshd_config\n" >>$SCPTDIR/Undo$2$time
chmod ug+x $SCPTDIR/Undo$2$time
# Check if UNDOXML file has <AIXPertUndo> tag or not
empty=`grep "^<AIXPertUndo>" $UNDOXML`
if [ "$empty" = "" ]
then
echo "\n<AIXPertUndo>\n</AIXPertUndo>" >> $UNDOXML
fi
# Get the rulename and put it in undo rule
name=`echo $AIXPERT_NAME`
# Get the rule description & pass it to undo rule
desc=`echo $AIXPERT_DESC`
desc_catmsginfo=`echo $AIXPERT_DESC_CATMSGINFO`
undomsg=`/usr/bin/dspmsg -s 49 aixpert.cat 1 "Undo action for: "`
# Add an undo XML rule to the file $UNDOXML
awk -v rulepart1="\t<AIXPertEntry name=\"$name\">\n\
\t\t<AIXPertRuleType type=\"Undo\"/>\n"\
-v rulepart2="\t\t<AIXPertDescription ${desc_catmsginfo}>$undomsg \"$desc\"</AIXPertDescription>\n\
\t\t<AIXPertPrereqList/>\n"\
-v rulepart3="\t\t<AIXPertCommand>$SCPTDIR/Undo$2$time</AIXPertCommand>\n\
\t\t<AIXPertArgs/>\n\t\t<AIXPertGroup>Miscellaneous Rules</AIXPertGroup>\n\
\t</AIXPertEntry>" '{if(match($0,"^[\t ]*</AIXPertUndo>")==0) print $0;
else print rulepart1 rulepart2 rulepart3 "\n" $0}' $UNDOXML >$TMP$PID
if [ $? -eq 0 ] ; then
mv $TMP$PID $UNDOXML
fi
fi
exit 0
/etc/security/aixpert #
Bevor wir das Skript ausprobieren, entfernen wir alle aktuell gesetzten Regeln:
/etc/security/aixpert # aixpert -u
/etc/security/aixpert # aixpert -u
There are no security rules to undo in file /etc/security/aixpert/core/appliedaixpert.xml
/etc/security/aixpert # rm check_report.txt core/appliedaixpert.* core/undo.* log/* tmp/* undo/*
rm: cannot remove directory undo/data
/etc/security/aixpert #
Nun wenden wir zunächst unser XML-Profil custom/sshd.xml an:
/etc/security/aixpert # aixpert -f custom/sshd.xml
Processedrules=1 Passedrules=1 PrereqFailedrules=0 Failedrules=0 Level=TEST
Input file=custom/sshd.xml
/etc/security/aixpert #
Wir überprüfen zunächst die Datei undo.xml:
/etc/security/aixpert # cat /etc/security/aixpert/core/undo.xml
<AIXPertUndo>
<AIXPertEntry name="test_permitrootlogin_4E952A4B">
<AIXPertRuleType type="Undo"/>
<AIXPertDescription catalog="" setNum="" msgNum="">Undo action for: "Ensure that PermitRootLogin is False."</AIXPertDescription>
<AIXPertPrereqList/>
<AIXPertCommand>/etc/security/aixpert/undo/Undo1670354323</AIXPertCommand>
<AIXPertArgs/>
<AIXPertGroup>Miscellaneous Rules</AIXPertGroup>
</AIXPertEntry>
</AIXPertUndo>
/etc/security/aixpert #
Diese hat den erwarteten Inhalt. Das hinterlegte AIXPertCommand ist /etc/security/aixpert/undo/Undo1670354323. Das sollte das von local_chsshdconf generierte Undo-Skript sein. Wir überprüfen den Inhalt des Skripts:
/etc/security/aixpert # cat /etc/security/aixpert/undo/Undo1670354323
#!/usr/bin/ksh
export PATH=/usr/bin:/usr/sbin:$PATH
exec 1>>/etc/security/aixpert/log/aixpert.log
exec 2>&1
set -x
date
echo $0
sed -e 's/\(PermitRootLogin\) \(no\)/\1 yes/' /etc/ssh/sshd_config >/etc/ssh/sshd_config.new
mv /etc/ssh/sshd_config.new /etc/ssh/sshd_config
/etc/security/aixpert #
Dies ist der erwartete generierte Inhalt!
Als letztes überprüfen wir noch den Wert von PermitRootLogin:
# grep ^PermitRootLogin /etc/ssh/sshd_config
PermitRootLogin no
#
Dies ist der durch die Sicherheitseinstellung gewünschte Wert!
Als nächstes führen wir ein Undo aus:
# aixpert -u
#
Die Regel test_permitrootlogin müsste sowohl aus der Datei appliedaixpert.xml, als auch aus der Datei undo.xml, entfernt worden sein. Wir überprüfen das:
# cat /etc/security/aixpert/core/appliedaixpert.xml
<?xml version="1.0"?>
<AIXPertSecurityHardening>
</AIXPertSecurityHardening>
# cat /etc/security/aixpert/core/undo.xml
<AIXPertUndo>
</AIXPertUndo>
#
In beiden Dateien wurde die Regel entfernt! Als letztes Überprüfen wir noch den Wert von PermitRootLogin. Der Undo sollte den Wert wieder auf yes gesetzt haben:
# grep ^PermitRootLogin /etc/ssh/sshd_config
PermitRootLogin yes
#
Der Undo hat also wie gewünscht funktioniert. Vor dem Einsatz in der Praxis, sollte das Skript aber noch um eine bessere Fehlererkennung und Behandlung erweitert werden.