Перейти до вмісту
Пошук в
  • Детальніше...
Шукати результати, які ...
Шукати результати в ...

Слой защиты общего назначения для OpenCart


artnazarov

Recommended Posts

Взлом сайта начинается с внедрения в запросы вредоносных управляющих строк, позволяющих в зависимости от цели атакующего реализовать такие сценарии как установка паразитного управляющего модуля (шелл), уничтожение базы данных, получение доступа к конфиденциальным сведениям, скрытое размещение рекламы, отрицательно влияющее на позиции в поисковике, получение доступов к серверу и т.п.

Не секрет, что для осуществления этих атак все чаще используется специальный софт, позволяющий просканировать сайт на уязвимости и даже выполнить их эксплуатацию по заранее подготовленным сценариям. Все чаще атаки на коммерческие сайты приобретают массовый характер и затрагивают тысячи ресурсов по всему миру. 

К сожалению, не все уязвимости обнаруживаются и закрываются основной командой в самом динамично развивающемся движке, не говоря уже о модулях, подготовленных участниками коммьюнити.

 

Следовательно, для защиты интернет-магазинов на OpenCart необходимо разбирать фрагменты запросов от пользователей еще до того, как они попадут в любые компоненты системы, поскольку человеческий фактор в безопасности - один из решающих.

Советы: Для защиты сайта можно прикрыть сервер с помощью сервисов вроде CLOUDFLARE, QRATOR, VIRUSDIE и т.п Выполняйте сканирование файловой системы сайта с помощью бесплатного антивируса Манул, других скриптов и утилит, имеющих возможности отслеживать появление новых неизвестных файлов и изменения в файлах существующих.

Это позволит вовремя заметить факт взлома.

Но что делать, если в Вашем бюджете пока не предусмотрен Qrator, VirusDie или Cloudflare? Что делать, если у Вас нет ресурсов устраивать тщательный аудит кода на безопасность для каждого из модулей, которые Вы устанавливаете?  Утилиты вроде Acunetix имеют дорогие лицензии, а ими надо еще научиться пользоваться.

А безопасностью заниматься в наше непростое время надо как никогда.

 

Подобно тому, как операционные системы имеют несколько колец или слоев защиты, так и OpenCart нуждается в создании такого слоя, хотя бы в минимальном объеме  защищающем от исполнения XSS и SQL инъекций. Эффективность разработки такого слоя может быть достигнута только при предположении, что движок и модули имеют незакрытые уязвимости.

Этот слой должен быть размещен между ядром системы и контроллерами и запросами.

 

Таким образом, идея состоит в том, что нельзя доверять ни сайту (может быть заражен или уязвим), ни запросам (могут быть вредоносными). Нельзя доверять разработчикам модулей, поскольку они концентрируют свои усилия на выполнении определенных задач и могут просто не заметить проблем с безопасностью своего кода.

 

Сам же слой должен быть настолько прост и лаконичен, насколько это вообще возможно, чтобы  его собственная безвредность, соответствие требованиям и безопасность была очевидна. Он не должен опираться на остальные инструменты CMS и быть переносимым между разными CMS - CMS меняются, а безопасность остается.

 

Как мог бы выглядеть подобный слой:

 

Практический пример:

Сохраняем в корне сайта файл protection.php.

<?php
// АРТЁМ
// [email protected], подойдет для любых CMS на PHP
define('PROTECTION', true);
// change this setting to your one
define('MAIN_PAGE_URL', '/');

function request_handle($filter)
{
$rq = $_SERVER['REQUEST_URI'];
if (true == isset($_SESSION['hits']))
{
$_SESSION['hits'] = $_SESSION['hits'] + 1;
$mt = microtime(true);
$lasthit = ($mt-$_SESSION['lasthit']);
$_SESSION['lasthit'] = $mt;
$hits = $_SESSION['hits'];
}
else
{
$_SESSION['hits'] = 1;    
$hits = 1;
$_SESSION['lasthit'] = microtime(true);
$lasthit = 999;
};
$lasthit = $lasthit*1000;
$timeout = 15;
if ($filter)
{
    

if (($lasthit<=750) && ($rq!=MAIN_PAGE_URL))
        {            
            echo "<html><head>
            <meta http-equiv='refresh' content='$timeout;$rq'>
            <title>Система защиты</title><meta charset='utf-8'><body>
    <b>Система защиты.</b> 
    <p>Между повторными запросами прошло менее $lasthit мс! Вы будете автоматически перенаправлены на запрошенную страницу
    через $timeout сек.</p>    
    </body></html>";
            exit;
            die();

            };
            
};            
return $hits;        
}

