Техника Port knoсking уже достаточно известна и распространена, с каждым годом обрастая всё новыми модификациями и сферами применения. Сегодня мы рассмотрим основы её устройства, а также многочисленные реализации
Любые стандартные защитные средства от неправомерного доступа, будучи всегда на виду, хорошо изучены и всем известны, неизбежно и регулярно будут испытываться на прочность и совершенство конкретной реализации. Поэтому в вопросах безопасности особенно важных и критичных сетевых ресурсов, в последнее время ставка делается на различные нестандартные и скрытые формы аутентификации или получения целевого доступа. Для маскировки такого рода механизмов эффективней всего выбирать максимально рядовые и характерные события, типичные для сетевой среды, которые неявно могут нести функцию сообщения/аутентификации, при этом, никак не привлекая к себе внимания потенциальных злоумышленников.
Переходя к делам сетевым, в качестве такого секретного триггера или сигнала уместно выбрать сам TCP/IP поток, выделяя какую-то его специфику и используя её для своих скрытых нужд. В этом и заключается суть метода PK, который имеет огромное количество реализаций и применений. Но перед началом нашего практического экскурса попробуем сформулировать и дать определение технике «секретного простукивания» портов.
Port knocking — это неявная форма разрешения доступа к некоему сервису, при условии прохождения предварительно заданной последовательности соединений с различными портами целевого сервера.
Специальное ПО на стороне сервера отслеживает все входящие соединения, и если фиксируется характерная «цепочка подключений» соответствующих ранее заданному «эталонному стуку» — временно открывает доступ к закрытому порту (и, соответственно, скрытому сервису на нем).
В более общем случае, технология PK позволяет удаленно и скрытно выполнять команды на защищенном сервере, даже если все порты на нем постоянно закрыты.
Что касается разнообразия подходов по реализации PK, то условно их все можно выделить в две группы. С одной стороны, это простейшие «самопальные скрипты» следящие за лог-файлом брандмауэра (или, например СУБД MySQL), которые обнаружив там заданные закономерности «стуков извне» — добавляют в него новые правила (или исполняющие условленные системные команды).
Похожий подход иногда реализуется через сочетание работы стандартных tcpdump и sendip, существуют также и другие вариации на вечную сисадминскую тему «сделано на коленке».
Эта статья посвящена подробному рассмотрению доступного арсенала из второй крупной группы в зоопарке решений для PK —специализированных приложений, которые гораздо более универсальны и часто технически безупречны.
Так уж повелось, что Port knocking чаще всего применяют для скрытия сервисов удаленного доступа на компьютер, например для SSH. Чтобы защитится от «плохих парней» некоторые перевешивают SSH на другой, нестандартный порт. Многие сидя за наглухо закрытым брандмауэром «проковыривают в нем дырочки» для доступа только из тех подсетей, откуда работают сами. В первом случае это решение слабо защищает от современных атак, в последнем — лишает мобильности.
Настройка knockd
чрезвычайно проста, и эта одна из причин его популярности. Вся система делится на серверную часть, которая будет слушать поступающие сигналы «из центра», и поставляемую в комплекте клиентскую часть, которая позволит «сыграть на серверных портах» нужную «мелодию» из сетевых пакетов в момент, когда вам понадобится закрытый со стороны сервера доступ.
Итак, собираем и устанавливаем knockd (я описываю вариант для FreeBSD, но также доступны пакеты и для разных версий Linux).
$ cd /usr/ports/security/knock $ make install clean
Перед настройкой демона knockd
поясню — он выполняет любые ранее заданные команды на стороне сервера в случае обнаружения управляющей последовательности. Какая же функциональность будет вложена в эти заданные триггеры — дело исключительно вашей необходимости и фантазии. Для демонстрации я выбрал защиту доступа к SSH.
Приведу пример настройки главного конфигурационного файла knockd.conf
:
# Глобальная секция настроек [options] # Путь к лог файлу logfile = /var/log/knockd.log # Какой сетевой интерфейс будет прослушивать knockd? interface = eth1 [ssh_open] sequence = 1291:udp, 3614:udp, 1492:tcp, 1090:udp seq_timeout = 20 tcpflags = syn,ack,!urg start_command = /usr/sbin/iptables -A INPUT -s %IP% -p tcp —syn —dport 22 -j ACCEPT [ssh_close] sequence = 1217:udp, 3114:udp, 1099:udp, 1292:tcp seq_timeout = 20 tcpflags = syn,ack,urg command = /usr/sbin/iptables -D INPUT -s %IP% —dport 22 -j ACCEPT
Здесь в общем блоке [options]
задаем общие значения, и далее перечисляем блоки-условия, параметры в которых будет контролировать демон (у нас таких только два, это ssh_open
и ssh_close
). В них через ключевое слово sequence мы последовательно указываем порты и протоколы, которые будут прослушиваться, а в seq_timeout
— максимальное время в секундах, отведенное нами на проигрыш полной «цепочки из портов».
Здесь протоколы можно не указывать явно, тогда по умолчанию будет подразумеваться TCP. Следующий параметр tcpflags
указывает TCP-пакеты с какими взведенными флагами будут учитываться в качестве TCP-стуков (если таковой протокол вообще используется в sequence
). Кроме простого перечисления возможно также и явное исключение некоторых флагов в качестве «сигнальных» (через префикс «!»).
В случае выполнения всех условий описанных в блоке запускается его целевая команда (оператор command
), в нашем случае — это открытие и закрытие порта для брандмауэра. Но ручное закрытие соединения вовсе не обязательно, предусмотрено несколько вариантов для его автозакрытия. Приведем подобный пример с аналогичной функциональностью, где количество выполняемых команд в блоке ssh_open
расширено с 1 до 3 (а ssh_close
отпадает за ненужностью):
start_command = /usr/sbin/iptables -A INPUT -s %IP% -p tcp —dport 22 —syn -j ACCEPT cmd_timeout = 20 stop_command = /usr/sbin/iptables -D INPUT -s %IP% -p tcp —dport 22 —syn -j ACCEPT
Это значит, что сначала открыв порт для доступа, мы ждем в течение 20 секунд входящих на него подключений, после чего закрываем его. Мы исходим из того, что пакетный фильтр сохраняет уже установленные соединения, поэтому блокировка порта не прервет уже запущенную SSH-сессию, — теперь нам не нужно помнить о необходимости «уходя закрывать за собой двери».
Внимательный читатель, вероятно, заметил, что в первом примере для команды использован единственный оператор command
, тогда как во втором я использую тернарную конструкцию start_command
и stop_command
, с разделяющей их cmd_timeout
(задающей временной шаг срабатывания между ними). Смысл всех этих трех разновидностей command
эквивалентен — запуск внешней команды.
Теперь обратим внимание на слабые места этого механизма: при возможности прослушки трафика, любой злоумышленник вооруженный простейшим tcpdump
сможет с большой вероятностью обнаружить закономерности подобных повторяющихся действий (пакетов), после которых инициируется успешное соединение с сервером. После этого он может самостоятельно повторить необходимые «стуки», т.е. провести так называемую replay-атаку (sequence replay attack).
Для того чтобы свести опасность этого к минимуму, у knockd
имеется вариант работы с одноразовыми секретными последовательностями, для демонстрации чего приведем третий вариант настройки блока:
[openFTP] one_time_sequences = /etc/knockd/ftp_sequences.txt seq_timeout = 20 tcpflags = fin,!ack command = /usr/sbin/iptables -A input -s %IP% -p tcp —dport 25 -j ACCEPT
Единственное новое, что требует пояснение в этом примере — параметр one_time_sequences
, который указывает на файл-список всех доступных последовательностей, который должен быть подготовлен заранее. После каждой успешно сработавшей последовательности она аннулируется (будет закомментирована символом ’#’ вначале строки), после чего сервер начинает ожидать поступления следующей ключевой последовательности по списку.
Естественно, у сервера и клиента должны быть полностью аналогичные списки, проведение replay-атаки в таком случае затруднительно.
Вот «кусочек» такого списка для наглядности:
#3237:udp, 3334:udp, 1569:tcp, 1652:tcp #1945:udp, 4574, 2849:udp, 1952:udp 1367:tcp, 3176, 1678, 4893 1667:tcp, 3566:udp, 1596:tcp, 1589:tcp 1677, 3774, 1789:udp, 2697 5516:tcp, 5335:udp, 2044:tcp, 3297:tcp
Рассмотрев «дела серверные» самое время переключить наше внимание на сторону клиента и ответить на насущный вопрос: как же выстукивать все эти «сетевые трели» простому смертному?
Во-первых, можно использовать штатный клиент поставляемый вместе с самим сервером, вот типичный пример запуска SSH (параметры для подключения аналогичны формату используемому в серверном knockd.conf
и в режиме подключения по списку):
savgor$ knock 1291:udp, 3614:udp, 1492:tcp, 1090:udp & ssh sesame.samag.ru
Но, при большой мобильности не всегда удобно иметь дело именно с unix’овым клиентом, и тут на выручку приходят сторонние клиенты, полностью совместимые с оригинальным knockd
. Прежде чем перечислять их следует отметить, что в качестве универсального решения можно приспособить обычные telnet
или netcat
, разве что при этом на сервере следует увеличить тайм-аут ожидания и использовать более простые комбинации стуков.
Для обладателей мобильных устройств на базе iOS я рекомендую KnockOnD или Port Knock Lite for iPhone (увидеть первый из них можно на рисунке ниже). Кроме того можно использовать Knock-Android для одноименной платформы, ну и в заключение стоит привести пример веб-клиента для knockd
, который написан на PHP — это phpKnockClient.
Knockd-клиент для iPhone/iPod – KnockOnD
Вот его запуск из командной строки:
$ knock.php sesame.samag.ru 1291:udp, 3614:udp, 1492:tcp, 1090:udp
Обзор клиентов закончу классическим nmap, который при правильно заданных параметрах может «выстукивать» сколь угодные сложные чечетки на удаленном брандмауэре, вот готовый шаблон из ключей для его использования в этих целях:
$ nmap -sS -T Polite -p<port1>,<port2>,<portN>... <target>
Здесь мы указываем правильный порядок из портов (port1, port2
и так далее), где target
— это сетевой адрес целевого сервера. При этом важно указать ключ Polite
, который гарантирует строго указанный порядок отправки пакетов, более подробное объяснение опций можно посмотреть в документации к nmap.
Brute-force атаки в интернете с каждым готом принимают все большие обороты. По словам одного из сотрудников SANS, «если у вас есть SSH-сервер, открытый для доступа из Интернет и пароль к нему не имеет длины в 8 символов или больше, то этот сервер либо уже взломан, либо будет взломан в ближайшее время». В последнее время начали свою активную работу сразу несколько ботнетов работающие по распределенному принципу: с одного IP-адреса производится лишь несколько попыток подбора пароля, тогда как в подборе участвуют несколько десятков тысяч зараженных машин, каждая из которых перебирает небольшой диапазон вариантов. Такой ботнет способен обнаруживать через предварительное сканирование наличие SSH на нестандартных портах, после чего координировать работу всего «пчелиного улея» по «ленивому перебору» всех вариантов паролей с совершенно разных IP-адресов.
В декабре 2011 года в ходе расследования работы троянского ПО Duqu, эксперты «Лаборатории Касперского» обнаружили факты взломов unix-систем через OpenSSH 4.3 без использования brute-force, вероятнее всего для этого был использован пока неизвестный 0day-эксплоит. В завершении цепочки подобных однотипных примеров хочется вспомнить недавнюю публикацию рабочего эксплоита для одного из самых популярных в мире ftp-серверов — proftpd (чуть позже похожая уязвимость была обнаружена в vsftpd, а также в ftpd из FreeBSD).
Можно приводить бесконечные примеры того, что открытый для всего мира сервис опасен по огромному набору причин: это и возможность подбора или перехвата паролей, использование известной или 0day-уязвимости, нахождение ошибки в настройке и так далее. Часто жесткое ограничение доступа по IP-адресу невозможно, и в таком случае, как один из действительно универсальных вариантов для профилактики любых подобных ситуаций можно рекомендовать сокрытие сервиса через port knocking.
Следующую часть-продолжение этой статьи — читайте здесь.
6 комментариев
У вас ошибочка в статье. MySQL ну никак нельзя называть СУБД, побойтесь Бога!
Пользователь MS SQL - спасибо, рассмешили про замечание с СУБД :) Но пусть остаётся уж как есть, люди мы тёмные...
FYI для всех остальных:
http://ru.wikipedia.org/wiki/MySQL -> Тип: Реляционная СУБД
MS SQL - вас как раз сложно назвать СУБД. На дворе 21-й век, а эта индусская поделка намертво застряла в 20-м и морально, и технически. MySQL недалеко ушёл, но на нём свет клином не сошёлся, посмотрите например PostgreSQL, хоть это и версионник. Впрочем вам и слова то такие боюсь не знакомы, вы похоже вместе с MS застряли в 90-х годах :)
2Unixman MySQL не сильно отстала от PostrgreSQL. Зря вы так о ней отзываетесь. Ограничения без сомнения есть, но это очень мощное средство.
Вы еще здесь Oracle вспомните, а MariaDB очень даже ничего база, да и пофиг на ее реляционность, это уже дело 10-е.
В команде
savgor$ knock 1291:udp, 3614:udp, 1492:tcp, 1090:udp & ssh sesame.samag.ru
ошибка
видимо так
savgor$ knock sesame.samag.ru 1291:udp, 3614:udp, 1492:tcp, 1090:udp & ssh sesame.samag.ru