Eines der größten Probleme mit bigbeat.ch ist, wie könnte es anders sein, Spam... Die zahlreichen Möglichkeiten uns Nachrichten und Kommentare zu hinterlassen werden in drastisch steigendem Maße von Spam-Bots missbraucht um ihre Werbung zu verbreiten.

 

Nun kann man natürlich captchas und blacklists in den Quellcode implementieren, die zumindest verhindern, dass der Spam gespeichert wird. Hierzu muessen die Daten aber erst einmal komplett übertragen und verarbeitet werden. Ab einem gewissen Spam-Aufkommen ist aber gerade das das kritische Problem: Wenn mal 50 und mehr Bots auf einmal ihren Spam abladen wollen (keine Seltenheit..) werden auch die Anfragen von echten Besuchern nur noch quälend langsam bis gar nicht mehr beantwortet. So ein Bot begnügt sich dann ja auch nicht mit ein - zwei Links: Der schickt mehrere Kilobytes an Links...

Also muss ein Mechanismus her, der die Übertragung schnellst möglich unterbricht, sobald ein Spam-Bot erkannt wurde. Die Lösung heißt: mod_security.  Quasi eine Webserver-Firewall. Hiermit lassen sich zahlreiche Gegebenheiten überprüfen und Reaktionen festlegen:
Man kann zum Beispiel eine Regel erstellen, die beim Aufruf einer bestimmten Seite eine bestimmte POST-Eingabe auf ein bestimmtes Keyword überprüft, dies im positiven Fall loggt und einen 403-Fehler ausgibt. Man kann die IP des Benutzers aber z.B. auch mit einer oder mehreren DNSBL abgleichen und vieles, vieles mehr...

Einleitung

Da ich selbst auf meinem Server "Debian etch" und "Apache 2.2" einsetze, werde ich in diesem howto auch nur auf diese Konfiguration eingehen.. Wer ein Wenig Ahnung von seinem Betriebssystem hat, wird die Informationen aber sicher auch für seine Distribution verwenden können..
Auch setze ich ein gewisses Grundwissen von Debian und Apache voraus. Wer nicht weiß, wie die Konfiguration seines Webservers funktioniert, sollte sich erstmal darüber informieren und erst dann anfangen mit Modulen wie mod_security zu "spielen"...
Dieses howto spiegelt natürlich auch nur meinen Wissens-Stand wieder und kann somit im schlimmsten Falle sogar falsche Informationen enthalten.. Ich garantiere keinen Erfolg noch übernehme ich die Haftung für Schäden irgendeiner Art, die durch meine hier geschriebenen Anweisungen auftreten...
Besonderer Dank gilt auch otaku42, der seine dank madwifi.org reiche Erfahrung mit Spam und ihrer Bekämpfung immer bereitwillig mit mir teilt... ;) Sein englischsprachiges howto zu mod_security <2 findet Ihr auf der madwifi-website.

Installation von mod_security 2.1.0

Da im Debian-Repo nur ein veraltetes mod_security Paket für Apache 2.0 zu finden ist, müssen wir uns zunächst ein eigenes erstellen. Dank otaku42, der einen debianisierten Quellcode per SVN zur Verfügung stellt, ist das aber gar kein Problem:

        #~> svn co http://svn.projects.otaku42.de/libapache2-mod-security/trunk/
        #~> cd trunk
        #~> chmod +x debian/rules
        #~> dpkg-buildpackage

Evtl. beschwert er sich zunächst über fehlende Abhängigkeiten - sind diese erfüllt, sollte er aber eigentlich problemlos durch-compilieren und danache eine Verzeichnissebene höher ein .deb-Paket ausspucken, welches wir dann mit Hilfe von dpkg installieren:

        #~> cd ..
        #~> dpkg -i libapache2-mod-security*.deb

 Damit das Modul auch verwendet wird, muss ein entsprechender symlink erstellt werden:

        #~> cd /etc/apache2/mods-enabled
        #~> ln -s ../mods-available/security2.load .

