Protokolldateien
About 25% of the activity is 200-OKEtwa 25 % der Aktivität ist 200-OK
Ich habe festgestellt, dass mein Webserver einige Protokolldateien seit einem Jahr und andere seit einem Monat speichert. Ich habe drei Arten von Protokolldateien untersucht, die Informationen über Besucher des Servers enthalten (es gibt andere Dateien, die weniger interessant erscheinen). Hier einige typische Beispiele:
Der auth.log (IPs geändert)
Oct 23 06:02:24 server1 sshd[20172]: Failed password for invalid user admin from 192.168.1.1 port 64721 ssh2
Oct 23 06:09:01 server1 CRON[20181]: pam_unix(cron:session): session opened for user root by (uid=0)
Oct 23 06:09:01 server1 CRON[20181]: pam_unix(cron:session): session closed for user root
Oct 23 06:10:35 server1 sshd[20195]: Did not receive identification string from 192.168.1.1
Oct 23 06:10:40 server1 sshd[20196]: Invalid user admin from 192.168.1.1
Oct 23 06:10:40 server1 sshd[20196]: input_userauth_request: invalid user admin [preauth]
Oct 23 06:10:41 server1 sshd[20196]: pam_unix(sshd:auth): check pass; user unknown
Autorisierungsversuche auf einem Webserver stellen Anmeldeversuche dar, entweder von mir, von Software, die auf meinen Server gehört (CRON, oben), oder von einer anderen Person oder einem anderen Computer (jemand, der die Benutzer-ID „admin“ verwendet, oben). Admin fällt in die Kategorie „Bösewichte“.
Der access.log (Apache-Server) (IPs geändert)
192.168.2.2 - - [30/Aug/2016:08:30:29 -0400] "GET / HTTP/1.1" 200 1714 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
192.168.1.1 - - [30/Aug/2016:08:51:52 -0400] "GET /hndUnblock.cgi HTTP/1.0" 404 496 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:52 -0400] "GET /tmUnblock.cgi HTTP/1.0" 404 495 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:52 -0400] "GET /cgi/common.cgi HTTP/1.0" 404 496 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:53 -0400] "GET /stssys.htm HTTP/1.0" 404 492 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:53 -0400] "GET / HTTP/1.0" 200 1714 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:54 -0400] "POST /command.php HTTP/1.0" 404 493 "-" "Wget(linux)"
192.168.3.3 - - [30/Aug/2016:09:09:01 -0400] "GET /?feed=rss2 HTTP/1.1" 200 794 "-" "Feedly/1.0 (+http://www.feedly.com/fetcher.html; like FeedFetcher-Google)"
Die Zugriffsprotokolleinträge stellen Versuche dar, eine Webseite vom Server abzurufen. Die erste Zeile oben stellt eine gültige Anfrage eines Webcrawlers dar ( Baidu , eine chinesische Suchmaschine). Die Get-Anfrage bezog sich auf /, die Hauptseite. Die 200 bedeutet, dass die Seite ordnungsgemäß bereitgestellt wurde. Die nächsten sechs Zeilen haben alle ein 404-Ergebnis (nicht gefunden). Dies ist ein Hacker, der versucht, einen falsch konfigurierten Webserver zu finden. Nach mehreren Versuchen bemerkte eine Überwachungssoftware (Fail2Ban), was passierte, und sperrte ihn aus. Früher dachte ich, Fail2Ban sei wirklich wichtig (ist es immer noch!), aber dann erfuhr ich von UFW, der Uncomplicated Fire Wall, und einer noch größeren Bedrohung.
Hier ist die UFW.log :
Oct 9 04:35:21 server1 kernel: [5110701.311961] [UFW BLOCK] IN=venet0 OUT= MAC= src=175.9.9.9 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=40 ID=53848 DF PROTO=TCP SPT=10651 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:35:24 server1 kernel: [5110704.311558] [UFW BLOCK] IN=venet0 OUT= MAC= src=175.8.8.8 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=40 ID=53849 DF PROTO=TCP SPT=10651 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:35:36 server1 kernel: [5110715.912365] [UFW BLOCK] IN=venet0 OUT= MAC= src=112.7.7.7 DST=192.168.1.1 LEN=40 TOS=0x00 PREC=0x00 TTL=39 ID=32234 PROTO=TCP SPT=60061 DPT=23 WINDOW=16244 RES=0x00 SYN URGP=0
Oct 9 04:35:46 server1 kernel: [5110726.213736] [UFW BLOCK] IN=venet0 OUT= MAC= src=67.6.6.6 DST=192.168.1.1 LEN=44 TOS=0x00 PREC=0x40 TTL=239 ID=7084 PROTO=TCP SPT=57510 DPT=23 WINDOW=14600 RES=0x00 SYN URGP=0
Oct 9 04:37:02 server1 kernel: [5110802.146865] [UFW BLOCK] IN=venet0 OUT= MAC= src=139.5.5.5 DST=192.168.1.1 LEN=40 TOS=0x00 PREC=0x00 TTL=39 ID=33753 PROTO=TCP SPT=6885 DPT=23 WINDOW=9693 RES=0x00 SYN URGP=0
Oct 9 04:37:53 server1 kernel: [5110853.056320] [UFW BLOCK] IN=venet0 OUT= MAC= src=87.4.4.4 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=54 ID=61204 DF PROTO=TCP SPT=47013 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:37:56 server1 kernel: [5110856.056659] [UFW BLOCK] IN=venet0 OUT= MAC= src=87.3.3.3 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=54 ID=61205 DF PROTO=TCP SPT=47013 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:38:02 server1 kernel: [5110862.056195] [UFW BLOCK] IN=venet0 OUT= MAC= src=87.2.2.2 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=54 ID=61206 DF PROTO=TCP SPT=47013 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:39:04 server1 kernel: [5110924.610656] [UFW BLOCK] IN=venet0 OUT= MAC= src=175.1.1.1 DST=192.168.1.1 LEN=40 TOS=0x00 PREC=0x00 TTL=43 ID=16953 PROTO=TCP SPT=35941 DPT=23 WINDOW=41293 RES=0x00 SYN URGP=0
Jede Zeile der UFW BLOCK-Zeilen stellt eine andere Art von Angriff auf einen Server dar: die Suche nach einem falsch konfigurierten Port. Alle diese Zeilen testen DPT=23 Telnet , ein altes Protokoll. Beachten Sie, dass dies mindestens einmal pro Minute geschieht. Den ganzen Tag. Täglich.
Laden Sie die Daten in eine Datentabelle
Jede der Dateien ist anders formatiert, die Datumsangaben enthalten möglicherweise nicht das aktuelle Jahr, Felder haben möglicherweise Name=Wert oder sind einfach positionell. Ich habe alle Dateien vom Linux-Server auf meinen Windows-Rechner verschoben und FilesInDirectory verwendet, um eine Liste der Dateinamen in JSL abzurufen. Dann habe ich eine Reihe von Mustern geschrieben, um die drei Dateitypen effizient zu analysieren. Die Spalten der Datentabelle wurden ausgewählt, um die Daten darzustellen, die ich aus den einzelnen Dateien erfassen wollte:
Columns in tableSpalten in der Tabelle
ipaddr32 ist eine Formelspalte, um 1.2.3.4 in 1<<24 + 2<<16 + 3<<8 + 4 für eine kontinuierliche Achse in einem Diagramm umzuwandeln. IP-Name wird später nachgeschlagen. kind2 ist eine Formel, um alle verschiedenen Benutzer-IDs auf nur „Login“ zu reduzieren.
path = "f:/logs/";
list = Files In Directory( path, "recursive" );
global:dt = New Table( "logData",
New Column( "datetime", Numeric, "Continuous", Format( "ddMonyyyy:h:m:s", 18, 0 ), Input Format( "ddMonyyyy:h:m:s", 0 )),
New Column( "ipaddr", Character, "Nominal" ),
New Column( "kind", Character, "Nominal" ),
New Column( "detail1", Character, "Nominal" ),
New Column( "detail2", Character, "Nominal" )
);
Effizientes Parsen
Für maximale Geschwindigkeit bei großen Dateien muss die JSL-Analyse in einem einzigen PatMatch-Funktionsaufruf erfolgen. Jeder Aufruf von PatMatch hat einen gewissen Overhead, und wenn Sie mehrere Aufrufe tätigen, zerhacken Sie wahrscheinlich auch die Eingabezeichenfolge, was zu einem höheren Overhead führt. Machen wir es also mit einem PatMatch pro Protokolldatei. Die Schlüssel sind zwei Mustervergleichsfunktionen: PatRepeat und PatTest. PatRepeat lässt das Muster für jede Zeile in der Datei wiederholen. PatTest lässt das Muster während des Abgleichs etwas JSL ausführen (nominal, um eine Bedingung zu testen, aber unser Testergebnis wird immer „wahr“ sein). Ein paar Hilfsmuster und dann geht es los mit den guten Sachen ...
ipPattern = patRegex("(\d{1,3}[-.]\d{1,3}[-.]\d{1,3}[-.]\d{1,3})|([a-fA-F0-9:]+)"); // approximation
ipMonth=patRegex("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec");
datePattern1 = "[" + patregex("\d{2}")>>day + "/" + ipMonth>>month + "/" + patregex("\d{4}")>>year + ":" + patregex("\d\d:\d\d:\d\d")>>time + patregex(" [-+]\d{4}") +"]"; // [18/Sep/2016:06:14:25 -0400]
datePattern2 = ipMonth>>month + patspan(" ") + patregex("\d{1,2}")>>day + " " + patregex("\d\d:\d\d:\d\d")>>time + pattest(year="2016";1); //vs Oct 16 04:54:31 the unknown year is 2016 for these logs
quote = "\!"";
quotepattern = quote + patrepeat(patbreak(quote||"\") +(("\"+(quote|""))|"")) + quote; // allows \" escaped embedded quotation marks
Die beiden Datumsmuster stimmen mit den beiden Datumsformaten überein. Der >>-Operator fügt den passenden Text links in die Variable rechts ein. PatTest(year="2016";1) gibt immer true zurück, nachdem 2016 dem Jahr zugewiesen wurde; Dies gilt für die Protokolldateien ohne explizite Jahresangabe. Ich verwende eine Mischung aus Mustern und regulären Ausdrücken, um immer größere Muster aufzubauen. Hier ist das Apache-Access.log-Muster:
apachePat = ipPattern>>ip+" "+patbreak(" ")+" "+patbreak(" ")+" "
+datePattern1+" "
+quotePattern>>request+" "
+patbreak(" ")>>code+" "
+patbreak(" ")>>length+" "+patbreak(" ")+" "
+(quotePattern|patbreak("\!n\!r"))>>browser
+pattest(
dt1<<ADDROWS></ADDROWS>
Vergleichen Sie die Wirkung mit einer Zeile aus dem access.log
192.168.1.1 - - [30/Aug/2016:08:51:52 -0400] "GET /tmUnblock.cgi HTTP/1.0" 404 495 "-" "Wget(linux)"
und beachten Sie das pattest(...) am Ende; Es fügt der Tabelle dt1 eine Zeile hinzu und füllt die Spalten mit den gerade analysierten Werten.
Es gibt auch UFW- und Authentifizierungsmuster. Hier ist die Funktion zum Parsen einer Datei:
global:skipPattern = (patbreak("\!n\!r") + patlen(1))>> unknown + pattest(show(filename,unknown);stop();1);
global:whitespace = patregex("\s*");
parser = Function( {filename, pattern, dt1}, {Default Local},
txt = Load Text File( filename );
rc = Pat Match( //
txt, //
Pat Pos( 0 ) //
+ Pat Repeat( ((global:whitespace + pattern + global:whitespace) | global:skipPattern) + Pat Fence() ) //
+ Pat R Pos( 0 ) //
); //
);
Die Funktion lädt ein Protokoll aus Dateiname, analysiert es mithilfe des Musterparameters und speichert die Ergebnisse in dt1. Die PatMatch-Funktion erstellt ein Wechselmuster, das das Überspringen nicht erkannter Zeilen ermöglicht. PatFence() ist eine weitere Optimierung für große Dateien; Das bedeutet: „Wenn Sie so weit gekommen sind, macht es keinen Sinn, eine Sicherungskopie zu machen und etwas anderes auszuprobieren.“ Außerdem kann es sowohl das Spiel beschleunigen als auch den benötigten Speicher reduzieren. Abschließend ist hier der Treiber für die Funktion:
While( N Items( file = Remove From( list, 1 ) ) == 1, //
file = file[1];//
If(//
!Is Missing( Regex( file, "ssl_access.log" ) ), //
parser( path || file, apachePat, global:dt );//
, // else
!Is Missing( Regex( file, "other_vhosts_access.log" ) ), //
0//parser( path || file, apachePat, global:dt );//
, // else
!Is Missing( Regex( file, "access.log" ) ), //
parser( path || file, apachePat, global:dt );//
, // else
!Is Missing( Regex( file, "ufw.log" ) ),
parser( path || file, ufwPat, global:dt );//
, // else
!Is Missing( Regex( file, "auth.log" ) ), //
parser( path || file, authPat, global:dt );//
);//
);//
Sehenswürdigkeiten
Der Raspberry PI-Computer scheint mit dem Benutzernamen PI viele Angriffe anzuziehen. PHP-Skripte müssen häufig falsch konfiguriert werden. Es gibt viele Prüfungen für bestimmte PHP-„Admin“-Dateien. Und es muss wirklich wertvoll sein, einen offenen Port zu finden, der eine Schwachstelle aufweist. Bei der überwiegenden Mehrheit der Angriffe handelt es sich um das Testen von Ports. Wenn Sie einen Webserver verwalten und keine Fail2ban- und Firewall-Regeln (wie UFW) verwenden, sollten Sie deren Installation und Konfiguration in Betracht ziehen. Sie können einen Brute-Force-Angriff verlangsamen, indem Sie einige Versuche pro Tag statt mehrerer Versuche pro Sekunde zulassen.
Dashboard view of web trafficDashboard-Ansicht des Webverkehrs