Jump to content
Sign in to follow this  
artnazarov

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

Recommended Posts

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

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

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

 

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

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

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

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

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

 

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

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

 

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

 

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

 

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

 

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

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

<?php
// АРТЁМ
// admin@artnazarov.ru, подойдет для любых 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), пожалуйста напишите об этом в этой теме или отправьте мне свои соображения на почту admin@artnazarov.ru.

 

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

 

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

 

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

Share this post


Link to post
Share on other sites

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

 

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

Share this post


Link to post
Share on other sites

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

 

  //  check specials chars and delimeters

 

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

 

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

 

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

 

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

Share this post


Link to post
Share on other sites

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

 

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

 

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

Share this post


Link to post
Share on other sites

этож просто GENERAL PROTECTION LAYER не судите его строго. Не генеральское это дело вникать в специфику.

Share this post


Link to post
Share on other sites

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

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

 

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

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

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

 

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

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

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

 

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

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

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

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

 

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

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

 

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

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

 

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

Share this post


Link to post
Share on other sites

этож просто GENERAL PROTECTION LAYER не судите его строго. Не генеральское это дело вникать в специфику.

 

Не вникай.

Share this post


Link to post
Share on other sites

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

 

  //  check specials chars and delimeters

 

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

 

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

 

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

 

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

 

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

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

Share this post


Link to post
Share on other sites

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

 

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

 

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

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

Share this post


Link to post
Share on other sites

 

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

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

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

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

 

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

 

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

Share this post


Link to post
Share on other sites

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

 

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

 

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

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

Share this post


Link to post
Share on other sites

suhosin, не?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
You are posting as a guest. If you have an account, please sign in.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×

Important Information

On our site, cookies are used and personal data is processed to improve the user interface. To find out what and what personal data we are processing, please go to the link. If you click "I agree," it means that you understand and accept all the conditions specified in this Privacy Notice.