Monitoring-Skript

Fragen zur Installation von CONTENIDO 4.9? Probleme bei der Konfiguration? Hinweise oder Fragen zur Entwicklung des Systemes oder zur Sicherheit?
Antworten
kloevekorn
Beiträge: 199
Registriert: Mo 31. Okt 2005, 15:26
Wohnort: Hamburg
Kontaktdaten:

Monitoring-Skript

Beitrag von kloevekorn »

Liebe Leute,

weil die Hackerangriffe, vor allem erfolgreiche, nerven, und man solche auch bei aktuellester Contenido-Version nicht ausschließen kann, habe ich mir ein Überwachungsskript für die Verzeichnisse geschrieben.

Das Skript liegt in contenido/cronjobs und wird (mindestens) einmal am Tag aufgerufen und schickt einen Statusbericht per Mail.

Es verhindert nicht den erfolgreichen Angriff, sorgt aber für die zeitnahe Kenntnisnahme und gibt detailliert die Änderungen am Webspace aus. Bei mir hat es sich bereits sehr zuverlässig bewährt.

Das Script geht _alle_ Verzeichnisse auf dem Webspace, auch außerhalb der Contenido-Verzeichnisse durch und überprüft Veränderungen:
1 - enthält das Verzeichniss nur zulässige Dateien
2 - Änderungsdatum (wenn Heute oder Gestern) der enthaltenen Dateien.

Wer das Skript einsetzen möchte .... muss
a) alle Verzeichnisse im Webspace im Array $sollarrays ergänzen (rekursiv per PHP machen oder manuell ;). Es sind sehr viele.
b) Serverpfad $pfad_praefix angeben
c) $mail - Variablen setzen.
d) cronjob tabelle aktualisieren oder per URL das Skript ausführen.


Zwei Sachen wären aus meiner Sicht noch zu verbessern:
1 - Veränderte Dateien werden für den aktuellen _und_ letzten Tag abgefragt. Veränderte Dateien und Verzeichnisse werden dann also an zwei aufeinanderfolgenden Tagen, also doppelt, gemeldet. Der Grund für die Abfrage von heute und gestern ist natürlich, dass wenn der cronjob um 22:00 läuft, ich sonst nicht weiß, was zwischen 22:00-23:59 passiert.

2 - Bei Verzeichnissen, die sich per Definition verändern dürfen, z.B. Upload und die Unterordner habe ich noch keinen befriedigenden Lösungsansatz. Möglicherweise wäre es sinnvoll, auf Dateiendung ".php" zu prüfen, weil solche Dateien dort nicht vorkommen dürfen.

Wenn jemand für diese beiden Aufgaben eine elegante Lösung weiß ....?

Leider ist mein Coding- und Comment-Style nicht so superdufte, ich denke aber, man kann durchsteigen. Für Kommentare und Verbesserungen bin ich gerne zu haben.

Code: Alles auswählen

<?php
/*****************************************
* File      :   hackkontrolle.php
* Project   :   Contenido - 
* Descr     :   Verzeichnis√Ueberwachung um Hackerangriffe zu identifizeren. In Systemverzeichissen werden Dateien abgelegt, die da nicht hingehoeren. Diese werden durch dieses Skript erkannt, eine Nachricht wird abgesetzt. Das Skript wird durch cronjob gestartet.

√úberwachung der a) Contenido-Verzeichnisse:
contenido,contenido/includes, contenido/applets,contenido/cronjobs,contenido/external,contenido/external/backendedit,contenido/external/frontend,contenido/external/mozile,contenido/external/wysiwyg,contenido/images,contenido/images/actions,contenido/locale,contenido/logs,contenido/plugins,contenido/scripts,contenido/styles,contenido/temp,contenido/templates,contenido/tools,contenido/tools
cms, cms/includes, cms/js, cms/logs,cms/templates
conlib
docs, docs/api, docs/techref,docs/backend,docs/frontend,docs/modules,docs/plugins
downloads
pear, pear/CACHE, pear/HTML,pear/Log, pear/Net, pear/OLE,pear/OS,pear/PEAR,pear/scripts,pear/Spreadsheet, pear/XML

Erweitert um b) _alle_ Verzeichnisse auf dem Webspace, auch ausserhalb von Contenido. Es wird eine Lösung gesucht, fuer Verzeichnisse, die dynamischen Content enthalten und sich regelmäßig ändern dürfen.


* Author    :   Kloevekorn
* Created   :   29.02.2008
******************************************/
require('../../contenido/classes/class.phpmailer.php');
$heute = date("Y-m-d");
$gestern = date("Y-m-d",(strtotime("now")-86400));