function statinfo($hits)
{    
$v_ip = $_SERVER['REMOTE_ADDR'];
$ag = $_SERVER['HTTP_USER_AGENT'];
$ru = $_SERVER['REQUEST_URI'];
$v_date = date("l d F H:i:s"); 
$fp = fopen("./logs/ips.log", "a+");
fputs($fp, "IP:$v_ip;REQUEST:$ru;DATE:$v_date;USERAGENT:$ag;HITS:$hits#\n\r\n\r");
fclose($fp);
}

/* GENERAL PROTECTION LAYER */

function dang_symb($str)
{
 $test = false;
  // check fragments of php/js code  
 if (strpos($str, "base64")!==false) {$test = true;};
 if (strpos($str, 'eval')!==false) {$test = true;};
 if (strpos($str, 'write')!==false) {$test = true;};
  //  check specials chars and delimeters
 if (strpos($str, "\\")!==false) {$test = true;};
 if (strpos($str, '0x')!==false) {$test = true;};
 if (strpos($str, '/*')!==false) {$test = true;};
 if (strpos($str, '*/')!==false) {$test = true;};
 if (strpos($str, '|')!==false) {$test = true;};
 if (strpos($str, '&&')!==false) {$test = true;};
 if (strpos($str, '--')!==false) {$test = true;};
 if (strpos($str, ':;')!==false) {$test = true;};
 if (strpos($str, ';')!==false) {$test = true;};
 if (strpos($str, '*')!==false) {$test = true;};
 if (strpos($str, ':=')!==false) {$test = true;}; 
 if (strpos($str, '(')!==false) {$test = true;}; 
 if (strpos($str, ')')!==false) {$test = true;}; 
 if (strpos($str, "'")!==false) {$test = true;}; 
 if (strpos($str, ",")!==false) {$test = true;}; 
 if (strpos($str, "#")!==false) {$test = true;}; 
 if (strpos($str, "$")!==false) {$test = true;}; 
 if (strpos($str, "|")!==false) {$test = true;}; 
 if (strpos($str, "<")!==false) {$test = true;}; 
 if (strpos($str, ">")!==false) {$test = true;}; 
 if (strpos($str, "[")!==false) {$test = true;}; 
 if (strpos($str, "]")!==false) {$test = true;}; 
 if (strpos($str, "~")!==false) {$test = true;}; 
 if (strpos($str, "`")!==false) {$test = true;}; 
   // detect calls to OS tools
   // for WIN
 if (strpos($str, "..")!==false) {$test = true;}; 
 if (strpos($str, "/etc/passwd")!==false) {$test = true;}; 
 if (strpos($str, "c:\\")!==false) {$test = true;}; 
 if (strpos($str, "cmd.exe")!==false) {$test = true;}; 
 if (strpos($str, "\\")!==false) {$test = true;}; 
 if (strpos($str, "//")!==false) {$test = true;}; 
 if (strpos($str, "`")!==false) {$test = true;}; 
   // for NIX   
 if (strpos($str, "yum")!==false) {$test = true;}; 
 if (strpos($str, "apt")!==false) {$test = true;}; 
 if (strpos($str, "sudo")!==false) {$test = true;}; 
 if (strpos($str, "rm")!==false) {$test = true;}; 
    // check that no one parts of request have a SQL operators
  if (strpos(strtoupper($str), 'UNION')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'SELECT')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'DROP')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'GROUP')!==false) {$test=true;};  
  if (strpos(strtoupper($str), 'WHERE')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'UPDATE')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'COUNT')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'HAVING')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'SCRIPT')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'DELETE')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'OR ')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'AND ')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'IN ')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'SCRIPT')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'INSERT')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'INTO ')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'VALUES')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'TABLE')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'GRANT')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'ROLLBACK')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'COMMIT')!==false) {$test=true;};
  if (strpos(strtoupper($str), 'CREATE')!==false) {$test=true;};
  
 return $test;
 }
 
