aufruf des interpreters/start eines prozesses unterbinden
Dirk
- cgi
hallo,
bin seit längerem ein eifriger forumsleser, hab aber leider noch nix gefunden, was in richtung meiner frage geht.
folgendes problem: ich habe eine chattergalerie erstellt, bei der sämtliche aktivitäten der user hauptsächlich mit perl-scripten realisiert werden. funzt soweit auch alles einwandfrei. vor kurzem hatte ich aber das problem, daß plötzlich kein script mehr lief ("cgi-limit reached"), ursache hierfür war ein mißbräuchliches, unverhältnismäßig oftes aufrufen eines scriptes. die seite ist bei 1&1 gehostet ist, dort ist die anzahl gleichzeitig laufender prozesse auf 12 begrenzt, und die maximale prozesslaufzeit auf 6sec. beschränkt. folgendes war passiert: ein user hatte ein (ziemlich rechenintensives) script über einen längeren zeitraum im schnitt ca. 3x pro sekunde aufgerufen, anscheinend mit einer speziellen software, also nicht im browser, da in $ENV{'HTTP_USER_AGENT'} nichts drin stand, und der wert von $ENV{'REMOTE_ADDR'}, also die ip, wechselte ständig. nun hab ich zwar sämtliche scripte dahingehend ergänzt, daß, falls $ENV{'HTTP_USER_AGENT'} leer ist, der prozess sofort abbricht und fehlermeldung ausgibt (der hintergedanke war, die prozesslaufzeit zu verringern), aber ohne erfolg. bei einem nächsten "angriff" war dasselbe in grün :-(
die einzige möglichkeit, die ich mir evtl. vorstellen könnte, wäre, solch einen mißbrauch über die .htaccess zu unterbinden...aber wie? oder wißt ihr eine andere lösung? bin für jeden vorschlag dankbar, denn so, wie's im moment ist, könnte derjenige die seite eigentlich für immer, nach lust und laune, "stillegen".
gruß, Dirk
hallo
dein Angreifer kann Dich ja nicht über beliebig viele IPs angreifen. Schreib Dir die IPs doch einfach mal alle auf und blockiere dann die Zugriffe, die von diesen IPs kommen.
Ich glaube das Risiko, dass Du einen normalen User auf diese Weise blockierst, ist so gering, dass Du Dir das erlauben kannst.
Die Software des Angreifers funkionier vielleicht so:
mfg Flunsi
Halihallo
dein Angreifer kann Dich ja nicht über beliebig viele IPs angreifen. Schreib Dir die IPs doch einfach mal alle auf und blockiere dann die Zugriffe, die von diesen IPs kommen.
Ich glaube, dass dies nicht sehr viel bringt, es sei denn, dass Dirk denjenigen verklagen will. Dann kann man mit Hilfe der IP und der Zeit den Client identifizieren (oder zumindest den Computer). Aber da die IP's immer wechseln (bei gewissen Providern, kann dies bei _jedem_ Request passieren!), wird die IP bereits geändert haben, wenn Dirk anfängt, sich die IP zu notieren.
Ich glaube das Risiko, dass Du einen normalen User auf diese Weise blockierst, ist so gering, dass Du Dir das erlauben kannst.
Das stimmt.
Die Software des Angreifers funkionier vielleicht so:
- Er greift über verschiedene Proxies auf dein cgi-skrip zu. (wer braucht sonst schon Proxies? ;-) )
;-)
Na, na, da zeigt sich eine Hackerseele ;-)
- Er hat sich bei einigen cgi-gratis-server ein Verzeichnis installiert und ein Weiterleitungs-Skipt von jedem dieser Server eingerichtet.
Das hab ich mal bei E-Mails gemacht und einige Freunde genervt ;-)
Viele Grüsse
Philipp
hallo
dein Angreifer kann Dich ja nicht über beliebig viele IPs angreifen. Schreib Dir die IPs doch einfach mal alle auf und blockiere dann die Zugriffe, die von diesen IPs kommen.
Ich glaube das Risiko, dass Du einen normalen User auf diese Weise blockierst, ist so gering, dass Du Dir das erlauben kannst.
doch, tut er leider. hab mir mal die mühe gemacht sie aufzulösen...also die server sind, soweit mein nameserver sie überhaupt auflösen konnte, kreuz + quer über den globus verstreut. und nur bestimmte user bzw. ip's oder ip-bereiche zulassen geht ja leider net, d.h. geht schon, aber dann kann ja kein fremder mehr die seiten betrachten.
Die Software des Angreifers funkionier vielleicht so:
- Er greift über verschiedene Proxies auf dein cgi-skrip zu. (wer braucht sonst schon Proxies? ;-) )
ist unwahrscheinlich, da fast selten eine ip doppelt vorkommt...bei tausenden von anfragen. ich denke vielmehr, er nutzt eine art ip-spoofing, da ihn die antwort bzw. die ausgabe ja gar nicht interessiert und sie auch nicht verwertet.
- Er hat sich bei einigen cgi-gratis-server ein Verzeichnis installiert und ein Weiterleitungs-Skipt von jedem dieser Server eingerichtet.
und wie kommt's dann zu den ständig unterschiedlichen ip's?
gruß,
Dirk
und wie kommt's dann zu den ständig unterschiedlichen ip's?
sehr gute frage! ich kann mir nicht vorstellen, dass man von einer ip etwas abschicken kann, die nichts damit zu tun hat. also müsste er doch irgendwie kontakt zu den 1000 (?) ip's haben.
keine ahnung.
Flunsi
Hi,
ich kann mir nicht vorstellen, dass man von einer ip etwas abschicken
kann, die nichts damit zu tun hat.
das muß der Angreifer doch gar nicht.
Er muß Dir nur eine falsche IP-Adresse mitschicken, also das gesendete
Paket so fälschen, daß es aussieht, als hätte jemand anderes es geschickt.
Irgendwo in diesem Paket muß ja letzten Endes drin stehen, an wen der Server
seine Antwort schicken muß.
Wenn da eine falsche Adresse drin steht, dann wird der Angreifer natürlich
die Antwort des Servers nicht empfangen können, da sie ja nicht an ihn,
sondern an die angegebene IP-Adresse geschickt wird.
_Diesen_ Angreifer interessiert die Antwort aber ggf. gar nicht.
Ihn interessiert nur, nicht identifiziert zu werden.
Viele Grüße
Michael
Halihallo
Nun, hierbei ist mir folgendes durch den Kopf gegangen:
- Das Script so programmieren, dass zur selben Zeit nur eine oder maximal zwei, drei Instanz(en) des Programmes läuft und sonst eine Fehlermeldung ausgegeben wird, alla
"<http-equiv name='refresh' content='1; URL=<same-script>'> einen Augenblick bitte, das Programm ist momentan ausgelastet"; das Script wird dann automatisch nach einer Sekunde erneut gestartet.
- Die Laufzeit der Scripte verkürzen. Besonders bei Scripten mit grossen Laufzeiten, kann man einige Optimierungen vornehmen. Wenn ein Programm z. B. nur einen dynamischen Output generiert und selber keine Daten ändert (z. B. Datenbank, Dateien, ...), könnte man den Output cachen und den Cache erneuern, wenn er älter als 5 Minuten ist, o. ä. So kann man einiges an Laufzeit einsparen, ohne die Qualität zu senken.
- Theoretisch lässt sich auch ein Session-Management einrichten. Programme, welche ohne gültige SessionID und SessionKey aufgerufen werden, werden sofort beendet. Zwischen den Requests einer Session muss mindestens eine halbe Sekunde verstreichen, sonst wird das Programm ebenfalls beendet.
Ich denke, dass die meisten Vorschläge nicht allzuschwer zu implementieren sind und einen gewissen Dienst zur Schadensbegrenzung erfüllen.
Viele Grüsse
Philipp
hi philipp,
"<http-equiv name='refresh' content='1; URL=<same-script>'> einen Augenblick bitte, das Programm ist momentan ausgelastet"; das Script wird dann automatisch nach einer Sekunde erneut gestartet.
das hilft in dem fall leider auch net weiter, da daß aufrufende progi die antwort nicht abwartet...und somit auch nicht verarbeitet. außerdem bezweifele ich stark daß es ein browser ist. das script soll ÜBERHAUPT NICHT starten.
- Die Laufzeit der Scripte verkürzen. Besonders bei Scripten mit grossen Laufzeiten, kann man einige Optimierungen vornehmen. Wenn ein Programm z. B. nur einen dynamischen Output generiert und selber keine Daten ändert (z. B. Datenbank, Dateien, ...), könnte man den Output cachen und den Cache erneuern, wenn er älter als 5 Minuten ist, o. ä. So kann man einiges an Laufzeit einsparen, ohne die Qualität zu senken.
fast alle scripte ändern irgendwelche daten. die laufzeit hab ich insofern verkürzt, daß ganz am anfang, bevor das script überhaupt seine eigentliche arbeit startet, zuerst $ENV{'HTTP_USER_AGENT'} abgefragt wird, und, falls $ENV{'HTTP_USER_AGENT'} eq "" dann exit...geholfen hat's leider nix, nach knapp 20minütiger attacke war's dann soweit :-(
- Theoretisch lässt sich auch ein Session-Management einrichten. Programme, welche ohne gültige SessionID und SessionKey aufgerufen werden, werden sofort beendet. Zwischen den Requests einer Session muss mindestens eine halbe Sekunde verstreichen, sonst wird das Programm ebenfalls beendet.
öhm, sagt mir jetzt net viel, auf der anderen seite, was bringt's, wenn der prozess sowieso wird? ich will vielmehr verhindern, daß er überhaupt erst gestartet wird
Ich denke, dass die meisten Vorschläge nicht allzuschwer zu implementieren sind und einen gewissen Dienst zur Schadensbegrenzung erfüllen.
mag sein, daß diese ihren dienst versehen...aber leider unzureichend :-( trotzdem thanx.
gruß,
Dirk
Hi Dirk,
ich will vielmehr verhindern, daß er überhaupt erst gestartet wird
nein, das willst Du nicht wirklich.
Du willst nicht, daß der Prozeß überhaupt nicht gestartet wird. Vielmehr
willst Du, daß der Prozeß manchmal gestartet wird und manchmal nicht.
Das genau ist aber das Problem.
Wovon soll es abhängen, ob der Prozeß gestartet wird oder nicht?
Du kannst nicht generell verhindern, daß ein Angreifer mit wechselnden
IP-Adressen Last auf Deinen Server bringt.
Was Du seht wohl könntest, das ist, die Zugriffe generell zu limitieren,
um die CPU-Leistung so zu verteilen, daß alle Teilnehmer gleichermaßen
darunter leiden (um beispielsweise einer im Hintergrund mitlaufenden
Anwendung genügend Power zu überlassen). Das ist aber das Gegenteil
dessen, was Du in diesem Falle erreichen willst.
Du kannst lediglich versuchen, diese Last so gering wie möglich zu halten,
indem Du mit minimalem Aufwand zwischen 'guten' und 'bösen' Requests unter-
scheidest und den Prozeß deshalb so schnell wie möglich wieder beenden
kannst, falls nötig.
Gute Hinweise, wie das funktionieren könnte, hat Phillip Dir genannt.
Viele Grüße
Michael
Halihallo
mit Verspätung kommen noch einige Anmerkungen...
Ich bin der Meinung von Michael: Du solltest eigentlich jedem Benutzer den Zugang zu deinen Programmen gewähren und kannst nicht zwischen "guten und bösen" Abfragen unterscheiden (dafür gibt's leider keine 100% sicheren Kriterien). Deshalb schlage ich auch nur Lösungsansätze vor, die mögliche Attacken minimieren.
"<http-equiv name='refresh' content='1; URL=<same-script>'> einen Augenblick bitte, das Programm ist momentan ausgelastet"; das Script wird dann automatisch nach einer Sekunde erneut gestartet.
das hilft in dem fall leider auch net weiter, da daß aufrufende progi die antwort nicht abwartet...und somit auch nicht verarbeitet. außerdem bezweifele ich stark daß es ein browser ist. das script soll ÜBERHAUPT NICHT starten.
Ist mir klar, dass das Programm die Ausgabe nicht abwartet. Diese Meldung soll den "guten" User darüber informieren, dass dein Programm ausgelastet ist. Die Abfrage (ob ausgelastet) kannst du an den Anfang deiner Programme setzen. Somit kannst du die Laufdauer der Programme im Falle einer Attacke verkleinern.
Falls keine Attacke am Laufen ist, wird diese Meldung praktisch nie ausgegeben (es sei denn zwei oder mehrere Klienten greifen zur selben Sekunde auf dieselbe URL zu). Mir ist jedoch auch klar, dass die Attacke dennoch nach 20 Minuten erfolgreich sein wird. Du müsstest theoretisch ein Programm schreiben, welches schneller ist als die Request des attackierenden Programmes. Dann hättest du keine Probleme mehr.
fast alle scripte ändern irgendwelche daten. die laufzeit hab ich insofern verkürzt, daß ganz am anfang, bevor das script überhaupt seine eigentliche arbeit startet, zuerst $ENV{'HTTP_USER_AGENT'} abgefragt wird, und, falls $ENV{'HTTP_USER_AGENT'} eq "" dann exit...geholfen hat's leider nix, nach knapp 20minütiger attacke war's dann soweit :-(
Das ist leider ein Problem, dass nicht einfach (oder gar nicht?) zu lösen ist.
- Theoretisch lässt sich auch ein Session-Management einrichten. Programme, welche ohne gültige SessionID und SessionKey aufgerufen werden, werden sofort beendet. Zwischen den Requests einer Session muss mindestens eine halbe Sekunde verstreichen, sonst wird das Programm ebenfalls beendet.
öhm, sagt mir jetzt net viel, auf der anderen seite, was bringt's, wenn der prozess sowieso wird? ich will vielmehr verhindern, daß er überhaupt erst gestartet wird
Um den Lösungsvorschlag zu erklaren:
Jedem Clienten teilst du eine SessionID und einen SessionKey (temporäres Passwort) zu. Für jeden Request hast du also folgende Informationen:
2002-01-16 15:36:01 /cgi-bin/.../prog.pl SessionID=123 (das Attackescript)
2002-01-16 15:36:01 /cgi-bin/.../prog1.pl SessionID=456 (ein anderer)
2002-01-16 15:36:02 /cgi-bin/.../prog1.pl SessionID=123 (Attacke!)
Also, dann sollte das prog1.pl Programm sofort merken, dass die SessionID 123 vor nur _einer_ Sekunde ein anderes Programm gestartet hat und somit sollte eine Meldung ausgegeben werden (falls es ein braver Client war) und das Programm _sofort_ beendet werden (um die Laufzeit zu verkürzen und die Attacke etwas zu vermiesen).
mag sein, daß diese ihren dienst versehen...aber leider unzureichend :-( trotzdem thanx.
Einverstanden. Sicher sind sie unzureichend, aber du wirst _nie_ eine zureichende Lösung finden, ohne andere in Mitleidenschaft zu ziehen! - Michael hat ja die einzelnen Punkte genannt.
Viele Grüsse
Philipp
hallo philipp,
Einverstanden. Sicher sind sie unzureichend, aber du wirst _nie_ eine zureichende Lösung finden, ohne andere in Mitleidenschaft zu ziehen! - Michael hat ja die einzelnen Punkte genannt.
scheint ja tatsächlich (ich bin immer schwer von etwas zu überzeugen, wenn ich anderer meinung bin *g*) keine "musterlösung" zu geben. jedenfalls werd ich versuchen, die genannten möglichkeiten zu implementieren und beobachten was dabei rauskommt. was ich ursprünglich wollte, nämlich, daß, falls in user_agent nix drin steht, erst gar kein (eigener) prozess gestartet wird, scheint wohl nur über die httpd.conf zu gehen, soweit ich michael richtig verstanden habe (hab nachsehen mit diesem satzmonstrum *g*). auf die hab ich leider keinen zugriff, und kenn mich damit auch, zugegebenermaßen, recht wenig bis gar nicht aus.
thanx,
Dirk
Halihallo
Einverstanden. Sicher sind sie unzureichend, aber du wirst _nie_ eine zureichende Lösung finden, ohne andere in Mitleidenschaft zu ziehen! - Michael hat ja die einzelnen Punkte genannt.
scheint ja tatsächlich (ich bin immer schwer von etwas zu überzeugen, wenn ich anderer meinung bin *g*) keine "musterlösung" zu geben.
Nun, es gibt eine Lösung, aber eben keine *gute* Lösung. Natürlich kannst du den Clienten zwingen sich zu registrieren und dann alle Programme einloggpflichtig zu machen, aber dann verlierst du Clienten!
jedenfalls werd ich versuchen, die genannten möglichkeiten zu implementieren und beobachten was dabei rauskommt. was ich ursprünglich wollte, nämlich, daß, falls in user_agent nix drin steht, erst gar kein (eigener) prozess gestartet wird, scheint wohl nur über die httpd.conf zu gehen, soweit ich michael richtig verstanden habe (hab nachsehen mit diesem satzmonstrum *g*). auf die hab ich leider keinen zugriff, und kenn mich damit auch, zugegebenermaßen, recht wenig bis gar nicht aus.
mit der httpd.conf? - Geht das? - Kann man da einfach sagen, wenn kein user_agent => kein Prozess? - Hm. Ich glaube nicht.
Keine Ahnung, wie man das dem WebServer verklickern soll, dass er Prozesse unterbinden soll. Da müsste man wohl schon einen eigenen programmieren.
Um mich nocheinmal zu wiederholen: Die einzige Lösung (welche die "guten" Kunden bei der Stange hält), ist, die Scripte so zu programmieren, dass sie im Falle einer Attacke möglichst schnell beendet werden (in der Hoffnung, dass dies schneller geschieht, als die Requests des Attackenden; dann hast du nämlich kein Problem mehr). Dazu musst du einige gute Kriterien haben, welche den "Attackenden" identifizieren. Ein leerer user_agent mag ein Kriterium sein, wenn auch ein schwaches (wie Michael sagt, lässt sich der ganz einfach ändern). Ein sehr viel besseres Kriterium ist es eben, dass der Attackende sehr viele Requests in kurzer Zeit ausführt. Wenn du mit Sessions arbeitest, kannst du dann diese Session einfach sperren. Arbeitest du nicht mit Sessions, musst du einfach eine "Ausgelastet" Meldung anzeigen.
Viele Grüsse
Philipp
Hi Philipp,
mit der httpd.conf? - Geht das?
Kann man da einfach sagen, wenn kein user_agent => kein Prozess?
Hm. Ich glaube nicht.
1. Schritt: Mit mod_setenvif bedingt auf Inhalte des HTTP-Headers eine Environment-Variable setzen.
2. Schritt: Mit mod_rewrite den URL dynamisch umschreiben, in Abhängigkeit vom Inhalt der Environment-Variable.
Nein, ich habe das noch nicht selbst gemacht, aber das wäre die Bauanleitung, mit der ich es versuchen würde.
Keine Ahnung, wie man das dem WebServer verklickern soll, dass er
Prozesse unterbinden soll.
Da müsste man wohl schon einen eigenen programmieren.
Es reicht, wenn man den URL umschreibt - dieser ist ja dafür zuständig, ob das CGI-Skript gestartet wird oder nicht.
Um mich nocheinmal zu wiederholen: Die einzige Lösung (welche die
"guten" Kunden bei der Stange hält), ist, die Scripte so zu
programmieren, dass sie im Falle einer Attacke möglichst schnell
beendet werden
Yep - und mod_rewrite kann Teil dieser Programmierung sein.
Dazu musst du einige gute Kriterien haben, welche den "Attackenden"
identifizieren.
Genau - hier sehe ich das Haupt-Problem.
Ein sehr viel besseres Kriterium ist es eben, dass der Attackende sehr
viele Requests in kurzer Zeit ausführt.
Um das zu merken, brauchst Du aber ein Gedächtnis - also muß das Skript die entsprechende Buchführung selbst erledigen.
Das kann der Apache alleine nicht mehr leisten, weil HTTP gedächtnislos funktioniert.
Viele Grüße
Michael
Halihallo Michael
[httpd.conf und deine Bauanleitung]: Hier kann ich leider nicht mitreden, da ich den Apache noch nie verwendet habe (d. h. online schon, aber diesen Webspace administriere nicht ich)
Keine Ahnung, wie man das dem WebServer verklickern soll, dass er
Prozesse unterbinden soll.
Da müsste man wohl schon einen eigenen programmieren.
Es reicht, wenn man den URL umschreibt - dieser ist ja dafür zuständig, ob das CGI-Skript gestartet wird oder nicht.
Klar. Ich wusste jedoch nicht, das dies funktioniert.
Ein sehr viel besseres Kriterium ist es eben, dass der Attackende sehr
viele Requests in kurzer Zeit ausführt.
Um das zu merken, brauchst Du aber ein Gedächtnis - also muß das Skript die entsprechende Buchführung selbst erledigen.
Das kann der Apache alleine nicht mehr leisten, weil HTTP gedächtnislos funktioniert.
Stimmt. Deshalb auch der Tip mit dem SessionManagement. Ansonsten werden andere User auch in Mitleidenschaft gezogen, da das Programm dann für alle "Ausgelastet" ist.
Viele Grüsse
Philipp
Hi!
Jedem Clienten teilst du eine SessionID und einen SessionKey (temporäres Passwort) zu.
So eine SessionID kann sich natuerlich auch der Angreifer staendig neu holen. Allerdings muss er dann seine echte IP-Adresse verraten, sonst erreicht ihn die Antwort nicht. Und dann wird eine sich staendig wiederholende IP-Adresse irgendwie auffallen (oder wenige verschiedene bei load-balancing Proxies).
So long