$pfad_praefix= '/dasIst/der/hosting/serverpfad.de/';
$handle = fopen('hackkontrolle.log', 'a');


//verzeichnisinhalte definieren:
$sollarrays = array(
'/'=>array('.htaccess','cms','conlib','contenido','docs','downloads','error404.html','index.html','logo.jpg','pear','php.ini','phpinfo.php','phpMyAdmin'),
'cms'=>array('cache','config.php','css','dbfs.php','error.php','front_content.php','front_crcloginform.inc.php','images','includes','index.php','js','logs','php.ini','templates','upload'),
'cms/logs'=>array('index.php'),
//-----und alle weiteren Verzeichnisse auf dem Webspace
)
;
//einzelnes öffnen der definierten Verzeichnisse aus $sollarrays, und Vergleich des Sollinhalts mit aktuell enthaltenen Dateien
foreach ($sollarrays as $key=>$sollarray) {
		$verz = opendir($pfad_praefix.$key);
		if ($verz){
			$sollarray = array();
			foreach ($sollarrays[$key] as $index) {
				array_push($sollarray,$index);}
			
				$linkl=array();
				while ($file = readdir ($verz))  { 
					// akt. Verzeichnis auslesen
		    		if($file != "." && $file != ".." && $file != $filename) {
			  			// Ordner/Dateien ins Ist-Array
						array_push ($linkl, "$file");
		    			}
		 		} 
			$count_ist = count($linkl);
			$count_soll = count($sollarray);
		  // wenn sich das verzeichnis geändert hat, Array mit Dateinamen fuellen:
		   if ( $count_soll == $count_ist)	{
				//$fehlerstring .= 'OK: '.$key."\n";
				$okays++;
				
			}
			elseif ($count_ist > $count_soll) {			
				for($x = 0; $x < $count_ist; $x++) 
		  			{  if(!in_array("$linkl[$x]", $sollarray))
						{
						$fehlerstring .= "\n".$key.":".$linkl[$x]." !!! \n\n";
						fwrite ($handle,"Falsche Datei: $pfad_praefix.$key: $linkl[$x]\n");
						$errors++;
						}  
		  			}
				
			}
			else {$fehlerstring .=  "\n\nACHTUNG: ".$key." ist unterschiedlich (ist:$count_ist / soll:$count_soll) - bitte prüfen.\n\n";
				fwrite ($handle, "ACHTUNG: ".$key." ist unterschiedlich (ist:$count_ist / soll:$count_soll) - bitte prüfen.\n"); 
				$errors++;
			
			
			}	
		}
		else {$fehlerstring .= "\n\nMeldung: ".$key. " konnte nicht geöffnet werden oder wurde nicht gefunden.\n\n";
		fwrite ($handle, "\n\nMeldung: ".$key. " konnte nicht geöffnet werden oder wurde nicht gefunden.\n"); 
		$errors++;
	}
}

closedir($verz); 

foreach($sollarrays as $key=>$sollarray) //geht natürlich auch mit dem ersten verzeichnis-array.
{if ($key != 'contenido/cronjobs'){ //cronjobs nicht, weil sich die dateien immer ändern dürfen
//	$files=glob("$pfad_praefix$dir/*.*",GLOB_BRACE);
$files=glob("$pfad_praefix$key/*.*",GLOB_BRACE);

	if (is_array($files))
	{
		{foreach ($files as $filename)
		{	$filedate = date ("Y-m-d", filemtime($filename));
			if ($filedate == ($heute) || $filedate==$gestern) {
				$errors++;
				fwrite ($handle, "Geaendert am ".$filedate.": ".$filename."\n"); 
				$fehlerstring .= "\nGeaenderte Datei: ".$filedate.": ".$filename;
				}
		}}
	}
	}
}


