`` NETerrorism ''
                          =================

 content:

 : 0x00 :   gateway bypassing

   : 0x01 :   IPv4 over IPv4 tunneling
   : 0x02 :   GRE (Generic Rounting Encapsulation) protocol

   : 0x03 :   usage in FreeBSD and Linux

 : 0x04 :   have real phun with routing tables

   : 0x05 :   how does work routing tables?
   : 0x06 :   ICMP redirect messages

 : 0x07 :   scan the net

============================================/   Gateway bypassing  /===========

  Здесь будут рассмотрены  методы проникновения в  закрытые сети с помощью
  обхода ограничений tcp/ip стека шлюзовой системы.

  Итак, поехали.  Для начала нада сказать пару слов о работе  этого самого
  стека. Он основан, если вы не знаете, на модели OSI то есть используется
  многоуровневая обработка датаграмм (пакетов).  Протоколом  транспортного
  уровня является IP, далее ядро начинает его разбирать  дальше и смотреть
  что там за типы и прочее.  Но по идее пакет с одним ip заголовком должен
  дойти до пункта назначения, разве что какой-нибудь промежуточный  роутер
  увидит, что контрольная сумма заголовка вышестоящего протокола (которого
  у нас нет) является лажовой и порежет его. Значит так, мы  пишем в пакет
  dest_addr  (ip адрес  для доставки)  и  выгружаем  его в  сеть.  Роутеры
  принимают и доставляют датаграмму до конечного пункта.  Теперь наш пакет
  начинает ковырять ip-стек оси  той машины и в зависимости от  значения в
  поле  proto,  передавать  управление  обработчику  данного  вышестоящего
  протокола.


  В этом разделе я не буду  рассказывать подробно о том что  и как пашет в
  GRE и IPoverIP,  просто  в кратце  объясню саму  идею.  Назначением оных
  является  организация  и передача  данных по виртуальным  каналам поверх
  публично доступной сети.  Во втором  всё просто до безобразия:  один ip-
  пакет оборачивается в другой.  Внешний заголовок в поле dest_addr держит
  адрес  гейта,   а  внутренний  адресует  датаграмму   конкретному  хосту
  внутренней сети.


  Рассмотрим пример:

  адрес нашей машины: 13.6.6.6
  адрес шлюза:  65.143.81.93
  адрес назначения (во внутренней сети): 192.168.0.5


     +------------------------+
     I     icmp echo пакет    I
     +------------------------+
     I внутренний IP заголовокI
     I                        I
     I src_ip:  13.6.6.6      I   внутренний пакет = ip заголовок + icmp пакет
     I dst_ip:  192.168.0.5   I
     I proto:  1 (ipv4 icmp)  I
     +------------------------+   -------------
     I  внешний IP заголовок  I
     I                        I   внешний заголовок
     I src_ip:  13.6.6.6      I
     I dst_ip:  65.143.81.93  I
     I proto:  4 (ip over ip) I
     +------------------------+

   Отправляем такой пакет, и когда он достигнет шлюза,  стек увидит в поле
   proto внешнего заголовка стоит 4, то есть это ip over ip протокол. Гейт
   передаёт  (если,  конечно,  поддерживает  IP over IP) внутренний  пакет
   своему  обработчику,  тот  снова  пробегает  на этот раз  внутренний ip
   заголовок и  видит что, во-первых, это icmp сообщение, а во-вторых, оно
   адресованно не ему.  Поэтому он передаёт его  во внутреннюю  сеть хосту
   (в нашем случае это 192.168.0.5).  Ответ к нам должен прийти нормально,
   т.к. для пользователя этого LAN'а отправка пакетов совершенно прозрачна
   что играет нам на руку.


   Теперь про GRE (хотя rfc на эту тему немало).  В  rfc  1701  вы  можете
   найти формат его пакетов:

    +-----------------------+
    I   внутренний  пакет   I
    +-----------------------+
    I     заголовок  GRE    I
    +-----------------------+
    I  внешний IP заголовок I
    +-----------------------+

   А вот и формат самого GRE-заголовка:

       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |C|R|K|S|s|Recur|  Flags  | Ver |         Protocol Type         |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |      Checksum (optional)      |       Offset (optional)       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                         Key (optional)                        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                    Sequence Number (optional)                 |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                         Routing (optional)
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   C,R,K,S,s - это опции,смотрите их подробное описание в rfc. Вкратце,они
   показывают, присутствует ли секция для  этих опиций или нет. К  примеру
   если 2-й бит не сброшен,то в GRE-заголовке должна присутствовать секция
   Routing в которой должен быть объявлен маршрут доставки датаграммы.   И
   так по аналогии:

   C - checksum
   K - key
   R - routing (кстати,  если  эта  опция  включена,  обязательно  должена
     присутствовать checksum)

   S - sequnce number
   s - strict source route

   В  protocol  type  мы  указываем  тип  инкапсулированного  пакета,  вот
   небольшой их список:

          Protocol Family                     PTYPE
       ---------------                     -----
       Reserved                            0000
       SNA                                 0004
       OSI network layer                   00FE
       PUP                                 0200
       XNS                                 0600
       IP                                  0800
       Chaos                               0804
       RFC 826 ARP                         0806
       Frame Relay ARP                     0808
       VINES                               0BAD
       VINES Echo                          0BAE
       VINES Loopback                      0BAF
       DECnet (Phase IV)                   6003
       Transparent Ethernet Bridging       6558
       Raw Frame Relay                     6559
       Apollo Domain                       8019
       Ethertalk (Appletalk)               809B
       Novell IPX                          8137
       RFC 1144 TCP/IP compression         876B
       IP Autonomous Systems               876C
       Secure Data                         876D
       Reserved                            FFFF

   Offset юзается только когда включена опция routing.

   Как видите, протокол достаточно полезный и интересный.  Часто с помощью
   него линкуют локальные сети поверх инета,  в такие сетки вполне реально
   проникнуть с помощью gre.


   Пример использования GRE в FreeBSD:

   1.

  # kldload if_gre.ko  # загружаем модуль обработчика протокола, если он
                       # не вкомпилён в ядро

   Получим что-то подобное:

  # kldstat
  Id Refs Address    Size     Name
     1    4 0xc0100000 2c1af8   kernel
     3    1 0xc13d4000 6000     ipfw.ko
     5    1 0xc14ab000 4000     if_gre.ko

  # ifconfig gre0 create
  # ifconfig gre0 tunnel this_ip gate_ip
  # создаём point-to-point канал между нашей машиной и шлюзом

  # ifconfig gre0 inet my_ip/30 gate_ip/30 netmask 255.255.255.252
  # конфигурим ip-ranges той сети

  # ifconfig gre0 up

   или вот так (с помощью утилиты greconfig) логинимся в лан:

   10.1.12.37 - my lan ip
   10.1.12.38 - internal lan'z gate
   212.25.240.34 - my internet ip
   217.154.12.2  - lan'z gate inet ip


  # ifconfig gre1 inet 10.1.12.37 10.1.12.38 netmask 255.255.255.252 up
  # /usr/sbin/greconfig -i gre1 -v -s 212.25.240.34 -d 217.154.12.2

   а на шлюзе:

  # kldload if_gre.ko
  # sysctl -w net.inet.ip.gre_default_mtu=1450
  # ifconfig gre1 create
  # ifconfig gre1 tunnel 217.154.12.2 212.25.240.34
  # ifconfig gre1 mtu 1450
  # ifconfig gre1 inet 10.1.12.38 10.1.12.37 netmask 255.255.255.252
  # ifconfig gre1 up



