Содержание статьи
В моей предыдущей статье я показал, как, опираясь лишь на особенности сетевого трафика злоумышленников, можно узнавать весьма любопытные, порою неочевидные вещи. Но такая информация вряд ли поможет нам защититься от них.
Куда более интересный вопрос — как мы можем помешать злоумышленникам изучать наши ресурсы в интернете, сбить их с толку или — еще лучше — испортить этот процесс и даже встречно атаковать злоумышленников? И это будут не советы по защите, а, скорее, рекомендации по тому, как стать максимально неудобным для хакера.
В этой статье мы разложим с десяток граблей, на которые непременно наступит хакер, — и станем максимально неудобными для атакующего!
Замедляем сканирование портов
Как правило, хакерские атаки начинаются на сетевом уровне. Пока у атакующего нет информации об используемых сервисах и протоколах, он не может подняться выше — на уровень приложений. И самая первая сетевая атака, с которой столкнется любая компания, — это, конечно же, сканирование портов.
Так хакер проводит активную разведку и определяет программное обеспечение, в котором ему потом предстоит искать уязвимости. И уже на этом этапе мы можем вступить в противостояние с хакером.
info
Эта статья основана на фрагменте книги «Хакерская самооборона. Приемы обнаружения и предотвращения хакерских атак», которая сейчас готовится к публикации.
Одной из самых простых рекомендаций по затруднению сканирования портов может быть запрет отправки пакетов TCP-RST. Такую возможность можно активировать буквально в одну команду:
iptables -A OUTPUT -o eth0 -p tcp --tcp-flags RST RST -j DROP
Суть в том, что, когда порт закрыт, мы не говорим об этом хакеру, сразу отправляя ему пакет TCP-RST. Тем самым мы вынуждаем его тратить некоторое время на ожидание возможного ACK-пакета, который отправляется уже в случае открытого порта.
Давай сравним время сканирования топ-1000 TCP-портов с отправкой RST-пакетов и с запретом.

А теперь активируем правило, запрещающее пакеты TCP-RST. Вновь запустим сканирование топ-1000 портов.

Видно, что эта простая рекомендация в десятки тысяч раз замедляет классическое сканирование TCP-портов. А умножив его на количество IP-адресов нашего периметра, получаем не очень приятное для хакера значение.
Делаем все порты открытыми
Учитывая, что количество возможных портов равно 65 535 для TCP и столько же для UDP, а типичный сетевой периметр нередко состоит из сотен IP-адресов, для хакера может оказаться достаточно накладным полное сканирование портов. В таком случае хакеры могут довольствоваться лишь самыми распространенными портами (топ-1000) или самыми перспективными для проникновения (low hanged fruits). И отсюда вытекает самая распространенная защитная практика — перевешивать службы на нестандартные порты. Но целеустремленный хакер все же не испугается полного сканирования портов и непременно найдет спрятанный сервис, на каком бы порте он ни висел.

Но куда более действенной техникой против сканирования портов является имитация всех неиспользуемых портов как открытых. Этого легко можно достигнуть с помощью файрвола, например iptables на Linux-сервере, и любого пустого листенера.
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 22 -j REDIRECT --to-ports 22iptables -t nat -A PREROUTING -i eth0 -p tcp -m conntrack --ctstate NEW -j REDIRECT --to-ports 1234while sleep 1; do nc -nv -lp 1234; doneПосле чего хакер увидит уже совсем иную, удручающую картину.

Все порты открыты. Теперь хакеру будет крайне затруднительно среди 65К открытых портов найти актуальные. Неопытные хакеры тут попадут еще в одну ловушку — часто они запускают сканирование портов с одновременной идентификацией служб, что в нашем случае еще сильнее замедлит сканирование и, скорее всего, не позволит им получить хоть какие‑то результаты.
Ложно открытые порты — относительно частая защитная мера коммерческих сетевых экранов. Но ее можно обойти, ведь за пакетом SYN-ACK с этого порта обычно ничего не приходит. Иными словами, эти порты не содержат никакой службы и хакеру видны как tcpwrapped или как порты с пустой версией.

Однако стоит признать, что потребуются колоссальные расходы трафика и времени на идентификацию всех возможных портов. Большинство хакеров обойдут этот узел стороной, и лишь самые целеустремленные и сумасшедшие продолжат атаки. Но мы тоже не сдаемся, в нашем арсенале есть еще ряд приемов…
Имитируем случайные сервисы
Раз хакер главным образом полагается все же не на сами открытые порты, а на службы, которые он идентифицирует на этих портах, то ударим ему по самому больному — сымитируем случайные службы! И на помощь нам вновь придет база фингерпринтов от Nmap.
Мы уже писали простой TCP/UDP-листенер для наблюдения за запросами хакеров. Теперь мы напишем листенер, который, вместо того чтобы молча принимать данные, станет слать хакеру особые байты, что будут казаться его сканеру каким‑либо сервисом. А эти байты мы возьмем из того же самого файла с фингерпринтами, используемого хакером.
В этот раз нам вновь предстоит распарсить базу фингерпринтов Nmap, только теперь нас будут интересовать уже не запросы, а ответы:
defence/services.py
#!/usr/bin/python3import socketimport rstr #pip3 install rstrimport randomdef get_random_match(): return random.choice(matches)matches = []with open("/usr/share/nmap/nmap-service-probes") as f: for line in f.readlines(): line = line.strip() if line.startswith("match "): matchtext = line[len("match "):] index = matchtext.index(" m") m = matchtext[index + 2] name = matchtext[:index] matchtext = matchtext[len(name):].strip() regx_start = 2 regx_end = matchtext.index(m, regx_start) regx = matchtext[regx_start:regx_end] try: matches.append( rstr.xeger(regx) ) except Exception as e: passs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)s.bind(("0.0.0.0", int(port)))s.listen(10)while True: c,info = s.accept() try: c.send(get_random_match().encode()) except: pass c.close()При каждом входящем подключении наш листенер будет отправлять случайно выбранный ответ из базы фингерпринтов Nmap.
Сетевой сканер Nmap парсит ответы от служб, опираясь на базу фингерпринтов, и делает это не по четкому совпадению, а по регулярному выражению. Поэтому мы, отправляя ответ, должны превратить случайно выбранную строку с регулярным выражением, содержащую в себе диапазон допустимых значений, во что‑то конкретное — в этом нам помогает библиотека rstr.
Мы запускаем наш «ответчик» на произвольном порте и ждем некоторое время, пока он распарсит Nmap-базу.

Хакер же при попытке просканировать этот порт и определить службу увидит совершенно случайный баннер.

Выглядит вполне правдоподобно. А что хакер увидит, когда мы совместим с этим трюк из предыдущего раздела? Сделаем все порты открытыми и направим их в этот листенер:
iptables -t nat -A PRETOUTING -i eth0 -p tcp --dport 22 -j REDIRECT --to-ports 22iptables -t nat -A PREROUTING -i eth0 -p tcp -m conntrack --ctstate NEW -j REDIRECT --to-ports 1234Теперь, когда хакер попробует просканировать большее количество портов, он увидит что‑то вроде такого.

Полная мешанина. На месте хакера я бы растерялся на какое‑то время. Такого большого количества разнообразных служб на одном компьютере быть не может. Но как среди этого найти настоящие сервисы?
Продолжение доступно только участникам
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
