Firewall/WAF mit PHP: Whitelist und Blacklist mit IP-Adressen für PHP-Scripte

Firewall/WAF mit PHP: Whitelist und Blacklist mit IP-Adressen für PHP-Scripte

Heute möchte ich hier einen kurzen Artikel mit einigen Beispielen wie eine Firewall/WAF mit PHP umgesetzt werden kann veröffentlichen.

Ich habe hierzu 4 Beispiele erstellt darunter eine Whitelist, eine Blacklist, eine Blackliste mit einer Textdatei als IP-Blockliste und ein Beispiel zur Umsetzung einer mini-WAF.

Alle Codebeispiele sind darauf ausgelegt im oberen Bereich bereits vorhandener Scripte eingefügt zu werden.

PHP Whitelist

Die erlaubten IP-Adressen befinden sich im Array $waf – welches natürlich auch erweitert werden kann.

Ist die IP-Adresse nicht in der Liste enthalten wird der Zugriff verweigert und die Meldung „Blocked 1“ ausgegeben, anderenfalls läuft das Script wie geplant weiter. In diesem Beispiel wird dann „Hello World 1“ ausgegeben.

// PHPWAF START - WHITELIST EXAMPLE
$waf = array(
    '127.0.0.1',
    '1.1.1.1',);
$rip = isset($_SERVER['REMOTE_ADDR']) ? trim($_SERVER['REMOTE_ADDR']) : '';
echo $rip; //echo the IP for testing
if ((($key = array_search($rip, $waf)) == false)) {
    echo 'Blocked 1';
    exit();
}

echo 'Hello World 1';
// PHPWAF END - WHITELIST EXAMPLE

PHP Blacklist

Im nächsten Beispiel drehen wir das Verfahren um und die IPs im Array $waf werden zu einer Blacklist. Das kann jedoch fehleranfällig sein – wenn z. B. Cloudflare genutzt wird – weshalb wir zusätzlich zur normal ermittelten IP-Adresse nach den Werden „CF_CONNECTING_IP“ und „X_FORWARDED_FOR“ fragen und mit unserer Blackliste abgleichen. Das erhöht die Trefferquote maßgeblich.

// PHPWAF START - BLACKLIST EXAMPLE
$waf = array(
    '0.0.0.0',
    '1.1.1.1',
  
);
$rip = ''; $cip = ''; $xip = '';
$rip = isset($_SERVER['REMOTE_ADDR']) ? trim($_SERVER['REMOTE_ADDR']) : '';
$cip = isset($_SERVER['HTTP_CF_CONNECTING_IP']) ? trim($_SERVER['HTTP_CF_CONNECTING_IP']) : ''; //rec: dont use for whitelist
$xip = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? trim($_SERVER['HTTP_X_FORWARDED_FOR']) : ''; //rec: dont use for whitelist
// echo $rip.$cip.$xip; //echo the IPs for testing
if ((($key = array_search($rip, $waf)) == true) || (($key = array_search($cip, $waf)) == true) || (($key = array_search($xip, $waf)) == true)) {
    echo 'Blocked 2';
    exit();
}

echo 'Hello World 2';
// PHPWAF END - BLACKLIST EXAMPLE

PHP Blacklist mit einer Blockliste

Dieses Beispiel folgt dem obigen Beispiel einer Blacklist. Es wird jedoch kein Array für die Blackliste genutzt, sondern eine Textdatei mit dem Namen „blacklist.txt“. Die IP-Adressen können dort Zeile für Zeile eingetragen werden.

// PHPWAF START - BLACKLIST EXAMPLE WITH FILE
$waf = file('blacklist.txt', FILE_IGNORE_NEW_LINES);
$rip = ''; $cip = ''; $xip = '';
$rip = isset($_SERVER['REMOTE_ADDR']) ? trim($_SERVER['REMOTE_ADDR']) : '';
$cip = isset($_SERVER['HTTP_CF_CONNECTING_IP']) ? trim($_SERVER['HTTP_CF_CONNECTING_IP']) : ''; //rec: dont use for whitelist
$xip = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? trim($_SERVER['HTTP_X_FORWARDED_FOR']) : ''; //rec: dont use for whitelist
// echo $rip.$cip.$xip; //echo the IPs for testing
if ((($key = array_search($rip, $waf)) == true) || (($key = array_search($cip, $waf)) == true) || (($key = array_search($xip, $waf)) == true)) {
    echo 'Blocked 3';
    exit();
}

echo 'Hello World 3';
// PHPWAF END - BLACKLIST EXAMPLE WITH FILE

mini-WAF mit PHP

Das ist lediglich ein Beispiel einer extrem vereinfachten Version einer WAF. In diesem Beispiel werden alle Werte – welche per POST oder GET an das PHP-Script übergeben werden – nach bestimmten Strings durchsucht um z. B. Cross-Site-Scripting und einfache SQL-Injections zu unterbinden. Natürlich ist das keinesfalls ausreichend oder vollständig.

//PHPWAF - INPUT CHECKS START

$postdata = file_get_contents("php://input");
if($postdata) {
if ((strstr($postdata, 'exec '))||(strstr($postdata, 'SELECT *'))||(strstr($postdata, 'select *'))||(strstr($postdata, 'UNION SELECT'))||(strstr($postdata, 'union select'))||(strstr($postdata, 'EXEC '))||(strstr($postdata, '<script>'))||(strstr($postdata, '<SCRIPT>'))||(strstr($postdata, '<?php'))||(strstr($postdata, '<?'))||(strstr($postdata, '?>'))||(strstr($postdata, 'UNION DELETE'))||(strstr($postdata, 'union delete'))||(strstr($postdata, 'UNION UPDATE'))||(strstr($postdata, 'union update'))||(strstr($postdata, 'UNION TRUNCATE'))||(strstr($postdata, 'union truncate'))) { //str_contains for php8
    echo "blocked 4";
	exit;
}
}
$postdata = $_GET;
$postdata = implode(" ", $postdata);

if($postdata) {
if ((strstr($postdata, 'exec '))||(strstr($postdata, 'SELECT *'))||(strstr($postdata, 'select *'))||(strstr($postdata, 'UNION SELECT'))||(strstr($postdata, 'union select'))||(strstr($postdata, 'EXEC '))||(strstr($postdata, '<script>'))||(strstr($postdata, '<SCRIPT>'))||(strstr($postdata, '<?php'))||(strstr($postdata, '<?'))||(strstr($postdata, '?>'))||(strstr($postdata, 'UNION DELETE'))||(strstr($postdata, 'union delete'))||(strstr($postdata, 'UNION UPDATE'))||(strstr($postdata, 'union update'))||(strstr($postdata, 'UNION TRUNCATE'))||(strstr($postdata, 'union truncate'))) { //str_contains for php8
    echo "blocked 4";
	exit;
}
}
echo 'Hello World 4';
echo file_get_contents("php://input");

//PHPWAF - INPUT CHECKS END

Schreibe einen Kommentar

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