function dang_in_arr($arr)
{
 $test_g = false;
 foreach ($arr as $k => $v)
 {
	if (dang_symb($v)===true) {$test_g = true;};
 };
 return $test_g;
}

function test_get()
{
 return dang_in_arr($_GET);
}

function test_post()
{
 return dang_in_arr($_POST);
}
       
function test_session()
{
 return dang_in_arr($_SESSION);
}
       
function test_server()
{
 return dang_in_arr($_SERVER);
}
       
 function test_cookie()
{
 return dang_in_arr($_COOKIE);
}



function test_both()
{
	return (test_get() || test_post() || test_server() || test_session() || test_cookie() );
}

function die_on_dang()
{
	if (test_both()===true) die('Malware symbols detected');
  // here may be code to ban this IP on some time
}

function general_protection($filter = true)
{
  if (PROTECTION)
  {
  // dont process hits with high frequency 
  $hits = request_handle($filter);
  statinfo($hits); // log to journal
  if ($filter)
  {
    die_on_dang(); // stop any activity on danger
  };
  };
}

?>

 

в файлах /index.php и /admin/index.php перед всеми инструкциями ставим первыми вызов защитной прослойки

require_once($_SERVER['DOCUMENT_ROOT'] . '/protection.php');
general_protection();

 

Результат: теперь попытки отправить нам на сайт в запросе прелести вроде eval, script или drop database и т.п. будут пресекаться на корню. Он универсален и подойдет для любой CMS.

 

Код опубликован "как есть", без каких-либо гарантий с моей стороны. 

Буду рад конструктивным предложениям по улучшению этого фильтра.

 

Если у Вас есть наработки и идеи по такого рода защите, если Вам что-либо известно об аналогичных модулях (возможно, в рамках других CMS), пожалуйста напишите об этом в этой теме или отправьте мне свои соображения на почту [email protected].

 

Уверен, что всем в той или иной степени интересна тема повышения безопасности OpenCart.

 

Пишу здесь, поскольку не уверен, что кто-либо из core/kernel team будет это когда-либо имплементировать, рефакторить или развивать, с учетом своеобразного характера персонажей вроде Daniel Kerr

 

Желаю всем растущих продаж, отличной конверсии и 100% аптайма :-)

Надіслати
Поділитися на інших сайтах


Подписался :) Чую рождается новый мем.

 

ЗЫ: А ежели аффтор через год другой узнает о существовании регулярных выражений...

Надіслати
Поділитися на інших сайтах

спорные рекомендации по поводу

 

  //  check specials chars and delimeters

 

 if (strpos($str, "..")!==false) {$test = true;}; - хм... прикольно - хотелось бы знать причину...  (что такое  ..  я знаю)

 

if (strpos($str, "`")!==false) {$test = true;}; - дважды

 

и... уже есть модуль для этого

 

И... есть более универсальный способ подключения такого файла,  который пропустит через себя все запросы, в том числе и к сторонним скриптам.

Надіслати
Поділитися на інших сайтах

Проверка на якобы SQL инъекцию бессмысленна

 

Я могу передавать текст, содержащий что-то из этого набора. кроме того, если заметите,  то select  insert update -  слова часто встречающиеся и в русскоязычных текстах,а  также может быть т в аякс запросах

 

У меня есть провайдер, который фильтрует  =1, ссылаясь на то что это общеизвестные фильтры, и отключать не хочет.

Надіслати
Поділитися на інших сайтах

"Проверка на SQL инъекцию бессмысленна".

Охранники в банке не нужны? Патрули в общественных местах?

 

1. А regex медленнее, чем strpos. 