//Ueberpruefung von CMS-Verzeichnissen, die sich aendern duerfen:
$dynamicDirs = array('cms/css','cms/cache','cms/images','cms/templates','cms/upload');
foreach ($dynamicDirs as $value)	{
		$files=glob("$pfad_praefix$value/*.*",GLOB_BRACE);
		foreach ($files as $filename) {
			if (preg_match('/(php|pl)\>/i', $filename)) {
					if ($filename != 'index.php') {
					$errors++;
					fwrite ($handle, "Unzulaessige Datei \"$filename\" in $value \n"); 
					$fehlerstring .= "\nGeaenderte Datei: ".$filedate.": ".$filename;
					}
				elseif ($filename == 'index.php') {
						if ($filedate == $heute || $filedate==$gestern) {
						$errors++;
					fwrite ($handle, "Geaendert am ".$filedate.": ".$filename."\n"); 
					$fehlerstring .= "\nGeaenderte Datei: ".$filedate.": ".$filename;
						}
					
					}
			}
		}
}





$ausgabestring = "OK: $okays Dateien/Verzeichnisse\n";
if ($errors>0) {$ausgabestring .= "Überprüfen ($errors Fehler: $fehlerstring";}



$mail = new PHPMailer();
$timestamp = time();
$datum = date("d.m.Y",$timestamp);
$uhrzeit = date("H:i",$timestamp);
$mail->From = "hackkontrolle@site.de";
$mail->FromName = "Hack-Kontrolle";
$mail->AddAddress("admin@site.de");
$mail->CharSet = "Mime-Version: 1.0 Content-Type: \"text/plain\"; charset=\"utf-8\" Content-Transfer-Encoding: \"quoted-printable\"";
$mail->Subject = "Hackkontroll site.de am $datum um $uhrzeit";
$mail->Body = $ausgabestring;

//EMail senden und überprüfen ob sie versandt wurde
if(!$mail->Send())
{
//$mail->Send() liefert FALSE zurück: Es ist ein Fehler aufgetreten
//echo "Fehler: Die Email konnte nicht gesendet werden ($datum $uhrzeit)". $mail->ErrorInfo >>hackgericht.log;
fwrite ($handle, "Fehler: Die Email konnte nicht gesendet werden ($datum $uhrzeit)\n");  
}
else
{
//$mail->Send() liefert TRUE zurueck: Die Email ist unterwegs
//echo "Die Email wurde versandt.  ($datum $uhrzeit)\n" >>hackgericht.log;
fwrite ($handle, "Email gesendet ($datum $uhrzeit).\n");  
}

?>
tina72
Beiträge: 5
Registriert: Do 28. Mai 2009, 14:40
Kontaktdaten:

Re: Monitoring-Skript

Beitrag von tina72 »

Hallo!
Vorweg, ich bin rein zufällig auf dieses Forum gestoßen, bzw. suchte ich über Google nach einem php-Script welches genau das macht wie von "kloevekorn" beschrieben. Die Idee finde ich super!

Nun weiß ich auch nicht ob ich hier überhaupt richtig bin, zu mal wir bisher nicht mit Contenido arbeiten. Auf unserem Webspace befinden sich zahlreiche Systeme wie (Wordpress, phpbb3, Joomla) mit entsprechenden Erweiterungen. Insgesamt, lt. dem letzten Backup, über 60.000 Dateien, ca. 7.500 Ordner.
Schier unüberschaubar, wenn man bedenkt, dass man täglich von unseriösen Robots "abgeklopft" wird. Die Gefahr dabei selbst zum Zombie-Server zu werden ist entsprechend groß.

Wir betreiben einen dedizierten Server, mittlerweile aber als Managed-Server – also keinen Zugriff per Root (mehr).
Nun würde ich gerne ein "Überwachungsscript", so, wie obiges Script, gerne direkt auf unserem Webspace laufen lassen, weiß aber nicht ob das unter den bereits beschrieben Voraussetzungen möglich ist, bzw. wie man genau eine Anpassung bewerkstelligen könnte.

Für eine Antwort /Hilfe wäre ich ausgesprochen dankbar!


LG Tina
Zuletzt geändert von tina72 am Do 28. Mai 2009, 15:29, insgesamt 1-mal geändert.
idea-tec
Beiträge: 1242
Registriert: Do 19. Sep 2002, 14:41
Wohnort: Dichtelbach
Kontaktdaten:

Re: Monitoring-Skript

Beitrag von idea-tec »

also, wenn man php beherrscht kann man das skript anpassen und überall einsetzen
man muss halt die einträge entsprechend anpassen und was nicht geht, wenn man contenido nicht hat ist die nutzung der email-funktion, da dies eine contenido-geschichte ist.
sowas sollte man jedoch auch integrieren können, bzw, die email-klasse des betreffenden systems nutzen können.

fazit: Ja, ist möglich und anpassbar
Allerdings:
- für jedes system ist aufwand notwendig
- es muss eine eigene email-funktion integriert oder die des jeweiligen systems genutzt werden
-> es ist in jedem fall, sofern es sich nicht um contenido handelt oder um ein contenido, das nicht im standard installiert wurde, professionelles knowhow notwendig.
MfG, Karsten
Nicht Können bedeutet nicht, dass man etwas nicht beherrscht, sondern lediglich, dass man sich nicht traut es zu tun ;-)
| Internet | Ihr Logo deutschlandweit auf T-Shirts |
Diplomatie: Jemanden so in die Hölle zu schicken, dass er sich auf die Reise freut!!! ;-)
tina72
Beiträge: 5
Registriert: Do 28. Mai 2009, 14:40
Kontaktdaten:

Re: Monitoring-Skript

Beitrag von tina72 »

Hallo Karsten,
vielen dank für Deine Antwort!

Wie sieht es denn aus wenn ich Contenido installieren würde, unter einer Subdomain, würde das die Anpassung erleichtern?
Mein Problem bisher war contenido/classes/class.phpmailer.php, logisch, da es den Pfad bzw. die Datei nicht gibt.
(Könnte man evetuell nur den phpmailer installieren)?
Des Weiteren habe ich auch nicht genau verstanden welche Ordner /Dateien ich wo/wie in das Script einzutragen habe, bzw. wie man es über den cronjob starten kann.

LG Tina
idea-tec
Beiträge: 1242
Registriert: Do 19. Sep 2002, 14:41
Wohnort: Dichtelbach
Kontaktdaten:

Re: Monitoring-Skript

Beitrag von idea-tec »

Grundsätzlich zum Skript: dieses Skript ist NATÜRLICH absolut auf eine Contenido-Installation abgestimmt.
Wenn du euren KOMPLETTEN Server damit überwachen willst, nutzt dir auch eine Contenido-Installation auf einer Subdomain nicht viel, da das Skript im Original dann auch NUR diese Contenido-Installation überwacht!!!

@cronjob:
a.) hierzu gibt es auf Servern entsprechende Befehle und Möglichkeiten, man muss jedoch einen SSH-Zugriff (mit entsprechenden Rechten) auf den Server haben. Dann kannst du dort das aufrufen der skript-Datei zeitgesteuert durch den server selbst ausführen lassen.
b.) man kann sich im web diverser cronjob-dienste bedienen, die man entsprechend beziehen kann (teils sogar kostenlos, kann das jedoch nicht verbürgen)

Das Fazit ist: Zur Anpassung dieses Skripts zur Überwachung des kompletten Servers bedarf es definitiv entsprechend profesioneller Unterstützung
Keine Werbung oder Anbiederung, aber ich, bzw. mein Unternehmen kann dies (inkl. externem cronjob-dienst, falls ihr keinen entsprechenden zugriff auf den server besitzt) umsetzen.
MfG, Karsten
Nicht Können bedeutet nicht, dass man etwas nicht beherrscht, sondern lediglich, dass man sich nicht traut es zu tun ;-)
| Internet | Ihr Logo deutschlandweit auf T-Shirts |
Diplomatie: Jemanden so in die Hölle zu schicken, dass er sich auf die Reise freut!!! ;-)
tina72
Beiträge: 5
Registriert: Do 28. Mai 2009, 14:40
Kontaktdaten:

Re: Monitoring-Skript

Beitrag von tina72 »

Hallo Karsten,
vielen Dank für Deine Antwort. Und ja, natürlich den KOMPLETTEN Server, zumindest was die "Ftp-Ebene" anbelangt. Den Cronjob könnte man auch über uns starten, allerdings müsste ich es bewerkstelligen lassen, (da kein ssh-root-zugriff mehr - Managed-Server). Das Script sollte "alleine" die Ordner- Serverstruktur erkennen, da sich "die Dinge" laufend ändern, bzw. weil wir bereits jetzt schon "reichlich beladen" sind. Werde darüber nachdenken, es bei uns besprechen.

LG Tina
muensmedia
Beiträge: 8
Registriert: Mo 2. Mär 2009, 17:58
Kontaktdaten:

Re: Monitoring-Skript

Beitrag von muensmedia »

