Подмена адреса

Самый простой способ обмануть сервер — это создать пакет, чей исходный адрес является фальшивым или поддельным. Это на удивление легко сделать. Для создания пакетов я использую очень мощный инструмент сетевого анализа, который называется Scapy . Scapy позволит вам создавать пакеты на лету, передавать их и сканировать вашу сеть на предмет любого ответа.

Например, допустим, я нахожусь в моей локальной сети (которой я сейчас занимаюсь, когда я пишу это), подключенной через беспроводную сеть как 192.168.15.113. Я собираюсь взаимодействовать с маршрутизатором, который находится на 192.168.15.1. Для целей анализа я также настроил запущенную виртуальную машину 192.168.15.114, чтобы я мог видеть, что происходит, когда я подделываю пакет.

Итак, допустим, я подделал ICMP- echo-requestпакет, отправленный .1(маршрутизатору) от .113(меня), но подделанный, как если бы он пришел .114(виртуальная машина). В Scapy это довольно легко сделать. Я запускаю два сеанса в двух терминальных окнах. В первом я набираю:

>>> send(IP(src=»192.168.15.114″, dst=»192.168.15.1″)/ICMP())
.
Sent 1 packets.

Несмотря на то, что мой компьютер работает .113, я говорю scapy, чтобы установить исходный адрес для echo-requestпакета ICMP .114, на который я хочу атаковать. Я отправляю этот «пинг» маршрутизатору, который теперь должен отправить .114мне ответ вместо меня.

В другом окне моего терминала я снова запускаю scapy, на этот раз в случайном режиме в качестве анализатора пакетов. Случайный режим означает, что он будет захватывать все пакеты, замеченные в сети, а не только те, которые предназначены для моей собственной машины. Вот что я вижу:

>>> sniff(filter=»icmp»)
^C
>>> _.show()
0000 Ether / IP / ICMP 192.168.15.114 > 192.168.15.1 echo-request 0
0001 Ether / IP / ICMP 192.168.15.1 > 192.168.15.114 echo-reply 0

Я запустил анализатор, затем сделал пинг, затем остановил анализатор, нажав Control-C. Я вижу, что два ICMP-пакета были замечены во время сниффа. Показывая содержимое этих пакетов, я могу видеть и пакет, который я передал, и ответ — который вернулся .114!

Это подделка. Как это может быть использовано для нападения на кого-то? Продолжайте читать в следующем разделе, поскольку то, что мы только что сделали, лежит в основе атаки smurf.

Однако некоторые подделки пакетов более очевидны. Например, пакет, поступающий из Интернета, привязан к частному IP-адресу или определенным широковещательным адресам, таким как адрес, начинающийся с 192.168или 224. Они никогда не действительны, поэтому рекомендуется отбрасывать такие пакеты сразу после получения. Вот iptablesправила, чтобы сделать это:

Reject packets from RFC1918 class networks (i.e., spoofed)
iptables -A INPUT -s 10.0.0.0/8 -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
iptables -A INPUT -s 127.0.0.0/8 -j DROP
iptables -A INPUT -s 224.0.0.0/4 -j DROP
iptables -A INPUT -d 224.0.0.0/4 -j DROP
iptables -A INPUT -s 240.0.0.0/5 -j DROP
iptables -A INPUT -d 240.0.0.0/5 -j DROP
iptables -A INPUT -s 0.0.0.0/8 -j DROP
iptables -A INPUT -d 0.0.0.0/8 -j DROP
iptables -A INPUT -d 239.255.255.0/24 -j DROP
iptables -A INPUT -d 255.255.255.255 -j DROP

Вот то же самое, теперь для ipfwпользователей:

Verify the reverse path to help avoid spoofed packets. This means any
packet coming from a particular interface must have an address matching the
netmask for that interface.
ipfw add 100 deny all from any to any not verrevpath in
Deny all inbound traffic from RFC1918 address spaces (spoof!)
ipfw add 110 deny all from 192.168.0.0/16 to any in
ipfw add 120 deny all from 172.16.0.0/12 to any in
ipfw add 130 deny all from 10.0.0.0/8 to any in
ipfw add 140 deny all from 127.0.0.0/8 to any in
ipfw add 150 deny all from 224.0.0.0/4 to any in
ipfw add 160 deny all from any to 224.0.0.0/4 in
ipfw add 170 deny all from 240.0.0.0/5 to any in
ipfw add 180 deny all from any to 240.0.0.0/5 in
ipfw add 190 deny all from 0.0.0.0/8 to any in
ipfw add 200 deny all from any to 0.0.0.0/8 in
ipfw add 210 deny all from any to 239.255.255.0/24 in
ipfw add 220 deny all from any to 255.255.255.255 in

Smurf атаки

Атака smurf (названная в честь программы, которую используют люди для выполнения атаки), состоит из трех хостов: атакующий, посредник и жертва.

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

Злоумышленник должен создать нескончаемый поток ICMP-пакетов, подделанных так, чтобы они выглядели так, как если бы они исходили от жертвы . Эти пакеты отправляются посреднику, который отвечает на каждый из них, отправляя ICMP- echo-responseпакет жертве. Жертва, конечно, никогда не просила эти пакеты, но у нее нет никакого способа остановить бесконечный поток. Даже если он позвонит интернет-провайдеру посредника, он не сможет легко остановить поток, кроме как путем отключения всего трафика ICMP. Даже если он проверяет свои журналы пакетов, он не может узнать IP-адрес злоумышленника, потому что злоумышленник подделал пакет.

Существует защита от атаки smurf: ограничение скорости входящих ICMP-пакетов до крайне медленной струйки. В конце концов, когда трафик ICMP является законным, он имеет очень низкую пропускную способность. Если кто-то пингует вас, чтобы увидеть, живы ли вы, обычно достаточно нескольких ответных пакетов. А для других типов ответа ICMP — например, когда маршрутизатор информирует вашу сетевую карту о проблемах маршрутизации — опять же требуется всего несколько пакетов, а не огромный поток, который представляет собой атаку smurf.

Вот как смонтировать защиту, используя iptables:

Allow most ICMP packets to be received (so people can check our
presence), but restrict the flow to avoid ping flood attacks
iptables -A INPUT -p icmp -m icmp ---icmp-type address-mask-request -j DROP
iptables -A INPUT -p icmp -m icmp ---icmp-type timestamp-request -j DROP
iptables -A INPUT -p icmp -m icmp -m limit ---limit 1/second -j ACCEPT

Здесь мы ограничиваем трафик ICMP одним пакетом в секунду. Таким образом, даже если кто-то нас засыпет через smurf, большинство пакетов, которые мы когда-либо получим за день, составляет чуть более 86 000. Если вы хотите еще меньше, увеличьте лимит.

Для реализации этого же правила ipfwнеобходимо использовать dummynetформирователь трафика для маршрутизации пакетов ICMP по узкому каналу пропускной способности:

If you want to make packet decision after pipe inejection, enable this to
make sure that packets get reinjected into the firewall
sysctl -w net.inet.ip.fw.one_pass=0
Rate limit ICMP traffic to avoid line clogging by Smurf attacks. We
direct ICMP packets into a 16 Kbit/s link.
ipfw pipe 300 config bw 16Kbit/s queue 1
ipfw pipe 310 config bw 16Kbit/s queue 5
ipfw add 300 drop icmp from any to not me in
ipfw add 310 drop icmp from not me to any out
ipfw add 320 pipe 100 icmp from any to any in
ipfw add 330 pipe 110 icmp from any to any out

Опять же, ограничение скорости можно настроить, поэтому, если вы обнаружите, что 16 Кбит/с — это большой процент вашего канала (как это может быть, скажем, для соединения DSL 256 Кбит/с), то уменьшите его до 8 Кбит/с. с или даже 4 кбит/с.