Nach dem nächsten Apache restart wird das Modul nun mit geladen, weiß aber noch nicht, was es tun soll und wo. Hierzu benötigt es Filterregeln, die ihm sagen wann er was tun sollte. Eine ausführliche, aber nicht wirklich praxisnahe gestaltete Übersicht über alle mod_security Direktiven gibt es in der Dokumentation auf der Homepage. Auch gibt es jede Menge HOWTOs und Beispiele im Internet - die sind aber leider (noch) meistens auf mod_security < 2.0 zugeschnitten. Da sich das Format der Direktiven in Version 2 grundlegend geändert hat, bringen uns diese howtos recht wenig...
Eine Menge aktueller Beispiele gibt es auch in dem Verzeichniss "rules" des eben heruntergeladenen Quellcode-Paketes. Da diese zumindest mich aber anfangs doch sehr verwirrt haben, hier erst einmal ein paar einfache Beispiele aus meiner Praxis:

mod_security aktivieren:

Das Modul wird nun zwar geladen, ist aber nicht generell überall aktiv. Hierzu muss es mit der folgenden Direktive eingeschalten werden:

        SecRuleEngine On

Die Grund-Einstellungen:

Damit mod_security nun zwar prüft, was an uns geschickt wird, nicht aber was wir selbst verschicken schieben wir gleich diese beiden Direktiven hinterher:

        SecRequestBodyAccess On
        SecResponseBodyAccess Off

Nun stellen wir eine Datei für das Debug-Log ein und setzen das Loglevel auf 0, da die wirklich wichtigen Meldungen sowieso im normalen errorlog der jeweiligen Domains erscheinen und mod_security wirklich genug logs produziert.. ;)

        SecDebugLog /var/log/apache2/debug.modsec_log
        SecDebugLogLevel 0

Und nun noch das "normale" logfile, in dem all das steht, von dem wir später entscheiden werden, dass es geloggt werden soll:

        SecAuditEngine RelevantOnly
        SecAuditLogRelevantStatus ^5
        SecAuditLogParts ABIFHZ
        SecAuditLogType Serial
        SecAuditLog /var/log/apache2/audit.modsec_log

Damit uns Spam-Bots gar nicht erst mehrere KiloBytes an Werbung schicken können setzen wir einfach eine maximale Größe für POSTs..

Achtung!Hierbei ist Vorsicht angebracht: Will man zum Beispiel auf irgendeiner Website dieses Servers Dateien entgegennehmen, kann das hier vorgeschlagene Limit recht schnell eng werden.
Es kann dann, wie die meisten mod_security-Direktiven, innerhalb der Tags VirtualHost, Location, LocationMatch, Directory, etc Domain- und sogar Pfad-spezifisch verändert werden. (siehe unten...)

        SecRequestBodyLimit 131072            # byte Angaben
        SecRequestBodyInMemoryLimit 131072   # byte Angaben

Eine gute Idee ist es auch, das Verzeichniss, in dem Uploads laden, auf einen anderen Pfad als "/tmp" zu setzen, da dieser für jedermann lesbar ist (und auch sein muss..)
Man kann (nein sollte!) zum Beispiel ein ganz neues Verzeichnis erstellen und dieses dann nur für den Webserver lesbar machen (bei Debian default: www-data:www-data) und dann mit folgender Direktive Apache sagen, wo er in Zukunft seine Uploads speichern soll:

        SecUploadDir /var/tmp/apache2

Mit der folgenden Direktive können wir entscheiden, ob Apache hochgeladene Dateien grundsätzlich behalten oder nach der weiteren Verarbeitung wieder löschen soll. Ersteres kann zu debugging-Zwecken interessant sein, im laufenden Betrieb aber nicht wirklich empfehlenswert, da das schnell in einem sehr grossen temp-folder enden kann...

        SecUploadKeepFiles Off

Auch nett ist es, die default-Status-Zeile, die Apache bei Fehlermeldungen mit ausgibt zu verändern damit er nicht immer alles über alle Module verrät:

        SecServerSignature "Apache/2.2.0 (Debian)"

Um uns später unnötige Tipperei zu ersparen können wir nun noch ein paar default-Parameter angeben, die allen folgenden Filterregeln mit übergeben werden:

        SecDefaultAction "phase:2,log,pass,status:412"