Hier meine Lösung:
Diese Lösung läuft auch ganz ohne Contenido, es können Verzeichnisse von der Überprüfung ausgenommen werden.
Es wird auch nach einer Modifikation innerhalb der letzten 24h gesucht und per Mail zugesendet.

Code: Alles auswählen

<?php
// Dieses Verzeichnis & alle Unterverzeichnisse werden überprüft
  $pruefe = './ksw';
// Verzeichnisse die nicht überprüft werden 
  $dynamicDirs = array('./ksw/contenido/logs', './ksw/contenido/cronjobs');
// Name der Überprüfung z.B. Domainname
  $site = 'Domain.de';
// Email Adresse
  $email = 'admin@domain.de';

// -------------------------------------------------------------------------------------------- //
function isStatic ($path){
	
  global $dynamicDirs;
	if (in_array($path, $dynamicDirs))
	  return false;
	else 
	  return true;
}

function ListFiles($dir) {

    if($dh = opendir($dir)) {

        $files = Array();
        $inner_files = Array();

        while($file = readdir($dh)) {
            if($file != "." && $file != ".." && $file[0] != '.') {
                if(is_dir($dir . "/" . $file) && isStatic($dir . "/" . $file)) {
                    $inner_files = ListFiles($dir . "/" . $file);
                    if(is_array($inner_files)) $files = array_merge($files, $inner_files); 
                } else {
                    array_push($files, $dir . "/" . $file);
                }
            }
        }

        closedir($dh);
        return $files;
    }
}

foreach (ListFiles($pruefe) as $key=>$file){
	if (filemtime($file) >= (time()-(60*60*24))){
		$content.= "<tr><td>".$file ."</td><td>".filesize($file)."</td><td>".date('d.m.Y H:i',filemtime($file))."</td></tr>\n";
		$fehler++;
	}
      
    $i++;
}

$mail='
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="de"><head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <style type="text/css">
    html * { padding:0; margin:0; }
    body * { padding:10px 20px; }
    body * * { padding:0; }
    body { font:small sans-serif; background:#eee; }
    body>div { border-bottom:1px solid #ddd; }
    h1 { font-weight:normal; margin-bottom:.4em; }
    h1 span { font-size:60%; color:#666; font-weight:normal; }
    table { border:none; border-collapse: collapse; width:100%; }
    td, th { vertical-align:top; padding:2px 3px; }
    th { width:12em; text-align:right; color:#666; padding-right:.5em; }
    #info { background:#f6f6f6; }
    #info ol { margin: 0.5em 4em; }
    #info ol li { font-family: monospace; }
    #summary { background: #aaa; }
    #explanation { background:#eee; border-bottom: 0px none; }
    #head {background: #aaa;}
  </style>
</head><body>
  <div id="summary">

    <h1>Virenalarm <span>('.$site.' am '.date('d.m.Y H:i', time()).')</span></h1>
</div>
  <div id="info">
    
      <p>&nbsp;</p>
      <p>Es wurden die folgenden Dateimodifikationen innerhalb der letzten 24 Stunden festgestellt.</p>
      <p>Bei den aufgef&uuml;hrten Dateien k&ouml;nnte es sich um Schadcode handeln.</p>
      <p>&nbsp;</p>
      <p><b>'.$i.' Dateien &uuml;berpr&uuml;ft, '.$fehler.' Dateien verd&auml;chtig!</b></p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
		<table>
		  <tr id="head">
		    <td>Datei</td>
		    <td>Size</td>
		    <td>Modifiziert:</td>
		  </tr>
		  '.$content.'
		</table>
	  <p>&nbsp;</p>
	  <p>&nbsp;</p>
</div>

  <div id="explanation">
  	<p>'.$_SERVER['SERVER_SIGNATURE'].'</p>
	<img src="http://img.muensmedia.de/logo.png" alt="[mm] muensmedia" />

</div>

</body></html>
';

$header="From: ".$email." <".$email.">\n";
$header.= 'MIME-Version: 1.0' . "\n";
$header .= 'Content-type: text/html; charset=iso-8859-1' . "\n";
$betreff = "Virenalarm(".$site." am ".date('d.m.Y H:i', time()).")";

if ($errors > 0)
  mail($email, $betreff, $mail, $header);

?>
Wünsche damit viel Spaß.
Anregungen / Kritik sind erwünscht. :wink:

Viele Grüße
Malte
Antworten