Under Construction
Aixpert Skript zu Einstellungen von SSHD
In dem bisher gezeigten Beispiel kann nur das Attribut PermitRootLogin auf „yes“ gesetzt werden und bei einem Undo zurück auf „no“. Es gibt neben PermitRootLogin eine ganze Reihe weitere sicherheitsrelevante Attribute, wie Ciphers, DisableForwarding oder PermitEmptyPasswords. Anstelle für jedes dieser Attribute ein eigenes Skript in Anlehnung des weiter oben entwickelten Skripts zu schreiben, bietet es sich an, das bisherige Skript anzupassen und beliebige Attribute und Werte zu unterstützen. Dazu müssen Attribut und gewünschter Wert als Argumente übergeben werden können, wie z.B. beim Standard-Skript chusrattr. Das bisher einzige Argument, der Regelname, sollte wie bei chusrattr optional sein. Ist das Argument vorhanden, soll ein Undo-Eintrag erzeugt werden, ist das Argument nicht vorhanden, wird kein Undo-Eintrag erzeugt.
Zunächst ändern wir die Beschreibung des Skripts local_chsshdconf wie folgt ab:
# Command Line Arguments : This script expects one or two command line arguments.
# The first argument should be of the form
# 'Attr=value', where 'Attr' is a valid keyword for sshd_config
# and 'value' is the value to set or to check for.
# The second argument is optional and if provided,
# indicates that the undo xml rule has to be
# generated.
# Syntac - local_chsshdconf Attr=value [rulename]
#
# OUTPUT : None
#
# Description : This script changes the attribute 'Attr' to
# the value 'value' in /etc/ssh/sshd_config.
# It dynamically generates an undo XML rule with
# shortname as "Undo$2_<timestamp>" if the second
# argument is provided.
# This script should be run with superuser privileges.
Als Pfad-Präfix für temporäre Dateien verwenden wir nun /etc/security/aixpert/tmp/local_chsshdconf (Variable TMP):
# Initialize variables AIXPERT_FIFO, LOG, REPORT, SCPTDIR and UNDOXML
. /etc/security/aixpert/bin/initialize_variables
TMP=/etc/security/aixpert/tmp/local_chsshdconf
PID=$$
Die Überprüfung auf die korrekte Anzahl von Argumenten muss ebenfalls abgeändert werden. Das Skript muss mit einem oder zwei Argumenten aufgerufen werden:
if [ $# -lt 1 ] || [ $# -gt 2 ]
then
echo "Usage : local_chsshdconf Attr=value [rulename]\n"
exit 1
fi
Das zu setzende oder zu überprüfende Attribut wird zusammen mit dem Wert als ein Argument der Form „Attr=value“ übergeben. Das Argument muss in den Attributnamen und den Wert aufgeteilt werden:
# Determine the user attribute that has to be changed.
sshdattr=`echo $1 | awk -F "=" '{print $1; if(NF != 2) exit 1}'`
if [ $? -ne 0 ] || [ "$sshdattr" = "" ]
then
dspmsg -s 4 aixpert.cat 1 "Usage : local_chsshdconf Attr=value [Rulename]\n"
exit 1
fi
# Determine the value that is being assigned to the $sshdattr
value=`echo $1 | awk -F "=" '{print $2}'`
Der Attributname wird in der Variablen sshdattr gespeichert und der Wert in der Variablen value.
Für die Überprüfung von Attributen schreiben wir eine kleine Funktion, die wir am Anfang des Skripts plazieren. Die Funktion gibt mittels „sshd -T“ die effektive Konfiguration aus, sucht die Zeile mit dem gewünschten Attribut und liefert den zugehörigen Wert zurück.
function getEffectiveSshdValue
{
typeset -l keyword="$1" # translate to lower case
typeset key
typeset value="invalid"
sshd -T | grep -w "$keyword" | read key value
print "$value"
}
Mit Hilfe dieser Funktion lässt sich dann die Überprüfung eines Attributs umschreiben. Den bisherigen Check:
defvalue=`awk '$1 ~ /^PermitRootLogin$/ { print $2; }' /etc/ssh/sshd_config 2>/dev/null | tail -n 1`
case "$defvalue" in
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]) ret=0 ;;
esac
schreiben wir dann wie folgt um:
defvalue=`getEffectiveSshdValue "$sshdattr"`
[ "$defvalue" = "$value" ] && ret=0
Die Meldungen falls die Überprüfung nicht erfolgreich ist (gesetzter Wert weicht vom Soll-Wert ab), müssen ebenfalls etwas angepasst werden:
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" $sshdattr
$value $defvalue >>$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" $sshdattr
$value $defvalue >>$TMPREPT
else
printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" $sshdattr
$value $defvalue >>$REPORT
printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" $sshdattr
$value $defvalue >>$AIXPERT_FIFO
fi
fi
Um einen Test-Lauf für die geänderte Überprüfung zu starten, muss noch die XML-Datei custom/sshd.xml angepasst werden:
/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>PermitRootLogin=no test_permitrootlogin</AIXPertArgs>
<AIXPertGroup>SSHD policy rules</AIXPertGroup>
</AIXPertEntry>
</AIXPertSecurityHardening>
/etc/security/aixpert #
Der Wert von PermitRootLogin ist aktuell:
# grep ^PermitRootLogin /etc/ssh/sshd_config
PermitRootLogin yes
#
Eine Überprüfung sollte damit nicht erfolgreich sein:
# aixpert -c -P custom/sshd.xml
Processedrules=1 Passedrules=0 Failedrules=1 Level=TEST
Input file=custom/sshd.xml
#
Wie erwartet schlägt die Überprüfung fehl (Failedrules=1). Wir ändern den Wert von PermitRootLogin auf „no“ und starten eine weitere Überprüfung:
# aixpert -c -P custom/sshd.xml
Processedrules=1 Passedrules=1 Failedrules=0 Level=TEST
Input file=custom/sshd.xml
#
Jetzt ist die Überprüfung erfolgreich. Damit erlaubt das modifizierte Skript schon mal die Überprüfung von beliebigen Attributen des sshd.
Als nächstes implementieren wir das Setzen von beliebigen Attributen in /etc/ssh/sshd_config. Auch hier verwenden wir eine Funktion, die wieder am Anfang des Skripts stehen soll:
function setSshdValue
{
typeset -l keyToChange="$1"
typeset newValue="$2"
typeset -l lowerCaseKey
changed=false
while read -r line
do
print "$line" | read -r key value rest
lowerCaseKey="$key"
case "$lowerCaseKey" in
$keyToChange)
print "$key $newValue"
changed=true
;;
*) print "$line" ;;
esac
done </etc/ssh/sshd_config >/etc/ssh/sshd_config.new
${change} || print "$key $newValue" >>/etc/ssh/sshd_config.new
cp /etc/ssh/sshd_config.new /etc/ssh/sshd_config
rm -f /etc/ssh/sshd_config.new
}
Mittels einer while-Schleife wird Zeile für Zeile nach dem zu ändernden Attributnamen gesucht. Wird dieser gefunden, werden Name und neuer Wert ausgegeben. Ansonsten werden die Zeilen unverändert ausgegeben. Wurde das Attribut nicht gefunden, wird am Ende Name und neuer Wert ausgegeben. Alle Ausgaben werden in eine Zwischendatei (/etc/ssh/sshd_config.new) umgeleitet.
Die bisherigen Zeilen für das Setzen von PermitRootLogin (im Skript nach der Überprüfung), können dann entfernt und durch den folgenden Aufruf der obigen Funktion ersetzt werden:
setSshdValue "$sshdattr" "$value"
Bevor wir einen Test-Lauf der neuen Skript-Version machen, setzen wir PermitRootLogin auf „yes“ und entfernen alle aktiven 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.xml log/* tmp/* undo/*
rm: check_report.txt: No such file or directory
rm: cannot remove directory undo/data
/etc/security/aixpert # grep ^PermitRootLogin /etc/ssh/sshd_config
PermitRootLogin yes
/etc/security/aixpert #
Wir wenden jetzt die Regel für das Setzen von PermitRootLogin erneut 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 #
Laut Ausgabe wurde die Regel erfolgreich abgearbeitet (Passedrules=1). Eine kurze Überprüfung mit „aixpert -c“ und grep zeigt das PermitRootLogin auf „no“ gesetzt wurde:
# aixpert -c
Processedrules=1 Passedrules=1 Failedrules=0 Level=TEST
Input file=/etc/security/aixpert/core/appliedaixpert.xml
# grep ^PermitRo /etc/ssh/sshd_config
PermitRootLogin no
#
Als letztes muss noch die Undo-Funktionalität angepasst werden. Für einen Undo muss das Skript lediglich mit dem Attributnamen und dem ursprünglichen Wert des Attributs aufgerufen werden. Ein Regelname darf in diesem Falle nicht angegeben werden, da beim Undo kein neuer Undo-Eintrag in /etc/security/aixpert/core/undo.xml gemacht werden soll.
Wir überprüfen ob das Skript mit 2 Argumenten, also mit Regelname, aufgerufen wurde. Ist das der Fall, wird der aktuelle Wert des Attributs ermittelt und in der Variablen defvalue abgespeichert. Außerdem wird dann die Variable undo gesetzt.
# This script generates Undo rule if the number of arguments is 2,
# otherwise it works as undo script.
if [ $# -eq 2 ]
then
# Determine the current value of $sshdattr from the effective configuration
defvalue=`getEffectiveSshdValue "$sshdattr"`
…
# Generate a dynamic undo rule
undo=1
fi
Das Skript muss nun kein Undo-Skript mehr erzeugen, da das Skript selbst für den Undo aufgerufen werden kann. Die entsprechenden Zeilen im Skript zum Erzeugen des Undo-Skripts entfallen damit.
Der Undo-Eintrag in der XML-Datei /etc/security/aixpert/core/undo.xml muss aber weiterhin vorgenommen werden. Allerdings wird jetzt als AIXPertCommand das Skript selbst hinterlegt und als Argument (AIXPertArgs) wird der Attributname zusammen mit dem ursprünglichen Wert ($defvalue) angegeben:
# 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\"</AIXPertDes
cription>\n\
\t\t<AIXPertPrereqList/>\n"\
-v rulepart3="\t\t<AIXPertCommand>/etc/security/aixpert/bin/local_chsshdconf</AIXPertCo
mmand>\n\
\t\t<AIXPertArgs>$sshdattr=$defvalue</AIXPertArgs>\n\
\t\t<AIXPertGroup>SSHD policy rules</AIXPertGroup>\n\
\t</AIXPertEntry>" '{if(match($0,"^[\t ]*</AIXPertUndo>")==0) print $0;
else print rulepart1 rulepart2 rulepart3 "\n" $0}' $UNDOXML >$TMP$PID
Insgesamt ergibt sich dann die folgende Version des Skripts:
/etc/security/aixpert # cat bin/local_chsshdconf
#! /bin/ksh
#
# Copyright (c) 2022 by PowerCampus 01 GmbH
#
# Anyone is free to copy, publish, use, or distribute this software,
# for any purpose, commercial or non-commercial, and by any means,
# as long as this copyright notice is kept.
# Modification of this software is allowed, as long as this copyright
# notice is kept, and a notice is placed in the software that indicates
# that the software has been modified. It is not allowed to sell this
# software without the written permission of PowerCampus 01.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
#
# Command Line Arguments : This script expects one or two command line arguments.
# The first argument should be of the form
# 'Attr=value', where 'Attr' is a valid keyword for sshd_config
# and 'value' is the value to set or to check for.
# The second argument is optional and if provided,
# indicates that the undo xml rule has to be
# generated.
# Syntax - local_chsshdconf Attr=value [rulename]
#
# OUTPUT : None
#
# Description : This script changes the attribute 'Attr' to
# the value 'value' in /etc/ssh/sshd_config.
# It dynamically generates an undo XML rule with
# shortname as "Undo$2_<timestamp>" if the second
# argument is provided.
# This script should be run with superuser privileges.
#
function getEffectiveSshdValue
{
typeset -l keyword="$1"
typeset key
typeset value="invalid"
sshd -T | grep -w "$keyword" | read key value
print "$value"
}
function setSshdValue
{
typeset -l keyToChange="$1"
typeset newValue="$2"
typeset -l lowerCaseKey
changed=false
while read -r line
do
print "$line" | read -r key value rest
lowerCaseKey="$key"
case "$lowerCaseKey" in
$keyToChange)
print "$key $newValue"
changed=true
;;
*) print "$line" ;;
esac
done </etc/ssh/sshd_config >/etc/ssh/sshd_config.new
${change} || print "$key $newValue" >>/etc/ssh/sshd_config.new
cp /etc/ssh/sshd_config.new /etc/ssh/sshd_config
rm -f /etc/ssh/sshd_config.new
}
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/local_chsshdconf
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 [ $# -lt 1 ] || [ $# -gt 2 ]
then
echo "Usage : local_chsshdconf Attr=value [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`
# Determine the user attribute that has to be changed.
sshdattr=`echo $1 | awk -F "=" '{print $1; if(NF != 2) exit 1}'`
if [ $? -ne 0 ] || [ "$sshdattr" = "" ]
then
dspmsg -s 4 aixpert.cat 1 "Usage : local_chsshdconf Attr=value [Rulename]\n"
exit 1
fi
# Determine the value that is being assigned to the $sshdattr
value=`echo $1 | awk -F "=" '{print $2}'`
# This script generates Undo rule if the number of arguments is 2,
# otherwise it works as undo script.
if [ $# -eq 2 ]
then
# Determine the current value of $sshdattr from the effective configuration
defvalue=`getEffectiveSshdValue "$sshdattr"`
if [ "$report" = "1" ]
then
ret=1
[ "$defvalue" = "$value" ] && ret=0
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" $sshdattr $value $defvalue >>$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" $sshdattr $value $defvalue >>$TMPREPT
else
printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" $sshdattr $value $defvalue >>$REPORT
printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" $sshdattr $value $defvalue >>$AIXPERT_FIFO
fi
fi
exit $ret
fi
# Generate a dynamic undo rule
undo=1
fi
setSshdValue "$sshdattr" "$value"
if [ $undo -eq 1 ]
then
# 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>/etc/security/aixpert/bin/local_chsshdconf</AIXPertCommand>\n\
\t\t<AIXPertArgs>$sshdattr=$defvalue</AIXPertArgs>\n\
\t\t<AIXPertGroup>SSHD policy 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 einen erneuten Test-Lauf der finalen Skript-Version machen, setzen wir PermitRootLogin wieder auf „yes“ und entfernen alle aktiven 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.xml log/* tmp/* undo/*
rm: check_report.txt: No such file or directory
rm: cannot remove directory undo/data
/etc/security/aixpert # grep ^PermitRootLogin /etc/ssh/sshd_config
PermitRootLogin yes
/etc/security/aixpert #
Wir wenden die Regel wieder auf unser System 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 schauen uns den Eintrag in der undo.xml an:
/etc/security/aixpert # cat /etc/security/aixpert/core/undo.xml
<AIXPertUndo>
<AIXPertEntry name="test_permitrootlogin_DD8096ED">
<AIXPertRuleType type="Undo"/>
<AIXPertDescription catalog="" setNum="" msgNum="">Undo action for: "Ensure that PermitRootLogin is False."</AIXPertDescription>
<AIXPertPrereqList/>
<AIXPertCommand>/etc/security/aixpert/bin/local_chsshdconf</AIXPertCommand>
<AIXPertArgs>PermitRootLogin=yes</AIXPertArgs>
<AIXPertGroup>SSHD policy rules</AIXPertGroup>
</AIXPertEntry>
</AIXPertUndo>
/etc/security/aixpert #
Der Undo-Eintrag ruft das obige Skript auf und verwendet dazu das Argument „PermitRootLogin=yes“, also den ursprünglichen Wert von PermitRootLogin.
Als letztes überprüfen wir ob das Undo korrekt funktioniert:
# aixpert -u
#
Eine kurze Überprüfung zeigt das die Einträge aus appliedaixpert.xml und undo.xml entfernt wurden und der Wert von PermitRootLogin wieder „yes“ ist:
/etc/security/aixpert # cat core/appliedaixpert.xml
<?xml version="1.0"?>
<AIXPertSecurityHardening>
</AIXPertSecurityHardening>
/etc/security/aixpert # cat core/undo.xml
<AIXPertUndo>
</AIXPertUndo>
/etc/security/aixpert # grep ^PermitRootLogin /etc/ssh/sshd_config
PermitRootLogin yes
/etc/security/aixpert #