Threat Intelligence

work in progress / Analyse der gesammelten Firewall Drops / Datenbank Design usw..

Zielsetzung

Alle Drops mit bestimmten Eigenschaften die auf der Firewall extern einschlagen protokollieren um daraus Hinweise auf gehackte Systeme zu gewinnen

Interessant wird dann die andere Richtung auf anderen Systemen - welche Endgeräte versuchen auf IP Adressen von Intern nach Extern zuzugreifen auf IPs die aus den historischen Daten gewonnen wurden

Datenbank

Ich möchte in der Lage sein SQL Queries auf die Daten abzusetzen

MariaDB [inteldb]> desc raw;
+---------------+--------------+------+-----+---------------------+-------------------------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------------------+-------------------------------+
| hash | char(64) | NO | PRI | NULL | |
| original | varchar(450) | NO | | NULL | |
| src | varchar(100) | NO | MUL | NULL | |
| dst | char(40) | NO | MUL | NULL | |
| dpt | int(11) | NO | MUL | NULL | |
| spt | int(11) | NO | MUL | NULL | |
| proto | varchar(15) | NO | MUL | NULL | |
| country | char(2) | NO | | NULL | |
| originalDate | datetime | NO | MUL | NULL | |
| insertionDate | timestamp | NO | | current_timestamp() | on update current_timestamp() |
+---------------+--------------+------+-----+---------------------+-------------------------------+

Storage Engine default-storage-engine = Aria - als Nachfolger von myisam - ich benötige Crash resistenten Table

Schnittstelle f. Datebank / Input der Daten

syslog-ng loggt direkt auf eine pipe / für das Skript macht es keinen Unterschied ob ein Logfile gelesen wird oder die Pipe geöffnet

<?php
// Shouldn't be used anymore
//declare(ticks = 1);
pcntl_async_signals(true);
pcntl_signal(SIGINT,'exit_handler');
$db_servername="";
$db_username="";
$db_name="";
$db_password="";
require_once("geoip2.phar");
use GeoIp2\Database\Reader;
if(!isset($argc) || $argc !== 2 )
{
echo "\nParamters count wrong \n";
exit(2);
}
$input_file=$argv[1];
if(!is_readable($input_file))
{
echo "\nCannot read: ".$input_file."\n";
exit(2);
}
$fp = fopen($input_file,"r");
global $entriesOk;
global $entriesFail;
$entriesOk=0;
$entriesFail=0;
$db_connection = new mysqli($db_servername,$db_username,$db_password,$db_name);
if($db_connection->connect_error)
{
echo "\nCannot connect to database: $db_servername : $db_username : $db_name \n";
exit(2);
}
$insert_statement=$db_connection->prepare("INSERT into raw (hash,original,src,dst,dpt,spt,proto,country,originalDate) values (?,?,?,?,?,?,?,?,? )");
while( ($line=fgets($fp,1024)) !== false)
{
//echo $line."\n";
$matches=array();
$matches_count=preg_match_all('/[A-Z]+=[A-Z,a-z,0-9,\.,:]+/i',$line,$matches);
if($matches_count > 1 )
{
$inputMaster=array();
$matches=$matches[0];
for($i=0; $i<count($matches); $i++)
{
$cut_array=explode("=",$matches[$i]);
if(count($cut_array)== 2)
{
$inputMaster[$cut_array[0]]=$cut_array[1];
}
}
//Jan 26 01:46:54
if(preg_match('/^[A-Z,a-z]{3}[ ]{1}[0-9]{1,2}[ ]{1}([0-9]{1,2}:){2}[0-9]{1,2}/i',$line,$matches_time)===0)
{
$inputMaster["timestamp"]=time();
$inputMaster["datetime"]= date("Y-m-d H:i:s",$inputMaster["timestamp"]);
$inputMaster["original_time"]=false;
}
else
{
$inputMaster["timestamp"]=strtotime($matches_time[0]);
$inputMaster["datetime"]= date("Y-m-d H:i:s",$inputMaster["timestamp"]);
$inputMaster["original_time"]=$matches_time[0];
}
$inputMaster["original_line"]=$line;
$inputMaster["hash"]=hash('sha256',$line);
if(isset($inputMaster["SRC"]))
{
$inputMaster["country"]=getCountry($inputMaster["SRC"]);
}
else
{
$inputMaster["SRC"]="00";
$inputMaster["country"]="00";
}
if(isset($inputMaster["DST"]))
{
$inputMaster["DST"]=hash('sha1',$inputMaster["DST"]);
}
else
{
$inputMaster["DST"]=hash('sha1',"00");
}
if(!isset($inputMaster["DPT"]) || strlen($inputMaster["DPT"])===0 )
{
$inputMaster["DPT"]=0;
}
if(!isset($inputMaster["SPT"]) || strlen($inputMaster["SPT"])===0 )
{
$inputMaster["SPT"]=0;
}
$entriesOk++;
$insert_statement->bind_param("ssssiisss",$inputMaster["hash"],$inputMaster["original_line"],$inputMaster["SRC"],$inputMaster["DST"],$inputMaster["DPT"],$inputMaster["SPT"],$inputMaster["PROTO"],$inputMaster["country"],$inputMaster["datetime"]);
//print_r($inputMaster);
if($insert_statement->execute())
{
$entriesOk++;
}
else
{
$entriesFail++;
echo "MYSQL Failure: ".$insert_statement->error."\n";
print_r($inputMaster);
}
if( !( $entriesOk % 1000) || !( $entriesFail %1000) )
{
echo "\nInsertion OK: $entriesOk \nInsertion FAIL: $entriesFail ";
echo "\nStats Entries handeled total: ".($entriesOk+$entriesFail);
}
}
else
{
$entriesFail++;
}
}
echo "\n Program quit !";
echo "\nInsertion OK: $entriesOk \nInsertion FAIL: $entriesFail ";
echo "\nStats Entries handeled total: ".($entriesOk+$entriesFail);
exit(0);
function getCountry($ip)
{
try
{
$reader = new Reader('/usr/local/etc/dbip-country.mmdb');
return $reader->country($ip)->country->isoCode;
}
catch(Exception $e)
{
return "00";
}
}
function exit_handler($signal)
{
echo "It's over'";
exit(2);
}
?>

Logging

Zentraler Server Beispiel syslog server auf 192.168.1.1 linux syslog.conf

..
destination d_intel { network("192.168.1.1" port(514) transport(udp)); };
filter f_firewall_intel { message("fw") and message("EXT-FW") and message("DROP"); };
log { source(s_src); filter(f_firewall_intel); destination(d_intel);};
..

openwrt /etc/config/system

..
option log_ip '192.168.1.1'
option log_port '514'
option log_proto 'udp'
..

API