Поддельные пакеты

Помимо подмены пакетов, существуют другие типы поддельных пакетов, которые злоумышленник может сгенерировать, чтобы попытаться раскрыть потоки в сетевом стеке. Возьмите, например, флаги SYN и FIN. TCP SYN используется для запроса открытия TCP-соединения на сервере; TCP FIN используется для завершения существующего соединения. Итак, имеет ли смысл посылать пакет, в котором одновременно установлены и SYN, и FIN?

Не за что. Эти типы пакетов являются «поддельными» в том смысле, что они используют комбинации флагов, которые не имеют смысла. Тем не менее, некоторые реализации сети могут быть обмануты в странное поведение, когда такие неожиданные пакеты принимаются. Тогда лучшая защита — просто отвергнуть их всех. Вот как можно ограничить использование поддельных пакетов iptables:

Drop invalid packets immediately
iptables -A INPUT -m state ---state INVALID -j DROP
iptables -A FORWARD -m state ---state INVALID -j DROP
iptables -A OUTPUT -m state ---state INVALID -j DROP
Drop bogus TCP packets
iptables -A INPUT -p tcp -m tcp ---tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp -m tcp ---tcp-flags SYN,RST SYN,RST -j DROP

Атаки сброса TCP

Чтобы понять атаку сброса TCP, вы должны сначала понять, как TCP управляет соединениями. Чтобы подключиться к удаленному хосту, клиент инициирует соединение, используя «трехстороннее рукопожатие» или последовательность из трех пакетов, передаваемых назад и вперед между клиентом и сервером, например:

  1. Клиент отправляет пакет TCP SYN на сервер с его полем «seq», установленным на случайное число.
  2. Сервер отвечает пакетом SYN + ACK, чье поле «ack» больше, чем поле «seq» клиентского пакета, но чье собственное поле «seq» является другим случайным числом, на этот раз выбранным сервером.
  3. Клиент устанавливает соединение, отвечая на этот пакет с помощью пакета ACK, у которого поле «ack» на единицу больше номера «seq» сервера, а чье собственное поле «seq» на единицу больше, чем первое значение «seq» из шага 1 ,

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

Лучше всего понять это, увидев реальные пакеты. Я буду использовать scapy, чтобы вручную установить TCP-соединение с сервером, и покажу вам, как выглядят пакеты в каждой точке во время связи:

Сначала я отправляю исходный пакет SYN, используя seq 0 (вместо случайного числа). Это означает, что я ожидаю, что поле «ack» в ответе сервера будет установлено на 1 (seq + 1). После отправки я слушаю ответный пакет, сервер SYN + ACK. Это можно сделать одной командой в scapy:

>>> sr1(IP(dst=’mail.johnwiegley.com’)/TCP(dport=25,flags=’S’))
Begin emission:
.Finished to send 1 packets.
..*
Received 4 packets, got 1 answers, remaining 0 packets
,IP version=4L ihl=5L tos=0x0 len=44 id=0 flags=DF frag=0L ttl=51
proto=tcp chksum=0x10d2 src=208.70.150.154 dst=192.168.15.113
options=» |
>

Я немного отформатировал результаты, но здесь вы можете увидеть флаги «SA» пакета ответа (SYN + ACK), а поле «ack» правильно установлено в 1. Поле seq было установлено в случайное число сервером 651538917. Это означает, что пакет, который я отправляю в ответ, должен установить в поле «ack» значение 651538918 (seq = ack + 1). Я могу использовать немного магии Python, чтобы упростить это для меня, используя специальную переменную underbar для ссылки на детали полученного пакета:

>>> sr1(IP(dst=’mail.johnwiegley.com’)/TCP(dport=25,flags=’A’,ack=_.seq+1,seq=1))
Begin emission:
Finished to send 1 packets.
……………*
Received 16 packets, got 1 answers, remaining 0 packets
,IP version=4L ihl=5L tos=0x0 len=80 id=43334 flags=DF frag=0L ttl=51
proto=tcp chksum=0x6767 src=208.70.150.154 dst=192.168.15.113
options=» |
,TCP sport=smtp dport=ftp_data seq=651538918L ack=1L dataofs=5L
reserved=0L flags=PA window=5840 chksum=0x2cdb urgptr=0
options=[] |
>>

Успех! Сервер ответил на наш ACK, отправив обратно исходный пакет данных в диалоге, который содержит начальный баннер SMTP-соединения. Вы можете видеть флаги в этом ответном пакете PA (PSH + ACK), что означает, что это подтверждение нашего подтверждения, и что мы должны рассмотреть полезную нагрузку данных немедленно, а не ждать, пока сначала накопится больше данных. Поле «seq» теперь на единицу больше, чем поле «seq» из пакета SYN + ACK (поскольку это второй пакет, отправленный нам сервером). Любой пакет, который мы отправляем обратно в ответ, должен иметь значение «ack», равное одному больше, чем этот «seq».

Теперь есть два способа заключения этой связи. Если клиент желает закрыть соединение, он отправляет пакет FIN, поле «ack» которого должно содержать правильное следующее значение в последовательности. Если сервер должен завершить работу, он также отправляет пакет FIN, опять же, чье «ack» должно быть правильно установлено. Если любая из сторон должна «прервать» соединение — обычно для того, чтобы восстановить его — они отправляют пакет RST вместо FIN.

Однако это открывает линию атаки, поскольку злоумышленнику теперь нужно знать только две вещи, чтобы заставить нас закрыть наше соединение: наш IP-адрес и следующий номер пакета в последовательности. Если у них есть оба из них, они могут отправить нам поддельный пакет, подделанный, как если бы он пришел с сервера, с установленным флагом RST. Если он правильно понял порядковый номер, у нас нет другого выбора, кроме как предположить, что сервер говорит нам разорвать наше соединение.

Конечно, угадать правильный порядковый номер не всегда легко. Существуют различные способы , чтобы уменьшить количество пакетов , которые должны быть сформированы, но решительная злоумышленник будет в состоянии найти правильный номер, если соединение является долгоживущим. Это имеет место с некоторыми аппаратными средствами маршрутизации, которые зависят от долгоживущих соединений для работы. Разумеется, это не повлияет на клиентов, использующих VPN на основе UDP, поскольку нет эквивалента флагу RST для прерывания связи UDP.

Как можно защититься от атаки RST? Самый простой способ — просто замедлить прием пакетов RST. Данные перемещаются в Интернете довольно быстро, и есть вероятность, что следующий пакет в последовательности будет доставлен довольно скоро. Задержка RST-пакетов примерно на полсекунды значительно усложняет злоумышленнику принудительную передачу своего пакета в очередь перед правильным. Это не надежная защита, но она, безусловно, значительно усложняет работу атакующего.

Эта защита не может быть реализована непосредственно iptables, но требует правильного выполнения дисциплин в очереди. Тем не менее, в некоторой степени похожая защита может быть осуществлена ​​простым ограничением скорости пакетов RST, как мы это делали для пакетов ICMP выше:

Drop excessive RST packets to avoid SMURF attacks, by given the
next real data packet in the sequence a better chance to arrive first.
iptables -A INPUT -p tcp -m tcp ---tcp-flags RST RST \
-m limit ---limit 2/second ---limit-burst 2 -j ACCEPT

В ipfwреализации проще, потому что мы можем использовать dummynet шейпер:
Delay TCP RESET packets.
ipfw pipe 400 config delay 500
ipfw add 400 pipe 400 tcp from any to any in tcpflags rst

SYN флуд

Если вы вспомните обсуждение трехсторонних рукопожатий TCP в предыдущем разделе, мы обнаружим, что в схеме есть слабое место: для каждого пакета SYN, который получает сервер, он должен назначить — и запомнить — соответствующее значение «seq», которое он отправляет с его SYN + ACK, чтобы авторизовать ACK клиента, когда он наконец получен.

