Скрипт защиты от хакеров на PHP и .htaccess

В интернете хакеры постоянно сканируют сайты на уязвимости. При этом обычно идет перебор по словарю уязвимостей с помощью атаки brute force.

Если Ваш сайт написан на известном движке, типа Wordpress, то для него ежедневно находят все новые и новые дыры. Данный скрипт проверяет известные ему атаки и полностью блокирует доступ с данного IP адреса к сайту с помощью записи в Deny from xxx.xxx.xxx.xxx в .htaccess, чтобы даже если появилась новая уязвимость, то хакер не сможет ее проверить и получить несанкционированный доступ.

Данный скрипт будет работать на любом хостинге, включая виртуальный и доменный, без root-прав. Вам необходимо поместить данный скрипт в файл, например banit.php и вставить вызов данного скрипта в начало всех ваших скриптов. Чаще всего достаточно вставить вызов в начало вашего корневого index.php с помощью команды:

include_once $_SERVER['DOCUMENT_ROOT'].'/banit.php';

Для исключения разрастания файла .htaccess, рекомендуется периодически вызывать скрипт с параметром ?cron для очистки старых блокировок. Оптимально вызывать по сron раз в неделю.

Скачать скрипт

Код скрипта:

<?
// Скрипт скачан: https://htmlweb.ru/php/example/banit.php
// Автор: Колесников Дмитрий Геннадьевич
// Вы можете использовать данный скрипт без ограничений на любых своих сайтах.
// При публикации сохраняйте активную ссылку на первоисточник.
// Периодически буду обновлять правила блокировки, поэтому заходите сюда за обновленной версией скрипта.
// Обновлено 11.11.2022
if(!empty($_SERVER['REQUEST_URI'])){
    if(isset($_REQUEST['cron'])){
        $v=$_SERVER['DOCUMENT_ROOT'].'/.htaccess';
        $buf=file_get_contents($v);
        preg_match_all("/\n#(\d{2}.\d{2}.\d{2}) [^\n]+\nDeny from \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}/", $buf,$ar,PREG_SET_ORDER);
        if(!empty($ar)) {
            $f_save = 0;
            echo "Всего заблокировано IP адресов: ".count($ar);
            //echo strtotime('-1 day')."\n";
            foreach ($ar as $s) {
                $s[1]=substr_replace($s[1], '20', 6, 0);
                //echo $s[0]." ~ ".$s[1]." ~ ".strtotime($s[1])." ~ ".date('d.m.Y',strtotime($s[1]))."\n";
                if (strtotime($s[1]) < strtotime('-30 day')) {
                    $buf = str_replace($s[0], '', $buf);
                    $f_save++;
                }
            }
            if ($f_save>0) {
                if(!is_file($v . '~')||filemtime($v . '~')<strtotime('-1 day')) {
                    if (is_file($v . '~')) unlink($v . '~');
                    copy($v, $v . '~');
                }
                file_put_contents($v, $buf);
                echo "Разблокировал ".$f_save;
            }
        }
        die;
    }
    while(substr($_SERVER['REQUEST_URI'],0,2)=='//')$_SERVER['REQUEST_URI']=substr($_SERVER['REQUEST_URI'],1);
    foreach(['/xmlrpc.php','/wp-login.php','/plus/recommend.php','/wp-admin','/wp-content','/wp-includes','/phpmyadmin','/.well-known/',
        '/usr/share/phpmyadmin','/wp-cc.php','/admin.php', '/zb_system/login.php','/user.php'/*?act=login*/,'/cgi-bin','/dropdown.php',
        '/wp/wp-includes/wlwmanifest.xml','/wordpress/wp-includes/wlwmanifest.xml','/blog/wp-includes/wlwmanifest.xml',
        '/cms/wp-includes/wlwmanifest.xml','/site/wp-includes/wlwmanifest.xml','/system_api.php','/nf_tracking.php','/wp-cron.php'] as $s)
        if(mb_strlen($_SERVER['REQUEST_URI'])>=mb_strlen($s) && mb_substr($_SERVER['REQUEST_URI'],0,mb_strlen($s))==$s) __BanIt('Hacker WP');;

    if ( strpos($_SERVER['REQUEST_URI'], "/wp-includes/wlwmanifest.xml") !== false) __BanIt('Hacker WP');;

    if ( strpos($_SERVER['REQUEST_URI'], ".php/component/users/") !== false) __BanIt('component'); // /index.php/component/users/?view=registration

    if ( strpos($_SERVER['REQUEST_URI'], "DOCUMENT_ROOT") !== false) __BanIt('DOCUMENT_ROOT'); // ?_SERVER[DOCUMENT_ROOT]=http://www.aerothaiunion.com/sik.txt?.

    if ( strpos($_SERVER['REQUEST_URI'], "'A=0") !== false) __BanIt('A=0');   // /price/?brand=641'A=0,

}
if(isset($_SERVER['HTTP_REFERER'])){
    if(strpos($_SERVER['HTTP_REFERER'], '\"')!==false || strpos($_SERVER['HTTP_REFERER'], '\'')!==false)__BanIt('апостроф в HTTP_REFERER');
}
if(!empty($_SERVER['QUERY_STRING'])){
    $s=urldecode($_SERVER['QUERY_STRING']);
    foreach (["mosConfig_","_REQUEST","GLOBALS","<iframe","<script","base64_encode","allow_url_include","auto_prepend_file","r57shell","tool25","cmd.txt","cmd.gif"] as $v)if(strpos($s, $v) !== false)__BanIt('QUERY_STRING');
    if(!empty($_GET['op'])&&$_GET['op']=='checkcode')__BanIt('QUERY_STRING'); // /api.php?op=checkcode&code_len=4&font_size=20&width=130&height=50&font_color=&background= HTTP/1.0" 403 410
}
if ($_COOKIE){
    if (!empty($_COOKIE['PHPSESSID'])){
        if (strpos($_COOKIE['PHPSESSID'], 'disclaimer_accepted') !== false || $_COOKIE['PHPSESSID'] == '-1\'' || strpos($_COOKIE['PHPSESSID'], 'username=') !== false ){
            __BanIt('Hacker Cookie');
        }
    }
    foreach ($_COOKIE as $key => $val) {
        if (strpos($key, 'wordpress') === 0 || strpos($key, 'phpbb') === 0 || $key == 'PHPSESSID' && $val == 'deleted' ||
        substr($key,0,10)=='BITRIX_SM_' || in_array($key, ['is_first_access','CMSRabbitAdminLangRUN','RabbitCookie'])){
            __BanIt('Hacker Cookie');
        }
    }
}
if (isset($_REQUEST['clientaction']) || isset($_REQUEST['"']) || isset($_REQUEST['1\'']) || isset($_REQUEST['\''])){
    __BanIt('REQUEST_KEY');
}

