Kibana
ONLINE

Absicherung mit mod_security und Spiderlabs OWASP

Ein von außen erreichbarer Webserver steht immer irgendwie unter Attacke; doch in den letzten Wochen habe ich live immer mehr Fälle erfolgreicher WordPress-Hacks erlebt und debuggt, und mein Respekt vor der Sache wuchs. Denn die Attacken sind alles, von stumpfsinnig bis richtig clever, und überwiegend hat man ja nicht in der Hand, was da abgeht.

Meine ersten Versuche machte ich mit fail2ban — der Erfolg war vorhanden, aber für meinen Geschmack nicht durchschlagend genug. Da ich jedoch sicher nicht der einzige Mensch mit diesem Problem bin, machte ich mich im Netz auf die Suche — und fand das OWASP ModSecurity Core Rule Set (CRS).

»The Open Web Application Security Project (OWASP) ModSecurity Core Rule Set (CRS) is a set of generic attack detection rules for use with ModSecurity or compatible web application firewalls. The CRS aims to protect web applications from a wide range of attacks, including the OWASP Top Ten, with a minimum of false alerts.«

Die Vorgehensweise ist gar nicht so kompliziert: den apache2 mit mod_security versehen; ihn dazu bringen, die OWASP-Regeln anzuwenden; und dann Logs lesen, sehr viele Logs lesen, um das Ganze gegebenenfalls an die eigenen Belange anpassen zu können. Im ersten Anlauf habe ich es mit nginx versucht, aber das war mir für den Produktivbetrieb zu frickelig — damit angefangen, dass ich alles von Hand kompilieren musste, es ist einfach noch zu experimentell…

Die Installation von mod_security

Für den apache2 gestalten sich Installation und Inbetriebnahme dank fertig geschnürter Pakete jedoch erfreulich unkompliziert:

$ apt-get install libapache2-mod-security2
$ cd /etc/modsecurity
$ cp modsecurity.conf-recommended modsecurity.conf
$ a2enmod security2
$ a2enmod headers
$ service apache2 restart

OWASP CRS

OWASP und das, was mod_security per Default so installiert, sollen sich nicht ins Gehege geraten; deshalb werfe ich die Defaults aus dem System und ziehe mir von GitHub den master. Für den Produktivbetrieb bietet es sich eventuell an, auf das aktuelle Release zurückzugreifen — aber das überlasse ich euch.

$ cd /usr/share
$ rm -rf modsecurity-crs
$ git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git modsecurity-crs
$ cd modsecurity-crs
$ cp crs-setup.conf.example crs-setup.conf

Jetzt muss in der apache2-Konfiguration noch hinterlegt werden, dass diese Regeln zukünftig ausgewertet werden sollen. Der Inhalt meiner Datei /etc/apache2/mods-available/security2.conf gestaltet sich nun wie folgt:

<IfModule security2_module>
  SecDataDir /var/cache/modsecurity
  IncludeOptional /etc/modsecurity/*.conf
  IncludeOptional /usr/share/modsecurity-crs/*.conf
  IncludeOptional /usr/share/modsecurity-crs/rules/*.conf
</IfModule>

Anpassungen der Konfiguration

Nach Installation ist zwar alles, was benötigt ist, vorhanden, aber sozusagen im Leerlauf: in /etc/modsecurity/modsecurity.conf steht SecRuleEngine auf DetectionOnly, was nichts anderes bedeutet als dass nichts aktiv geblockt wird. Aber: es ermöglicht, im Logfile zu verfolgen, was geblockt werden würde — so kann bereits vor Scharfschaltung ein fein abgestimmtes Regelwerk erarbeitet werden. Im Idealfall kommt es dann (sobald SecRuleEngine auf On gesetzt wird) nicht oder kaum zu irrtümlich geblockten Inhalten. Weitere Informationen zu den Parametern finden sich hier; die Parameter, die ich in meiner Konfiguration verändert habe, habe ich in Anhang A gelistet. Restart des apache2 ist nach Änderung der Konfiguration erforderlich, um diese Änderungen zu übernehmen; im Logfile — im Beispiel /var/log/apache2/error.log — wird ersichtlich, dass ModSecurity installiert ist und die Arbeit aufnimmt.

Betrachtung der Logfiles

Im Produktivbetrieb wird nun viel mit Logfiles jongliert. Ich zeige euch hier einen Eintrag aus dem error.log meiner Domain urban-exploring.eu, die unter fortgesetzten Attacken steht — da ist irgendwie immer was los. Der Übersichtlichkeit halber splitte ich den Eintrag zeilenweise auf:

[Mon Oct 02 10:49:24.204427 2017]
[:error]
[pid 19901]
[client 199.249.224.43:57940]
[client 199.249.224.43] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score.
[file "/usr/share/modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"]
[line "57"]
[id "949110"]
[msg "Inbound Anomaly Score Exceeded (Total Score: 5)"]
[severity "CRITICAL"]
[tag "application-multi"]
[tag "language-multi"]
[tag "platform-multi"]
[tag "attack-generic"]
[hostname "urban-exploring.eu"]
[uri "/xmlrpc.php"]
[unique_id "WdH9lLxEOzQAAE29EE8AAAAA"]

Fett markiert die id der auslösenden Regel — hier kann man sie herausgreifen, wenn man sie explizit abschalten möchte — und die unique_id: nach dieser könnt ihr in /var/log/apache2/modsec_audit.log (oder was immer ihr als SecAuditLog definiert) suchen und nähere Angaben erhalten. Schaut hier im Beispiel den Auszug für A und beachtet die Übersicht in Anhang B — das A steht für audit log header:

--1e20ae12-A--
[02/Oct/2017:10:49:24 +0200] WdH9lLxEOzQAAE29EE8AAAAA 199.249.224.43 57940 127.0.0.1 8080

Das F steht für die response headers — die Anfrage wurde mit Status Code 403 abgelehnt (wobei auch das konfigurierbar ist):

--1e20ae12-F--
HTTP/1.1 403 Forbidden
Strict-Transport-Security: max-age=63072000; includeSubdomains; preload
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Content-Length: 287
Connection: close
Content-Type: text/html; charset=iso-8859-1

Und so weiter. Es ist ein ziemlich weites Feld, und ich hab schon eine ganze Weile gebraucht, bis ich einigermaßen den Durchblick hatte — was in meinem Falle aber auch durch ein geschachteltes Proxy-Setup erschwert wurde, in dem auch der nginx kräftig herumfunkt 😇

Ausnahmen definieren

Entweder schalte ich mod_security für einen VHost explizit ab (SecRuleEngine Off) — bei einer Nextcloud-Instanz habe ich das erstmal so gehandhabt, weil mit aktiviertem ModSecurity überhaupt nichts mehr funktioniert hat — oder ich nehme explizit Regeln anhand ihrer ID von der Ausführung aus (SecRuleRemoveById). Wobei: handelt es sich hier um eine Regel, die in mehreren Kontexten Ärger bereitet, kann natürlich auch das ganze Regel-File entfernt werden.

## Fuer den gesamten VHost
<LocationMatch .*>
  <IfModule mod_security2.c>
    SecRuleEngine Off
  </IfModule>
</LocationMatch>
## Fuer einen Unterbereich des VHosts
<LocationMatch "/wp-(admin|login)/">
  <IfModule mod_security2.c>
    SecRuleRemoveById 931100
    SecRuleRemoveById 930120
  </IfModule>
</LocationMatch>

Fazit

Zugegeben: ich bin überrascht, was da alles aufläuft — mein Webserver ist ja lächerlich klein im Vergleich zu vielen anderen. Insofern war es eine noch spannendere Sache, das Setup auf einem shared hosting aufzuziehen: viele Webseiten, viele User, richtig viele Requests. Dort läuft es ebenfalls produktiv, jedoch unter sehr strenger Beobachtung. Ein ELK-Stack bietet sich zum Debuggen sehr an, vor allem auf dem shared hosting, man wird sonst schnell verrückt mit den ganzen Logs…

Erzählt doh mal: wie handhabt ihr das so? Welche Tools setzt ihr ein? UnterschriftOder ist euch das Attacken-Problem eher fremd?


Anhang A: Geänderte Parameter in modsecurity.conf

name default my value info
SecRuleEngine DetectionOnly On Generelles Einschalten
SecStatusEngine On Off Möchte nach Hause telefonieren, was ich auf diese Art unterbinde
SecAuditLogParts ABDEFHIJZ ABDEFIJZ Was alles nach modsec_audit.log geloggt werden soll; Erklärung der Parameter siehe Anhang B
SecResponseBodyAccess On Off Access response bodies
SecRequestBodyLimit 13107200 1073741824 In Bit; korrespondiert mit max_upload_size & Co., deshalb erhöht auf 128MB
SecRequestBodyInMemoryLimit 131072 655360 Ggf. Erhöhung in Erwägung ziehen

Anhang B: SecAuditLogParts

Letter Description
A Audit log header (mandatory)
B Request headers
C Request body
D Reserved
E Response body
F Response headers
G Reserved
H Audit log trailer which contains additional data
I Compact request body alternative to part C which excludes files
J Reserved
K Contains a list of all rules that matched for his transaction
Z Final boundary (mandatory)
  1. Ich finde den Titel deines Blogs so grandios. 😁

    via twitter.com

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.