Автогенерируемые аудиокапчи (баг в NetCat 5.2)

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

Эта история наверняка касается версии NetCat 5.2 всех редакций, а также модуля "Защита картинкой" и техподдержки NetCat :).
Также она может касаться соседних версий, но точно не 5.5, где этот баг исправлен.

Что случилось?

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

  • начиная с субботы, некий ботнет, состоящий преимущественно из взломанных сайтов низшего эшелона (порносайты, знакомства, "женские истории" и т.д.) начал неторопливо "прощупывать" один из наших сайтов на NetCat
  • предполагаю, что он искал SQL Injection Netcat 5.0, так как ломился на капчу
  • данная уязвимость на сайте закрыта, поэтому ботнет к успеху не пришел. Однако NetCat настолько... ммм... своеобразен, что начал реагировать на "прощупывания", инициализируя процесс генерации аудиокатч.
    • следует заметить, что опция (аудиокапчи) в админке вообще-то отключена, но об этом ниже
  • в результате аудиокапчи (то есть маленькие mp3-файлики со случайными комбинациями букв) постепенно генерились и генерились до тех пор, пока их не нагенерилось на 5 ГБ.
  • так как у нашего сайта на сервере не стояло квоты на использование дискового пространства, место на диске в итоге закончилось полностью
  • сервер завис и все сломалось.

Как я все пофиксил?

  • сначала я продиагностировал сервер и выяснил, что проблема в огромном множестве mp3-файлов в директории netcat_files/captcha/current_voice.
  • я зашел в админку и обнаружил что данный функционал модуля, вообще-то, выключен! В поле "использовать аудиокачу" стоит ноль!
  • я удалил все эти файлы, однако они немедленно начали появляться вновь, таким образом проблема не была решена;
  • затем я позвонил в NetCat и попробовал узнать, в курсе ли они такой проблемы. Дело в том, что я вроде уже сталкивался с чем-то похожим когда-то.
  • по телефону я не получил никакого ответа, кроме предложения писать тикет. Но это я предполагаю чем закончится: у вас кончилась лицензия, продлите лицензию, о, у вас старая версия, поставьте обновление, о, проблема решена и появилось две новые? пожалуйста, создайте два новых тикета. Я, конечно, утрирую, но ясно, что быстрого решения мне не добиться. Поэтому ковыряюсь сам дальше.
  • после анализа error.log выяснилось, что проблема как-то проявляется вот здесь:
[Mon Apr 06 14:55:00 2015] [error] [client 173.252.101.112] PHP Warning:  copy(/var/www/*/data/www/*/netcat_files/captcha/current_voice/33843462e319929356b2806dfc07e579.mp3) [<a href='function.copy'>function.copy</a>]: failed to open stream: \xd0\x9e\xd1\x82\xd0\xba\xd0\xb0\xd0\xb7\xd0\xb0\xd0\xbd\xd0\xbe \xd0\xb2 \xd0\xb4\xd0\xbe\xd1\x81\xd1\x82\xd1\x83\xd0\xbf\xd0\xb5 in /var/www/*/data/www/*/netcat/modules/captcha/function.inc.php on line 73
  • я посмотрел на код в районе 73-й строчки:
  1.  
  2.     // Обновление захешированных файлов для аудиокаптчи
  3.     $res = $nc_core->db->get_results("SELECT * FROM `Captchas_Settings`", ARRAY_A);
  4.     if (!empty($res))
  5.             foreach ($res as $v)
  6.             $captcha_settings[$v['Key']] = $v['Value'];
  7.  
  8.     if ($captcha_settings && is_writable($nc_core->FILES_FOLDER) && is_dir($nc_core->MODULE_FOLDER.'captcha/voice/'.$MODULE_VARS['captcha']['VOICE'].'/') && time() - 3600 >= strtotime($captcha_settings['time'])) {
  9.         $db->query("UPDATE `Captchas_Settings` SET `Value`= Now() WHERE `Key` = 'time'");
  10.         $from = $nc_core->MODULE_FOLDER.'captcha/voice/'.$MODULE_VARS['captcha']['VOICE'].'/';
  11.         $to = $nc_core->FILES_FOLDER.'captcha/current_voice/';
  12.         $nc_core->files->create_dir($to);
  13.  
  14.         $enc_mp3_files[] = '';
  15.         $enc_mp3_folder = opendir($to);
  16.         while ($one = readdir($enc_mp3_folder)) {
  17.             if ($one != '.' && $one != '..' && substr(strrchr($one, '.'), 1) == 'mp3') {
  18.                 $enc_mp3_files[] = $one;
  19.             }
  20.         }
  21.  
  22.         $normal_mp3_folder = opendir($from);
  23.         while ($one = readdir($normal_mp3_folder)) {
  24.             $file_hash = nc_captcha_generate_hash();
  25.             if ($one != '.' && $one != '..' && substr(strrchr($one, '.'), 1) == 'mp3') {
  26.                 if ($captcha_settings['current_voice'] != $MODULE_VARS['captcha']['VOICE'] || !in_array($captcha_settings[$one], $enc_mp3_files)) {
  27.                     $db->query("UPDATE `Captchas_Settings` SET `Value`= '".$MODULE_VARS['captcha']['VOICE']."' WHERE `Key` = 'current_voice'");
  28.                     if ($captcha_settings['current_voice'] != $MODULE_VARS['captcha']['VOICE']) {
  29.                         unlink($to.$captcha_settings[$one]);
  30.                     }
  31.                     copy($from.$one, $to.$file_hash.'.mp3');
  32.                     $db->query("UPDATE `Captchas_Settings` SET `Value`='".$db->escape($file_hash).".mp3' WHERE `Key` ='".$one."'");
  33.                 } else {
  34.                     rename($to.$captcha_settings[$one], $to.$file_hash.'.mp3');
  35.                     $db->query("UPDATE `Captchas_Settings` SET `Value`='".$db->escape($file_hash).".mp3' WHERE `Key` ='".$one."'");
  36.                 }
  37.             }
  38.         }
  39.     }
  • я внимательно посмотрел на этот код. Еще внимательнее... Еще внимательнее... И понял, что в нем нет проверки включенности аудиокапчи.
  • взял дистрибутив версии 5.5 и посмотрел аналогичное место. Эврика! В нем код слегка переписан, и как раз появилась недостающая проверка настроек модуля, значит здесь действительно ошибка, и ее уже исправили.

Так как мне не хотелось обновляться (ибо это чревато новыми багами и проблемами) и уж тем более править код самому, в итоге я еще раз проанализировал код и... просто назначил полю VOICE несуществующее значение. Получилось вот так:

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

Блог

Tilda Module: интеграция NetCat с Tilda.cc

Представляем нашу новую разработку, модуль интеграции CMS NetCat с платформой Tilda.cc. Модуль дает возможностью полуавтоматически размещать классные лендинги прямо в структуре вашего сайта!

далее

Как оптимально заархивировать файлы, чтобы распаковать их средствами ISPmanager?

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

далее

Как расшифровать бэкапы, зашифрованные ISPmanager?

В ISPmanager версии 5.52.0 и старше, реализована новая система резервного копирования, построенная на основе некоей ISPtar. И работает она... своеобразно. Попробуем разобраться, как именно.

далее

Типовой сайт по раскрытию информации по Приказу ФСФР 22.06.2005 № 05-23/пз-н

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

далее

Весь блог тут