function __BanIt($msg) // если передан ip0, сообщение не выдается
{
    $ips=[];
    if (!empty($_SERVER['REMOTE_ADDR'])) $ips[]=$_SERVER['REMOTE_ADDR'];
    $ip2 = getenv('REMOTE_ADDR');
    if (!empty($ip2) && $ip2 != "0.0.0.0" && !in_array($ip2, $ips)) $ips[]=$ip2;
    $ip2 = getenv('HTTP_X_FORWARDED_FOR'); // используется не анонимными прокси-серверами для передачи реального IP клиента X-Forwarded-For: client_ip, proxy1_ip, ..., proxyN_ip
    if (!empty($ip2) && $ip2 != "0.0.0.0" && !in_array($ip2, $ips)) $ips[]=$ip2;
    $ip2 = getenv('HTTP_FORWARDED_FOR');
    if (!empty($ip2) && $ip2 != "0.0.0.0" && !in_array($ip2, $ips)) $ips[]=$ip2;
    $ip2 = getenv('HTTP_FORWARDED'); // Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43
    if (!empty($ip2) && $ip2 != "0.0.0.0" && !in_array($ip2, $ips)) $ips[]=$ip2;
    $ip2 = getenv('HTTP_X_COMING_FROM');
    if (!empty($ip2) && $ip2 != "0.0.0.0" && !in_array($ip2, $ips)) $ips[]=$ip2;
    $ip2 = getenv('HTTP_VIA'); // если не пустая, значит используется proxy. Значение - адрес (или несколько адресов) proxy сервера.
    if (!empty($ip2) && $ip2 != "0.0.0.0" && !in_array($ip2, $ips)) $ips[]=$ip2;
    $ip2 = getenv('HTTP_XROXY_CONNECTION');
    if (!empty($ip2) && $ip2 != "0.0.0.0" && !in_array($ip2, $ips)) $ips[]=$ip2;
    $ip2 = getenv('HTTP_XROXY_CONNECTION');
    if (!empty($ip2) && $ip2 != "0.0.0.0" && !in_array($ip2, $ips)) $ips[]=$ip2;
    $ip2 = getenv('HTTP_CLIENT_IP');
    if (!empty($ip2) && $ip2 != "0.0.0.0" && !in_array($ip2, $ips)) $ips[]=$ip2;
    if (!empty($_SERVER['HTTP_X_REAL_IP'])){
        $ip2 = $_SERVER['HTTP_X_REAL_IP'];
        if ($ip2 != "0.0.0.0" && !in_array($ip2, $ips)) $ips[]=$ip2;
    }
    if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])){ //https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-
        $ip2 = $_SERVER['HTTP_CF_CONNECTING_IP'];
        if ($ip2 != "0.0.0.0" && !in_array($ip2, $ips)) $ips[]=$ip2;
    }
    foreach ($ips as $ip)if(preg_match("/\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}/", $ip)){
        file_put_contents($_SERVER['DOCUMENT_ROOT'].'/.htaccess', "\n#".date('d.m.y').' '.$msg."\nDeny from ".$ip, FILE_APPEND|LOCK_EX);
    }
    header("HTTP/1.0 403 Ban you");
    die('Ban you');
}

.