==================================/ have a real phun with routnig tables /=====


  Теперь  пора  поговорить  про  такое  веселье как  удалённая модификация
  таблиц  маршрутаризации на  вражеском хосте.  Это  позволяет нам сделать
  такой  бесценный тип icmp пакетов как redirect.  Но обо всём по порядку,
  сперва стоит рассказать о том, как собственно, работает маршрутизация на
  машине простого смертного.


  Итак, как всё это работает. Допустим, мы создаём в проге сокет семейства
  AF_INET (2), потом в его sin_addr загоняем ip конечного пункта и шлём, к
  примеру UDP пакет. Как хост узнаёт куда доставлять его?? Вот для этого и
  нужны таблицы маршрутаризации,  которые ядро постоянно  хранит в памяти.
  Представьте себе таблицу с полями dest_addr, gateway и interface (вообще
  всё  посложнее там,  но для  примера сойдёт).  Теперь  для  наглядности,
  заполним её:

      dest_addr       gate              interface
     +---------------+-----------------+---------------
      default         213.65.1.7        ppp0 (point-to-point)
      10.0./16        10.0.0.1          eth0 (ethernet adapter)

  Эти записи сообщают о том, что все  пакеты по умолчанию  отправляются на
  шлюз с адресом 213.65.1.7, который присоединён  каналом точка-точка.  Во
  второй  строке говорится,  что пакеты хостам с  адресами 10.0.х.х  нужно
  слать на гейт 10.0.0.1,  доступный через ethernet-сеть.  Ядро  пробегает
  сперва записи для частных маршрутов (как вторая строка) а уж потом, если
  не находит ничего подходящего, шлёт пакет дефолтовому гейту.


  Допустим мы отправляем датаграмму на хост 10.0.13.37.  Тогда ядро, после
  вызова sendto() начинает  искать в роутинговой  таблице подходящий  гейт
  для  отправки.  Найдя его (10.0.0.1),  она генерит ip и udp  заголовок к
  нашему пакету, причём ip_dest = 10.0.13.37, и упаковывает его в ehternet
  фрейм, в котором в качестве адреса назначения ставит mac адрес гейта.


  Тот, получив  датаграмму, видит, что  по dest_addr она адресована не ему,
  и перенаправляет  её дальше,  прогнав ip назначения по  своей роутиногвой
  таблице. Вот собственно и вся теория касательно самого роутинга.


  Пора поговорить о icmp_redirect пакетах.  Итак, по  rfc 1122  хосты  (не
  роутеры!!) обязаны обрабатывать такие сообщения, что есть  большой плюс.
  Формат icmp_redirect датаграммы:

   0        7        15                31
   +--------+--------+--------+--------+
   I  type  I  code  I    check sum    I
   +--------+--------+-----------------+
   I        new   router   addr        I
   +-----------------------------------+
   I   source IP-header + 64 bits of   I
   I         original datagam          I
   +-----------------------------------+

  поле type должно быть равно 5, код - сойдёт 0,  на  самом деле,  роли не
  играет код сообщения, он должен быть только в пределах 0..3.

    new router addr  -  IP нового  шлюза,  на который  будут  отправляться
                        пакеты для dest_addr.

  А теперь  внимание!!  После адреса  нового шлюза  должен  присутствовать
  заголовок  сообщения,  которое  не удалось доставить данным  маршрутом и
  64  бита  его  содержимого  (для  идентификации).  Ядра  linux'a (все!),
  FreeBSD  и  NetBSD,  как  оказалось после  изучения исходников  сетевого
  стека tcp/ip,  нихуя не смотрят на то, что ты суёшь после  адреса нового
  роутера,  кроме поля dest_ip из  присланного заголовка, и то просто чтоб
  узнать  к  какому  dest_addr  приписать  ip  нового роутера.  Так что мы
  запросто можем состряпать  нужный  нам  ip-заголовок,  вставить свой  ip
  в качестве нового роутера и  отправить какому-нибудь хосту своего lan'a,
  тем самым поменяв  ему таблицу  маршрутизации (умные  оси  типа *nix  не
  удаляют старые  роутинговые  записи,  а добавляют к  данному конкретному
  новую)  и  начать  снифать весь его исходящий  трафик для ip, который мы
  поспуфали. Пример:


   ### host A (our victim) ###

    таблица роутинга:
    default      192.168.0.1   eth0  netmask 0.0.0.0
    (такая  маска соотвествует всем default  записям и означает,  что всем
    адресам пакеты нужно слать через данный гейт)

    192.168./16  196.168.0.15  eth0  netmask 255.255.0.0

    ip: 192.168.0.15

   ### host X (our mad box)###

    таблица роутинга:
    default      192.168.0.1   eth0  netmask 0.0.0.0
    192.168./16  196.168.0.15  eth0  netmask 255.255.0.0

    ip: 192.168.13.37


  Итак,  нам  необходимо чтобы  пакеты шли через нашу  машину, а  не через
  стандартный гейт 192.168.0.1. Для этого мы шлём такой пакет хосту A:

    +----------------------------+
    | IP header:                 |
    | src_addr = 10.0.0.1        |
    | dst_addr = 192.168.0.15    |
    | proto = 1 (icmp)           |
    +----------------------------+
    | ICMP header:               |
    | type = 5 (redirect)        |
    | code = 0 (net)             |   headerz
    | new_gate: 192.168.13.37    |
    +----------------------------+  ---
    | fake IP header:            |
    | src_addr = 192.168.0.15    |   payload area
    | dst_addr = 13.6.6.6        |
    | ...                        |
    | + 64 bits of garbage       |
    +----------------------------+

  Представим как его будет разбирать ядро хоста А:  получено  IP сообщение
  с адресом  назначения равным  адресу данной  машины.  Протокол  равен 1,
  то бишь это  ICMP  пакет.  Далее заголовок  icmp + data передаются icmp-
  обработчику,  который видит, что это icmp_redirect сообщение.  Далее  он
  выдирает из icmp-заголовка адрес нового шлюза,  из присланного ip хидера
  заимствует dst_addr (который у нас 13.6.6.6) и прогоняет  его по таблице
  роутинга. Видя, что  нету  специальных  записей,  подходящих  к нему, он
  берётся модифицировать default запись и прописывает гейтом туда наш new-
  gate aka 192.168.13.37 leet box )) После этого таблица роутинга у жертвы
  будет выглядеть вот так:

    default      192.168.13.37   eth0  netmask 0.0.0.0
                   ^^^^^ sp00fed d0ne!
    192.168./16  196.168.0.15  eth0  netmask 255.255.0.0

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

    13.6.6.6     192.168.13.37   eth0

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


  Итак, что же мешает нам провернуть  описанную атаку в инете??  Начнём  с
  того, что ядро перед модификацией роутинговой  таблицы должно проверять,
  доступен ли шлюз напрямую, тоесть до него должен быть 1 hop  (короче  он
  должен быть доступен напрямую.. теоретически).  Это проверяется видимо с
  помощью пересчёта TTL,и конечно, установкой предельно малых значений TTL 
  когда пакет просто не может улететь далеко.  Точно сказать не могу, т.к.
  не смотрел, как всё это дело реализовано в ядре.


  Но  вот  как-то  поднимал pppd  на одной  из машин  под FreeBSD,  и  при
  коннекте увидел довольно интересную вещь:  pppd как известно добавляет в
  роутинговую  таблицу  ppp-гейт и  при опции  defaultroute делаёт  данный
  маршрут дефолтовым. Дык вот,  после коннекта у меня в  таблице появились
  две записи:


    default       217.42.85.3          netmask 0.0.0.0
    217.42.85.3   63.75.196.112  ppp0


  Причём ppp-линк соединял меня и машину 63.75.196.112.  Выходит,  что для
  отправки пакетов,  мне  необходимо слать  пакеты на неё,  а  оттуда  уже
  они уйдут на мой дефолтовый гейт 217.42.85.3.  Самое  интересное в  том,
  гейт мне  недоступен напрямую,  следовательно проверка как-то обходится.
  Занчит есть немалая  вероятность того, что  можно провернуть  это и не в
  ppp. К примеру, мы находимся в 2х хопах от жертвы:

    victim ---> gate ---> hax0r
           hop1      hop2

  Допустим нам нужно снифать её трафик до узла 3.1.33.7. Тогда мы шлём уже
  2 пакета, один из которых ставит дефолтовым шлюзом нашу тачку,  а вторым
  делаем сслыку на неё через старый гейт. Получится что-то вроде:

   default   hax0r   netmask 0.0.0.0
   hax0r     gate

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

  Кстати, интересный момент - по rfc роутеры не должны модифицировать свои
  таблицы при icmp_redirect'ах. Но если в качестве роутера  стоит *nix без
  всяких файрволов и адванседных настроек, то мы можем рулить уже трафиком
  всей сети!!


  Вот какой роутинг настроен у balthost:

    $ netstat -r
    Routing tables

    Internet:
    Destination        Gateway            Flags    Refs      Use  Netif Expire
    default            194.204.33.254     UGSc      322  6915257   fxp0
    localhost          localhost          UH          1  2792245    lo0
    194.204.33         link#1             UC          2        0   fxp0
    vm                 00:02:b3:af:de:bf  UHLW        1  2953207    lo0
    194.204.33.254     00:09:44:2b:75:80  UHLW      320        0   fxp0   1199
    $ exit

  Вы видите, что по умолчанию все пакеты летят  на 194.204.33.254, который 
  мы можем заменить своим хостом и сами рулить их трафиком, если находимся
  не очень далеко от них.


                     host A
    hacker --> gate <
                     host B


================================================/   Scan the net   /===========


  Теперь пару слов о поиске машин для данных атак. Для icmp_redirect, если
  ты хочешь атаковать хост через lan, будет достаточно присутствия в одном
  сегменте с жертвой. Для  подобной атаки через  интернет нюансов больше -
  кпримеру Cisco рекомендует резать проходящие по инету пакеты icmp_redir,
  и так далее, поэтому успех зависит от того какое железо стоит на пути до
  таргета, какая ось у него стоит и какая используется сетевая топология.


  При поиске хостов с поддержкой GRE/IPoIP  зачастую достаточно следить за
  входящими пакетами  icmp error с кодом 2 ("protocol unreachable"). Очень
  рекомендуется сканировать сети забугорных универов (особенно MIT, но там
  очень много  ibm-овских машин  со спецефическимим  осями типа  Aix и  не
  менее оригинальным железом) в штатах и европе. Умные люди также советуют
  сканить  бразилию,  но это не проверенная инфа ;).  Кстати,  в  инклудах
  лежит имага  NERDC.gif,  на скрине пример  коммуниканикационной  системы
  университета  Флориды  (University of Florida - ufl.edu),  но о подобных
  штуках в другой раз..

# eof