Die einzelnen Parameter bedeuten:

  • phase:2
    Mit "phase" stellt man ein, in welcher Phase des http-requests bzw. der Antwort die Filterregel greifen soll. Mit "phase:1" werden zum Beispiel die Inhalte des request-headers gefiltert, mit "phase:2" die Inhalte des request-bodys und so weiter. Mehr hierzu gibt es in der Doku von mod_security zu lesen...
  • log
    Der Vorgang soll geloggt werden.
  • pass
    Den Request an nachfolgende Filterregeln weitergeben auch wenn die aktuelle bereits zutraf
  • status:412
    Fehler Nummer 412 ausgeben... Zumindest als default ist ein 412 einem 5xx auf jeden Fall vorzuziehen, da dieser nicht sagt: "Gibt's generell nicht", sondern eben "Gibt's für Dich nicht"...

Diese defaults lassen sich später für jede einzelne Filterregel wieder überschreiben. Zum Beispiel werden wir "pass" meistens durch "deny" überschreiben, damit bei zutreffender Filterregel eben doch schluss ist. (siehe unten)

Die Filter:

Sind die Grundeinstellungen erst einmal getan, können die eigentlichen Filterregeln erstellt werden.. Manche davon sollen für alle gehosteten Websites gelten und manche auch nur für bestimmte Seiten oder sogar nur bestimmte Bereiche bestimmter Seiten.. Darum können die meisten mod_security Direktiven (und natuerlich auch die, mit der Filterregeln definiert werden) an verschiedenen Stellen in der Apache-Config gesetzt werden.
Im Globalen Kontext sind die Regeln logischerweise auch global aktiv. Innerhalb eines <VirtualHost>-Abschnittes gelten Sie nur für diesen VirtualHost und innerhalb eines <Location>-Abschnittes auch nur für diese Location..

Zunächst ein ganz einfaches Beispiel:

POST-Filter:

Da wir auf unserer Homepage den Besuchern jede Menge Möglichkeiten bieten, Kommentare und sogar ganze Artikel zu hinterlassen, besuchen uns auch in drastisch steigendem Maße Bots, die dort ellenlange Link-Listen abladen wollen. Da Links in der Regel die Zeichenfolge "http" (wie in http://www.pr0n.com) enthalten will ich nun also mit einer Regel checken, ob in dem fraglichen Formularfeld der Text "http" vorkommt und solche requests dann loggen und ablehnen:

Das geschieht über die Direktive "SecRule", die sich wie folgt zusammensetzt:

    SecRule <wo> <wonach> <parameter>

Hier zum Beispiel die oben besprochene Regel:

       SecRule ARGS:comment http \
             "id:95901,rev:1,phase:2,t:urlDecodeUni,msg:'gallery kommentar spam',deny"

Was die einzelnen Parameter bedeuten:

  • SecRule
    Leitet eine Filterregel ein...
  • ARGS:comment
    Der Inhalt der übertragenen Variable "comment" soll überprüft werden. In diesem Fall ist comment der Name des Textfeldes unserer Kommentar-Funktion und somit eine POST-Variable. "ARGS" umfasst aber auch GET und weitere Variablen.. Mehr dazu in der mod_security Dokumentation..
  • http
    Das ist das keyword nach dem gesucht werden soll. (Sieht hier zwar nicht so aus, ist aber ein regulärer Ausdruck..!)
  • id:95901
    Jede Filter-Regel sollte eine eigene ID haben, damit sie später z.B. auch in bestimmten Fällen deaktiviert werden kann..
  • rev:1
    Die revision der Filter-Regel.
  • phase:2
    Wie bei der default-Zeile (siehe oben): In diesem Fall wollen wir den body überprüfen, darum: "phase:2"
  • t:urlDecodeUni
    transformiert unicode codierte URLs, bevor sie durch den Filter laufen.
  • msg:'gallery kommentar spam'
    Welche Meldung bei einem Fund im Logfile ausgegeben werden soll (frei wählbar..)
  • deny
    Request ablehnen. Wie er abgelehnt wird, können wir mit dem Parameter "status:<nr>" angeben - tun wir das nicht, wird das default verwendet, welches wir mit "SecDefaultAction" gesetzt haben.. (siehe oben)

Verkettete Filter:

Da jede Regel aber Rechenpower braucht, ist es wichtig Regeln weitestmöglich einzugrenzen. Diese Regel wollen wir ja zum Beispiel eigentlich nur anwenden, wenn in der Galerie einen Kommentar hinterlassen wird.
Um das weiter einzugrenzen benötigen wir nun zwei miteinander verbundene Regeln. Die erste, die prüft ob der Request überhaupt der interessanten Seite gilt und die zweite um dann den Inhalt zu filtern:

        SecRule REQUEST_URI "index\.php\?handler=modules&g_handler=show_picture&module=vision" \
                "id:95901,rev:1,t:normalisePath,msg:'artikel kommentar spam',deny,chain"
        SecRule ARGS:comment http \
                "t:urlDecodeUni"


Was die einzelnen Parameter bedeuten:

Regel 1:

  • REQUEST_URI
    Die angeforderte URI soll überprüft werden...
  • "index\.php\?handler=modules&g_handler=show_picture&module=vision"
    ...und zwar auf diesen text... (regulärer Ausdruck!)
  • Die folgenden Parameter sind weitestgehend die gleichen wie im vorangegangenen Beispiel. Neu ist aber der Parameter "chain":
    Hiermit wird diese Regel mit einer (oder mehreren) folgenden verknüpft. Am Ende einer solchen "Verknüpfungs-Kette" (in unserem Beispiel ist das gleich die zweite Regel..) geben wir einfach keine "chain" mehr an, damit mod_security weiß, dass hier Schluss ist.

Regel 2:

Wie im ersten Beispiel, nur dass nahezu alle Parameter bereits in der ersten Regel gesetzt wurden...

Nur POST-Requests filtern:

Will man sowieso nur Spam bekämpfen und funktionieren (wie meistens) alle Text-Eingaben über POSTs, macht es wenig Sinn bei jedem GET Request alle Filterregeln durchzuarbeiten.. Selbst wenn die Regeln so gut gestrickt sind, dass sie meistens dann doch nicht ausgeführt werden, weil z.B. die falsche Seite angefragt wurde, muss mod_security sich erstmal bis zu dieser Information durcharbeiten..
Um dies zu unterbinden setzen wir über unsere Regel(n), die Formularfelder überprüfen folgende Regel:

        SecRule REQUEST_METHOD "!^(post)$" \
                "id:95000,rev:1,phase:1,t:lowercase,allow,nolog,noauditlog"

Diese Regel bewirkt, dass alle "nicht-POST-requests" nicht geloggt und generell zugelassen werden. Da auch kein "pass" mit angegeben wurde ist bei GET-Requests hier schon Schluss mit Filtern und wir haben wieder etwas Rechenpower gespart... :)

DNSBL befragen

DNSBL kennt man meistens eher vom Bekämpfen von E-Mail Spam her. Es spricht zunächst einmal aber nichts dagegen, diese auch für WebSite-Spam zu verwenden.
Hierzu legen wir einfach folgende, verkettete Regel an:

        SecRule REQUEST_METHOD "^post$" \
                "id:95951,log,deny,chain,msg:'LOCAL comment spammer \
                at rbl website.dnsbl.kennmer.net'"
        SecRule REQUEST_URI "index\.php\?addtalk" "chain,t:normalisePath"
        SecRule REMOTE_ADDR "@rbl website.dnsbl.kennmer.net"

Bis auf die letzte Zeile sind das alles bekannte Befehle. In der letzten Zeile weisen wir mod_security nun an, die IP mit der dnsbl "website.dnsbl.kennmer.net" zu vergleichen. Wird die IP gefunden, wird der Request abgelehnt.

Die Vorteile von DNSBL

Die Vorteile von dnsbl sind ganz klar der hohe Grad an Dynamik: Die Liste aus unserem Beispiel wird zum Beispiel alle 7 Minute upgedatet. Wird eine IP länger als 4 Stunden nicht gemeldet, wird sie automatisch wieder aus der Liste entfernt.
Ein weiterer Vorteil ist die Einfachheit: Man muss sich nicht groß um Regeln kümmern und keine IPs sammeln - das erledigt der Listen-Betreiber für uns.

Die Nachteile von DNSBL

Die Nachteile von dnsbl ergeben sich eigentlich schon aus den Vorteilen: Damit eine Liste so aktuell und dynamisch sein kann, müssen sich die Betreiber auf Automatismen und auf korrekte Angaben ihrer Benutzer verlassen.
Dabei landen auch immer wieder mal "false positives" in den Listen. Ein Beispiel sind z.B. dynamische IP-Adressen, wie sie auch mein ISP vergibt: Habe ich mich frisch eingewählt, bekomme ich eine IP, die vor kurzem noch von jemand anderem verwendet wurde. Hat mein Vorgaenger nun Spam versendet, wird seine (jetzt meine) IP auch noch eine Weile in dnsbl gelistet..

Also was nun?

cautionWärend man bei E-Mail Spam relativ leicht ein Punkte-System etablieren kann, nach dem eine Mail nur dann als Spam erkannt wird, wenn die IP des Senders in mehreren dnsbl gelistet ist, kenne ich (noch?) keine Möglichkeit, das gleiche mit mod_security zu tun.
Wenn wir also eine dnsbl in Apache verwenden, müssen wir auf ein paar Dinge ganz besonders achten:

  • Welche Liste verwenden wir?
    Die meisten dnsbl sind auf E-Mail Spammer ausgerichtet. Teilweise sind das die gleichen IPs, teilweise aber auch nicht. Ein ausführlicher Test, welche dnsbl möglichst viele Spammer findet, aber auch möglichst wenige false positives hat, sind unerlässlich!
    Eine große Liste von finden wir zum Beispiel bei DNSStuff.com: http://www.dnsstuff.com/tools/ip4r.ch?ip=192.168.1.1
  • Was filtere ich?
    Gibt es vielleicht andere Möglichkeiten, dem Spam zu begegnen? Muss diese Seite überhaupt getestet werden? Auf bigbeat.ch teste ich zum Beispiel nur die Talkbox anhand von dnsbl, da ich dort erstmal generell alle Wörter zulassen möchte und so einfach nicht mehr anhand des contents filtern kann.
  • Den Benutzer informieren!
    Wenn nun ein echter Benutzer eine Nachricht hinterlassen will und aufgrund eines dnsbl blockiert wird, müssen wir ihn unbedingt aufklären, was passiert ist.. Siehe hierzu den Abschnitt "Die Fehlermeldungen"...

Einzelne Regeln partiell deaktivieren:

Einige der mitgelieferten Beispiel-Regeln habe ich direkt übernommen, da sie mir sinnvoll erschienen. So zum Beispiel die "generic_attacks" Regeln.. In der Praxis hat mich das jetzt aber schon ein paar Male daran gehindert, diesen Artikel hier zu speichern.. Die Regeln erkennen, dass ich von Linux-Kommandos schreibe und das verbieten sie.
Anstatt gleich das komplette mod_security für den Administrations-Bereich meiner Homepage zu deaktivieren, kann ich auch einfach nur die störenden Regeln einzeln ausschalten, indem ich folgendes zu dem entsprechenden VirtualHost schreibe:

        <Location /admin/>
                SecRuleRemoveById 95000 95001 "95401-95415" "95451-95453" "95901-95906" 95951 95952
        </Location>

Die Nummern sind die IDs, die wir den Regeln vergeben haben (siehe oben). Es können auch ganze ID-Bereiche angegeben werden, diese müssen dann aber, wie im Beispiel, in Gänsefüsschen gesetzt werden..

Die Fehlermeldungen

Gerade zu Anfang können diese Filterregeln auch mal den Falschen treffen.. Da ist es dann doof, wenn man nur eine nichtssagende Standard-Fehlermeldung präsentiert und der Besucher womöglich noch denkt, es sei etwas kaputt..
Also wollen wir sprechende und präzise Fehlermeldungen. Das ist jetzt eigentlich gar nichts mod_security-spezifisches, wird mit mod_security aber wichtig und darum beschreibe ich es hier auch...
Damit alles so funktioniert, wie es soll, sind ein paar weitere Apache-Module nötig, die gegebenenfalls aktiviert oder installiert werden müssen:

Dann konfigurieren wir Apache, dass er benutzerdefinierte Fehlermeldungen verwendet. Hierzu muss zunächst ein Alias gesetzt werden unter dem die benutzerdefinierten Fehlermeldungen später zu finden sind:

        Alias /errors/ "/usr/share/apache2/custom-errors/"

Und dann welcher code mit welchem file quittiert werden soll:

        ErrorDocument 403 /errors/error403.html
        ErrorDocument 412 /errors/error412.html

Damit mod_include die html-files auch parset ist ein weiterer Parameter nötig, den wir, wieder um Rechenpower zu sparen und mögliche Sicherheitslücken einzuschränken, auf die neue Location "/errors/" beschränken:

        <Location /errors>
                XBitHack On
                SetHandler None
        </Location>

Wieder können diese Anweisungen sowohl im globalen Bereich der apache-config gegeben werden, wenn sie Server-weit gelten sollen, sie können aber auch auf einzelne VirtualHosts beschränkt werden, indem man sie einfach zu dem entsprechenden Host schreibt..

mod_security quittiert die verschiedensten Anfragen mit den Fehlern 403 und 412 - also brauchen wir eine genauere Beschreibung des tatsächlichen Problemes, als nur den Errorcode. Hier kommen die Umgebungsvariablen (mod_env) ins Spiel.. mod_security gibt uns die Möglichkeit bei jeder Regel auch eine Umgebungsvariable zu setzen, anhand derer wir später identifizieren können, welche Regel nun zum Fehler führte.
Das Beispiel von oben sähe dann z.B. so aus:

        SecRule REQUEST_URI "index\.php\?handler=modules&g_handler=show_picture&module=vision" \
                "id:95901,rev:1,setenv:TRIGGER=42901,t:normalisePath,msg:'gallery kommentar spam',deny,chain"
        SecRule ARGS:comment http \
                "t:urlDecodeUni"

Mit dem Parameter "setenv:TRIGGER=42901" setzen wir im "Erfolgsfall" die Variable "TRIGGER" auf den Wert "42901".
Spätestens jetzt wird es auch interessant, sich einen genauen Plan zu machen, welche Regel welche ID und welchen TRIGGER hat, damit man da auch später noch durchblickt, ohne jedes Mal gleich in drei verschiedene Dateien gucken zu müssen...

Nun brauchen wir noch die Dateien mit den angepassten Fehlermeldungen. In der Apache-Config haben wir angegeben, dass sie unter "/usr/share/apache2/custon-errors/" zu finden seien, also müssen wir sie auch dort erstellen... Zunächst die "Haupt-Datei", in der der Text steht, der immer gleich bleiben soll. Sie heisst, wie in der Apache-Config angegeben, "error403.html" bzw. "error412.html"

Hier ein Beispiel:

        <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
        <html>
        <head>
            <title>403 Forbidden</title>
        </head>
        <body>
            <h1>403 Forbidden</h1>
            <!--#if   expr="$REDIRECT_TRIGGER == 42000" -->
              <!--#include file="rule-42000.inc.html" -->
            <!--#elif expr="$REDIRECT_TRIGGER == 42901" -->
              <!--#include file="rule-42001.inc.html" -->
            <!--#else -->
            <p>
                You don't have permission to access <!--#echo var="" --> on this server.
            </p>
            <!--#endif -->

            <hr />
            <div style="background: #e0e0e0;">
                <p>
                    If the above information does not help you to fix the problem, or in case
                    you feel that it does not match your situation at all, we kindly ask you
                    to contact us by e-mail at<br />
                    <em>abuse &lt;at&gt; ambience-design &lt;dot&gt; net</em>.
                </p>
                <p>
                    In this case please make sure that your e-mail contains the following
                    information:
                </p>
                <table>
                    <tr>
                      <td style="text-align: right;"><strong>UNIQUE_ID:</strong></td>
                      <td><strong><!--#echo var="UNIQUE_ID" --></strong></td>
                    </tr>
                    <tr>
                      <td style="text-align: right;"><strong>TRIGGER:</strong></td>
                      <td><strong><!--#echo var="REDIRECT_TRIGGER" --></strong></td>
                    </tr>
                </table>
            </div>
            <hr />
            <address>
              <!--#echo var="SERVER_SOFTWARE" -->
              at <!--#echo var="SERVER_NAME" -->
              Port <!--#echo var="SERVER_PORT" -->
              -- <!--#echo var="REDIRECT_STATUS" -->
              triggered by rule <!--#echo var="REDIRECT_TRIGGER" -->
            </address>
        </body>
        </html>