2. Загнать в массив параметры было бы медленнее и прогнать в цикле тоже было бы медленно.

3. Возможные проблемы c REQUEST_URI и т.п. понятны, но разрешимы.
Однако, UPDATE в search запросах звучало бы странно :)

 

Рад, что к сообщению гуру, снизошедшие до простого смертного, относятся с юмором, пытаются

что-то осмысленное написать, медитируют над кодом, выискивая что-то, что позволило бы им почувствовать

себя крутышами.  Самовлюбленность меж тем противоречит общему делу.

 

Что ж, возможно, кто-то из гуру отважится аналог Manul для OpenCart написать.

Но что-то не наблюдаю что-то в магазине дополнений таких решений.

А они не одного меня, убогого, интересуют. Вы бы свой код показали.

Я ж не стесняюсь. Модули по безопасности пользовались бы большим спросом.

 

Все беды именно от уверенности в защищенности,  и в том, что всегда найдется крайний.

В мире бандерлогов-ревьюеров и розовых пони, блюющих радугой, все безоблачно )

 

Ведь есть Kerr со товарищи,  спасет quoting и т.п.  Поэтому и response и request считают безопасными,

под капотом же все все в порядке :) Ничего не произойдет. Ничего...

 

А дыры-то на текущих релизах должны быть в безопасности и не факт, что новых, не озвученных публично, не появится в новых версиях. Тех, о которых владельцы узнают только тогда, когда произойдет взлом. :)

Надіслати
Поділитися на інших сайтах


спорные рекомендации по поводу

 

  //  check specials chars and delimeters

 

 if (strpos($str, "..")!==false) {$test = true;}; - хм... прикольно - хотелось бы знать причину...  (что такое  ..  я знаю)

 

if (strpos($str, "`")!==false) {$test = true;}; - дважды

 

и... уже есть модуль для этого

 

И... есть более универсальный способ подключения такого файла,  который пропустит через себя все запросы, в том числе и к сторонним скриптам.

 

О каком модуле речь, о каком способе подключения вы говорите.

Был бы премного благодарен за ответ

Надіслати
Поділитися на інших сайтах


Подписался :) Чую рождается новый мем.

 

ЗЫ: А ежели аффтор через год другой узнает о существовании регулярных выражений...

 

Действительно, лучше всего это работает после применения патча Бармина. 

Попробуйте именно в таком порядке у себя на сервере.

Надіслати
Поділитися на інших сайтах


 

Рад, что к сообщению гуру, снизошедшие до простого смертного, относятся с юмором, пытаются

что-то осмысленное написать, медитируют над кодом, выискивая что-то, что позволило бы им почувствовать

себя крутышами.  Самовлюбленность меж тем противоречит общему делу.

Советую сбавить обороты в поисках всевдосатирических фраз.

 

Ни на один мой вопрос не отвечено.

 

И, я так понимаю, что вы не удосужились поиском модуля, а тем более способа подключения своих скриптов.

Надіслати
Поділитися на інших сайтах

Проверка на якобы SQL инъекцию бессмысленна

 

Я могу передавать текст, содержащий что-то из этого набора. кроме того, если заметите,  то select  insert update -  слова часто встречающиеся и в русскоязычных текстах,а  также может быть т в аякс запросах

 

У меня есть провайдер, который фильтрует  =1, ссылаясь на то что это общеизвестные фильтры, и отключать не хочет.

Полностью поддерживаю chukcha - за четыре года работы с opencart и более 500 ИМ,  ни разу не видел взлома через описанные в топике костыли, зато избыточных вычислений ...

Надіслати
Поділитися на інших сайтах

Створіть аккаунт або увійдіть для коментування

Ви повинні бути користувачем, щоб залишити коментар

Створити обліковий запис

Зареєструйтеся для отримання облікового запису. Це просто!

Зареєструвати аккаунт

Вхід

Уже зареєстровані? Увійдіть тут.

Вхід зараз
  • Зараз на сторінці   0 користувачів

    • Ні користувачів, які переглядиють цю сторінку
×
×
  • Створити...

Important Information

На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність.