Kategorien
Linux Sicherheit

Nginx User Authentifizierung mit pam_script

Eigentlich wäre pam_script dazu gedacht nach erfolgreicher Anmeldung ein Script auszuführen welches irgendwelche Änderungen oder Anpassungen vornimmt. Zumindest lese ich das so aus der Man-Page… 🙂

Nachdem Nginx in Sachen Authentifizierung dem Apache doch an einigen Stellen hinterher hinkt, habe ich mich nach einer Lösung umgesehen um für eine Web-Applikation ein einfaches Anmeldesystem zu bauen welches in weiterer Folge dann auch die Möglichkeit bieten soll dass der User das Kennwort selbst verwaltet. Die Kennwörter sollen in einer MySQL Datenbank gespeichert werden bzw. nur deren Hashes.

Nach längerer erfolgloser Suche habe ich mir folgende Lösung selbst zusammen gezimmert, zuerst wird in der nginx-Config des betroffenen Webhost folgendes eingefügt:

location ^~ /test/ {
auth_pam „Please specify login and password“;
auth_pam_service_name „nginx-test“;
auth_pam_set_pam_env on;
}

Der „auth_pam_service_name“ muss mit dem Namen der Datei in /etc/pam.d/ überein stimmen – also nginx-test, dieses sieht wie folgt aus:

auth    required    pam_script.so expose_authtok dir=/usr/share/libpam-script/pam-script.d/test/
account required    pam_permit.so

Im entsprechenden Verzeichnis „/usr/share/libpam-script/pam-script.d/test/
“ findet sich dann das eigentliche Script welches sich um die Authentifizierung kümmert – pam_script_auth und dieses sieht wie folgt aus:

#!/bin/bash

SID=$(echo $PAM_SERVICE|awk -F ’nginx-‚ ‚{print $2}‘)
PASSWORD=$(cat)

MD5USER=$(echo „$PAM_USER“|md5sum|awk ‚{print $1}‘)
MD5PASS=$(echo „$PAM_AUTHTOK“|md5sum|awk ‚{print $1}‘)

AUTHOK=$(mysql -s -u root -pmysqlkennwort testdb01 -e „SELECT count(*) FROM test_users WHERE sid=\“$SID\“ AND md5uname=\“$MD5USER\“ AND md5p
asswd=\“$MD5PASS\““)

if [ „X$AUTHOK“ == „X1“ ]; then
       exit 0
else
       exit 1
fi

Vom Aufbau recht einfach gehalten, „SID“ ist quasi die Service ID – und diese hole ich mir vom „nginx-test“ indem ich „nginx-“ einfach wegschneide (dient der Erkennung von welchem Webhost die Anmeldung kam – es wird für jeden Webhost eine eigene verwendet!). User und Kennwort verarbeite ich als MD5SUM (man könnte hier auch sha256sum oder sha512sum verwenden), dadurch vermeide ich Probleme die es beim Select geben könnte!

Der Select wird dann auf eine Tabelle los gelassen deren Inhalt im einfachsten Fall einfach nur aus drei Feldern besteht – der „SID“, dem Benutzer-Namen als MD5 Hash und dem Kennwort als MD5 Hash. In den entsprechenden Feldern „sid“, „md5uname“ und „md5passwd“.

Wird ein User gefunden und somit 1 zurück gegeben, dann beendet sich das Script mit dem Rückgabewert „0“ welches ein Login zu lässt. In allen anderen Fällen gibt es ein „1“ zurück und somit ist der Login fehlgeschlagen.

Die Lösung habe ich in gut 30 Minuten zusammengezimmert und sie funktioniert soweit mal, mich würde jetzt interessieren ob ihr hier irgendwelche Sicherheitsbedenken habt!?

Günstige SSL Zertifikate – Nginx/Dovecot/Postfix

Nachdem es inzwischen wohl nicht mehr unter Sport sondern eher zum guten Ton gehört verschlüsselte SSL Verbindungen mit zu schneiden oder per Man-In-The-Middle Attacke abzuhören (zumindest für den einen oder anderen Service-Dienst unserer lieben Politiker), hatte ich mal wieder die Aufgabe für einen Server ein SSL Zertifikat zu organisieren.

Die Preise fallen ja in letzter Zeit ein wenig und so muss man zum einfachen Absichern einer Web-Anwendung nicht mehr unbedingt hunderte Euros im Jahr ausgeben.

Wer nur eine einzige Domain mit ssl-Zertifakt versorgen will kann sich bei ssls.com das günstiges Zertifikat für knapp 5 $ im Jahr (bei 5 Jahres Vertrag) holen!

Die einzelnen Schritte sind recht einfach – erst das gewünschte Produkt in den Warenkorb und anschließend bezahlen, jetzt noch den CSR einreichen und nach kurzer Zeit bekommt man eine Zip Datei geliefert in der alles Nötige enthalten ist.

Das CSR generiert man sehr schnell mit folgendem Befehl:

openssl req -nodes -newkey rsa:2048 -keyout myserver.key -out server.csr -subj „/C=AT/ST=Tirol/L=Kufstein/O=Meine Firma/OU=IT/CN=mysubdomain.mydomain.com“

 

Anschließend kann hat man die erwähnte CSR Datei.

Erhält man das E-Mail mit dem Zip-Archiv retour sollten darin neben dem eigentlichen Zertifikat „mysubdomain.mydomain.com.crt“ auch noch diese drei Dateien vorhanden sein:

AddTrustExternalCARoot.crt
COMODORSADomainValidationSecureServerCA.crt
COMODORSAAddTrustCA.crt

Aus den vier Dateien kann man jetzt ein Bundle schnüren in dem alle Infos enthalten sind die die verschiedenen Dienste so brauchen:

cat mysubdomain.mydomain.com.crt COMODORSAAddTrustCA.crt COMODORSADomainValidationSecureServerCA.crt AddTrustExternalCARoot.crt > ssl-bundle.crt

Jetzt beinhaltet die Datei ssl-bundle.crt auch die CA-Daten so dass die Clients das Zertifikat bis zum Aussteller erfolgreich zurück verfolgen können und keine Fehlermeldung mehr auswerfen.

Die Integration in nginx ist recht einfach und schnell:

einfach die folgenden Zeilen der vhost-Konfiguration hinzufügen

    ssl on;
    ssl_certificate /etc/ssl/certs/ssl-bundle.crt;
    ssl_certificate_key /etc/ssl/private/mysubdomain.mydomain.com.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers „ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4“;
    ssl_prefer_server_ciphers on;

Ganz ähnlich funktioniert es beim dovecot /etc/dovecot/dovecot.conf:

ssl = yes
ssl = required
ssl_protocols = !SSLv2 !SSLv3
ssl_cert =

ssl_key = Und auch den Postfix sollte man nicht vergessen (/etc/postfix/main.cf):

smtpd_tls_security_level = may
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
smtpd_tls_protocols = !SSLv2, !SSLv3
smtpd_tls_loglevel = 0
smtpd_tls_cert_file = /etc/ssl/certs/ssl-bundle.crt
smtpd_tls_key_file = /etc/ssl/private/mysubdomain.mydomain.com.key
smtpd_tls_auth_only = no
smtpd_tls_received_header = yes

Für den Fall dass sich jemand wundert woher die Datei /etc/ssl/private/mysubdomain.mydomain.com.key kommt – diese wurde beim erstellen des CSR angelegt und beinhaltet den private-Key des Zertifikats, sollte also niemals abhanden kommen!

Ob das Ganze funktioniert kann man recht schnell und einfach mit dem openssl Befehl testen:

openssl s_client -connect mail.kufnet.at:993

Das Ergebnis sollte dann in etwa wie oben im Screenshot aussehen – wichtig ist das „verify return:0“, dann sollte der Client keine Fehlermeldung ausgeben.