То есть, если клиент отправляет пакет SYN, а сервер отвечает пакетом SYN + ACK, он теперь ожидает от клиента пакета ACK для завершения соединения. До получения пакета ACK сервер удерживает соединение в «полуоткрытом» состоянии, где он отслеживает номер «seq», назначенный этому потенциальному соединению, в ожидании пакета ACK клиента для его завершения.

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

Ответом на поток SYN является ограничение скорости новых подключений, так как очень редко человеку нужно будет открывать поток новых подключений одновременно. Имейте в виду, когда вы устанавливаете значения для этого правила, веб-страницы с тоннами крошечных значков будут запрашивать одинаковое количество запросов на подключение от клиента при каждом доступе к этой странице.

Protect against SYN floods by rate limiting the number of new
connections from any host to 60 per second. This does *not* do rate
limiting overall, because then someone could easily shut us down by
saturating the limit.
iptables -A INPUT -m state ---state NEW -p tcp -m tcp ---syn \
-m recent ---name synflood ---set
iptables -A INPUT -m state ---state NEW -p tcp -m tcp ---syn \
-m recent ---name synflood ---update ---seconds 1 ---hitcount 60 -j DROP

То же самое может быть достигнуто при ipfw использовании dummynet формирователя:
Direct SYN
ipfw pipe 500 config bw 64Kbit/s queue 5
ipfw add 500 pipe 500 tcp from any to any in setup

Сканирование портов

В настоящее время многие хосты пытаются сканировать порты на моем сервере в поисках открытых сервисов, которые они могут использовать. Поскольку я запускаю очень мало служб на своем сервере, мне нравится искать соединения портов с обычно сканируемым портом (порт 139, для общего доступа к файлам Windows), а затем блокировать хосты, которые пытаются подключиться, к разговору с моим сервером для целый день. Правило довольно простое с использованием iptables recentмодуля:

Anyone who tried to portscan us is locked out for an entire day.
iptables -A INPUT -m recent ---name portscan ---rcheck ---seconds 86400 -j DROP
iptables -A FORWARD -m recent ---name portscan ---rcheck ---seconds 86400 -j DROP
Once the day has passed, remove them from the portscan list
iptables -A INPUT -m recent ---name portscan ---remove
iptables -A FORWARD -m recent ---name portscan ---remove
These rules add scanners to the portscan list, and log the attempt.
iptables -A INPUT -p tcp -m tcp ---dport 139 \
-m recent ---name portscan ---set -j LOG ---log-prefix «Portscan:»
iptables -A INPUT -p tcp -m tcp ---dport 139 \
-m recent ---name portscan ---set -j DROP
iptables -A FORWARD -p tcp -m tcp ---dport 139 \
-m recent ---name portscan ---set -j LOG ---log-prefix «Portscan:»
iptables -A FORWARD -p tcp -m tcp ---dport 139 \
-m recent ---name portscan ---set -j DROP

К сожалению, нет способа реализовать эту ловушку, используяipfwв одиночку. Это потребовало бы divertправила, которое отправляет пакеты демону пользовательского пространства, которое будет отслеживать адрес хоста и реализовывать однодневное отбрасывание пакетов. Поскольку в настоящее время я не использую ipfwни на каких серверах, я еще не написал эту утилиту.

Парольная атака

Атаки с использованием паролей становятся постоянной проблемой для всех, кто запускает сервер в Интернете. Каждый день я вижу сотни и сотни неудачных попыток входа в систему как для моей службы FTP, так и для моей службы ssh.

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

Для FTP это намного сложнее, потому что вы хотите, чтобы люди могли войти, хотя бы анонимно. Я использую только анонимные входы в систему, vsftpdчто позволяет мне вообще отключать входы на основе пользователя. Это также устраняет проблему, так как в моих лог-файлах больше не появляется сбойных входов.

Источник