Größtenteils sind das alles HTML-Befehle, dank mod_include haben wir aber auch die Möglichkeit, eine simple Logik einzubauen, die z.B. Apache Umgebungsvariablen ausgibt und nach bestimmten Bedingungen weitere Dateien inkludiert.

Achtung!Alle Variablen, die in Apache gesetzt wurden (also auch unsere Variable "TRIGGER") stehen zwar im html-file zur Verfügung, haben nun aber ein "REDIRECT_" vorgestellt. Aus "TRIGGER" wurde also z.B. "REDIRECT_TRIGGER"...


Im oberen Bereich des Scriptes prüfen wir die Variable "REDIRECT_TRIGGER" und geben je nach Inhalt verschiedene html-files aus, die das Problem dann näher beschreiben..
Im unteren Bereich geben wir Standard-Informationen aus, die bei jedem Fehler gleich sind: Wie uns der Benutzer erreichen kann, wenn er diesen Fehler fälschlicherweise erhielt und welche Informationen er uns bei einer Anfrage mitsenden soll, damit wir seinen Fall auch schnell im Log wiederfinden..

Nun brauchen wir noch die zu inkludierenden Dateien, die den Fehler genauer beschreiben. Erstellen wir also eine Datei "rule-42901.inc.html" für unserer Beispiel-Regel:

        <h2>Reason: No links allowed in comments</h2>
        <p>
            Due to a <strong>very</strong> high quantity of homepage-spam, we
            decided to block every comment containing links.<br />
            If you really want to tell us about something we might want to know,
            please visit our Forum...
        </p>


Um das Ergebniss dessen zu sehen, was wir nun gemacht haben, könnt Ihr einfach mal das Wort "triggertest" in das Such-Feld am rechten oberen Bildschirmrand eingeben..

ScallyWhack:
otaku42 hat ein sehr ausführliches RuleSet und erklärungsseiten für trac geschrieben, mit dem sich sehr effektiv und ohne große eigen-Bemühungen trac-spam verhindert werden kann.
Dieses RuleSet wird ständig aktualisiert und verfeinert - des weiteren sind noch jede Menge interessanter Funktionen für die Zukunft geplant...
http://projects.otaku42.de/wiki/ScallyWhack

DNSStuff:
dnsstuff.com bietet diverse interessante Dienste rund um's DNS an. Teilweise kostenfrei, teilweise kostenpflichtig. Kostenfrei und sehr praktisch ist z.B. die Möglichkeit IPs in diversen DNSBLs nachschlagen zu lassen.. ("Spam Database Lookup" - weiter unten, auf der Startseite..)
http://www.dnsstuff.com/

myDNSBL:
Ich selbst habe ein System geschrieben, in dem man seine eigenen DNSBLs erstellen / verwalten / pflegen kann, die dann unter *.mydnsbl.kennmer.net zur Verfügung stehen. Seit Ende Juni befinde ich mich hiermit in der "non-public-beta-phase". Das heißt, Tester sind nach vorheriger, persönlicher Anfrage sehr willkommen! :)
http://mydnsbl.kennmer.net/

Nachwort

So. Nun haben wir mod_security einigermaßen konfiguriert und im Einsatz. Das ist aber kein Grund, sich nun zurückzulehnen - im Gegenteil! Jetzt geht die Arbeit erst richtig los, denn zumindest in den ersten Wochen und Monaten müssen wir ganz genau kontrollieren, was passiert, wann und vor allem warum es passiert.. Automatismen zu etablieren, die Besucher teilweise aussperren und dann nicht zu kontrollieren, wer denn da ausgesperrt wird, ist eine ganz schlechte Idee.. ;)
Das log-file von mod_security ist da ein erster Anlaufpunkt. Ist alles so eingestellt, wie in diesem HOWTO angegeben, steht dort alles, was wir wissen wollen und noch viel mehr..
Achtung: Das Log-File ist riesig! :) Es muss also auf jeden Fall rotiert werden und um es einigermaßen komfortabel lesen zu können, bietet es sich an, skripte zu schreiben, die die interessanten Informationen in einem angenehm lesbaren Format ausfiltern und in eine neue Datei schreiben.. (sed und grep sind Deine Freunde! ;) )

Zu guter Letzt noch einmal: Für alle Kommentare, Verbesserungen und Korrekturen zu diesem HOWTO bin ich sehr dankbar..! :)

Gravatar
stimpy
Sooo.. Artikel mit Download-Links und ausführlicher Beschreibung und Installations-Anleitung ist fertig und im Blog zu finden... :-)
Gravatar
Thom
re:
Hi!,
stimpy said :
Wenn Du magst, schick mir doch einfach mal beide VirtualHost-Abschnitte per email zu (also den, der funktioniert und den, der nicht funktioniert..), dann kann ich mir das richtig angucken..
stimpy ÄT stimpyrama DÖT org

@stimpy: danke, aber ich habe es schon hingekriegt!
P.S.: jemand macht da richtig Werbung! (schau ein Post über dem da)

Gruß,
Thom

Gravatar
stimpy
ah, super..
Und re Werbung: Was? Ich hab nix g'sehn.. ;-)

Gravatar
stimpy
neuer Absatz
Ich habe grad mal nen neuen Absatz mit nuetzlichen Links eingefuehrt, den ich in Zukunft auch noch erweitern werde...
Gravatar
Thom
modsec2iptables
stimpy said :
Ich habe grad mal nen neuen Absatz mit nuetzlichen Links eingefuehrt, den ich in Zukunft auch noch erweitern werde...

Supi danke!
Hast Du schon mal modsec2iptables verwendet?. Es ist eine Erweiterung für Modsecurity mit dem Ziel, angreifer's IP in der Iptables zu logen, so dass er keinen weiteren Angriff starten kann...

Laut Script-Entwickler, muss man volgende Zeile in die modsec.conf eintragen:
# Reject requests with status 500
SecFilterDefaul tAction "deny,log,status :500,exec:/usr/sbin/modsec2iptables "

Leider gibt's nur eine Anleitung für Modsec 1.X (Hier: http://www.fbis.ch/index-de.php?page=13&frameset=4), laut entwickler müsste die Zeile für Modesec 2.X jedoch:

SecDefaultActio n "phase:2,log,den y,status:500,ex ec:/usr/sbin/modsec2iptables " heißen.
Ich habe es bereits ausprobiert, leider wurde meine IP bereits nach dem ersten Webmail-abrufen in der Iptables gelogt..., ich vermutte, dass die Zeile für Modsec2 einfach irgend wie anders lauten muss, weil jetzt alles in der Wall gelogt wird, daher auch bei "Warnings"..., was nicht sein sollte...

Wüsstest du vieleicht ein Lösung?


thx,
Thom

Gravatar
Thom
re:
stimpy said :
ah, super..
Und re Werbung: Was? Ich hab nix g'sehn.. ;-)

Na jetzt ist es schon weg :D

Gravatar
Tom
jep :D
Also hab's geschaft, allerdings leider nur für eine Domain eine zweite tut so, als ob ich nichts eingetragen hätte-- habe bereits 3 Regel ausfindig gemacht, die den "error" verursachen und alle 3 kommen immer wieder trotz der eintragung und Apache neustart...

Thom

Gravatar
stimpy
Wenn Du magst, schick mir doch einfach mal beide VirtualHost-Abschnitte per email zu (also den, der funktioniert und den, der nicht funktioniert..), dann kann ich mir das richtig angucken..
stimpy ÄT stimpyrama DÖT org

Gravatar
stimpy
Ich nehme an, was fehlt waren die mit spitzen Klammer umgebenen Location-Tags.. Sowas geht halt net in Kommentaren.. :-)
Aber egal:
Die kommen da hin, wo sie gebraucht werden.. :-) Also entweder in den Hauptbereich der Config-Datei oder zwischen die entsprechenden VirtualHost-Tags..
Wie Du das mit webmin machst, weiss ich allerdings nicht...

Gravatar
Thom
Doch nicht..., aber ich glaube, du weist was ich meine...

5000 Characters left