Сниффинг сетевых пакетов – один из способов сбора информации о целевой системе без лишних телодвижений.
Пассивное прослушивание является скрытным, эффективным и, как правило, используется на начальной стадии хакерами и пентестерами, собирающими информацию о целевой сети. Однако если вы когда-либо запускали Wireshark от имени суперпользователя, то вероятно сталкивались с предупреждением, поскольку в этом случае ваша система подвергается риску. Запуск программы от имени суперпользователя и последующее компрометирование при помощи уязвимости нулевого дня – реальная угроза, которая существует во время перехвата случайного трафика. Цитата из документации на Wireshark:
«Очень небезопасно запускать Wireshark подобным образом, поскольку все возможные эксплоиты, заточенные под Wireshark, также будут запускаться от имени администратора, и ваша система может оказаться полностью скомпрометированной».
Соответственно, если какой-либо эксплоит под Wireshark уже разработан и известен узкому кругу лиц, то может быть запущен на вашем компьютере от имени суперпользователя в случае, если для Wireshark доступны эти привилегии. Поскольку мы часто сталкиваемся с неопределенностью, при получении разнообразной информации, важно предпринять шаги для минимизации ущерба и возможных неблагоприятных последствий.
Наилучший способ избежать эксплоитов нулевого дня - настроить юзера с правами на использование сетевого адаптера, но без привилегий суперпользователя. Однако вначале при решении этой задачи могут возникнуть некоторые сложности.
Для всех, кто занимается снифффингом пакетов, будет интересно узнать, что в Sniffglue эти функции безопасности используются по умолчанию. Эта утилита является средством пассивной разведки, позволяющая прослушивать трафик в сети без риска оказаться обнаруженным. В отличие от ARP-scan и других утилит, использующих активное сканирование, Sniffglue пассивно слушает без каких-либо действий по генерации трафика, позволяющих раскрыть ваше присутствие.
Один из ключевых методов для реализации безопасного сканирования – песочница, которая встроена внутрь Sniffglue. Само по себе приложение не делает ничего лишнего и, соответственно, оберегает себя от эксплоитов. Sniffglue написан на языке Rust, оптимизирован для использования всех доступных ресурсов процессора во время обработки пакетов, наделен дополнительными мерами безопасности и вполне заслуживает внимания.
Для работы с Sniffglue нужно установить Rust, поскольку программа написана на этом языке программирования. Рекомендую использовать Kali, Ubuntu или другую систему на базе Debian или Arch Linux. Я попробовал запускать Sniffglue в macOS, но столкнулся с трудностями. Вполне вероятно, что Rust у вас уже установлен, поскольку этот язык программирования предустановлен во многих системах.
Например, в системе со свежим дистрибутивом Kali Linux.
Кроме того, нужно установить библиотеки libseccomp-dev и libpcap-dev, предназначенные для модуля безопасных вычислений и парсинга pcap соответственно.
~$ sudo apt-get install libseccomp-dev libpcap-dev Reading package lists... Done Building dependency tree Reading state information... Done The following additional packages will be installed: libseccomp2 The following packages will be upgraded: libseccomp-dev libseccomp2 2 upgraded, 0 newly installed, 0 to remove and 1760 not upgraded. Need to get 0 B/116 kB of archives. After this operation, 68.6 kB of additional disk space will be used. Do you want to continue? [Y/n] y Reading changelogs... Done (Reading database ... 411760 files and directories currently installed.) Preparing to unpack .../libseccomp-dev_2.4.2-2_amd64.deb ... Unpacking libseccomp-dev:amd64 (2.4.2-2) over (2.4.1-2) ... Preparing to unpack .../libseccomp2_2.4.2-2_amd64.deb ... Unpacking libseccomp2:amd64 (2.4.2-2) over (2.4.1-2) ... Setting up libseccomp2:amd64 (2.4.2-2) ... Setting up libseccomp-dev:amd64 (2.4.2-2) ... Processing triggers for man-db (2.8.5-2) ... Processing triggers for libc-bin (2.28-8) ... Reading package lists... Done Building dependency tree Reading state information... Done The following packages will be upgraded: libpcap-dev 1 upgraded, 0 newly installed, 0 to remove and 1759 not upgraded. Need to get 0 B/29.0 kB of archives. After this operation, 2,048 B of additional disk space will be used. Reading changelogs... Done (Reading database ... 411761 files and directories currently installed.) Preparing to unpack .../libpcap-dev_1.9.1-2_amd64.deb ... Unpacking libpcap-dev:amd64 (1.9.1-2) over (1.9.0-2) ... Setting up libpcap-dev:amd64 (1.9.1-2) ...
Загрузка и запуск Sniffglue осуществляется при помощи менеджера пакетов Cargo (схожим образом Pip предназначен для Python), который появляется по умолчанию после установки Rust. После обновления системы проверьте, установлен ли Cargo, выполнив команду apt install cargo. Должны скомпилироваться множество других пакетов. Затем выполните команду cargo install sniffglue для установки Sniffglue при помощи этого менеджера пакетов или проверьте, установлен Snifglue, что должно произойти после установки Cargo.
~$ apt update Hit:1 http://archive.linux.duke.edu/kalilinux/kali kali-rolling InRelease Reading package lists... Done Building dependency tree Reading state information... Done 1759 packages can be upgraded. Run 'apt list --upgradable' to see them. ~$ apt install cargo Reading package lists... Done Building dependency tree Reading state information... Done The following package was automatically installed and is no longer required: libgit2-27 Use 'apt autoremove' to remove it. The following additional packages will be installed: libc-bin libc-dev-bin libc-l10n libc6 libc6-dbg libc6-dev libc6-i386 libgit2-28 locales locales-all Suggested packages: cargo-doc glibc-doc ... Setting up cargo (0.37.0-3+b1) ... Setting up libc6-i386 (2.29-3) ... Setting up libc-dev-bin (2.29-3) ... Setting up libc6-dev:amd64 (2.29-3) ... Processing triggers for man-db (2.8.5-2) ... Processing triggers for libc-bin (2.29-3) ... ~$ cargo install sniffglue Updating crates.io index error: binary `sniffglue` already exists in destination as part of `sniffglue v0.9.0` Add --force to overwrite
Теперь мы можем либо добавить Sniffglue в список путей или просто зайти в директорию, куда было установлено это приложение, и запустить напрямую. После запуска мы должны получить перечень команд с описанием, что свидетельствует об присутствии и готовности к запуску Sniffglue
~$ cd ~/.cargo/bin ~/.cargo/bin$ sudo ./sniffglue -h sniffglue 0.9.0 kpcyrd Secure multithreaded packet sniffer USAGE: sniffglue [FLAGS] [OPTIONS] [device] FLAGS: -d, --detailed Detailed output -h, --help Prints help information -j, --json Json output (unstable) -p, --promisc Set device to promisc -r, --read Open device as pcap file -V, --version Prints version information -v, --verbose Show more packets (maximum: 4) OPTIONS: -n, --cpus Number of cores ARGS:
Приступаем к прослушиванию сетевого интерфейса. Вначале находим имена сетевых карт:
~/.cargo/bin$ ip a | grep MULTICAST 2: enp2s0: mtu 1500 qdisc fq_codel state UP group default qlen 1000 3: wlp1s0: mtu 1500 qdisc noqueue state UP group default qlen 1000
Затем запускаем Sniffglue для сниффинга пакетов на нужном интерфейсе:
~/.cargo/bin$ sudo ./sniffglue enp2s0 Listening on device: "enp2s0" 50:7b:9d:7a:c8:8a -> 40:70:09:85:d1:a7, udp 192.168.0.37:57251 -> 209.18.47.62:53 dns req, (A, "null-byte.wonderhowto.com") 50:7b:9d:7a:c8:8a -> 40:70:09:85:d1:a7, udp 192.168.0.37:50381 -> 209.18.47.62:53 dns req, (AAAA, "null-byte.wonderhowto.com") 40:70:09:85:d1:a7 -> 50:7b:9d:7a:c8:8a, udp 209.18.47.62:53 -> 192.168.0.37:57251 dns resp, ("null-byte.wonderhowto.com", A(104.193.19.59)) 40:70:09:85:d1:a7 -> 50:7b:9d:7a:c8:8a, udp 209.18.47.62:53 -> 192.168.0.37:50381 dns resp,
В результате прослушивания Ethernet-карты (enp2s0) видные DNS-запросы к сайту Null Byte. Если бы мы подключились к LAN tap или Hak5 Packet Squirrel, то легко могли бы считать любой незашифрованный трафик, проходящий через кабель, к которому у нас есть доступ.
Далее переключаем внимание на беспроводную карту. Вначале, как и в предыдущем шаге, узнаем имя карты:
~/.cargo/bin$ ip a | grep MULTICAST 2: enp2s0: mtu 1500 qdisc fq_codel state DOWN group default qlen 1000 3: wlp1s0: mtu 1500 qdisc noqueue state UP group default qlen 1000
Затем в нашей системе запускаем Sniffglue с аргументом –d для более детального просмотра каждого запроса и аргументом –p для перевода карты в «неразборчивый» режим (promiscuous mode). В примере ниже я зашел на сайт «badsite.com» после начала сниффинга беспроводного трафика на карте wlp1s0.
~/.cargo/bin$ sudo ./sniffglue wlp1s0 -d -p Listening on device: "wlp1s0" eth: EthernetFrame { source_mac: MacAddress([48, 82, 203, 107, 118, 95]), dest_mac: MacAddress([64, 112, 9, 133, 209, 167]), ethertype: IPv4 } ipv4: IPv4Header { version: 4, ihl: 20, tos: 0, length: 73, id: 44379, flags: 2, fragment_offset: 0, ttl: 64, protocol: UDP, chksum: 52279, source_addr: 192.168.0.24, dest_addr: 209.18.47.62 } udp: UdpHeader { source_port: 43195, dest_port: 53, length: 53, checksum: 13395 } dns: Request(Request { questions: [(A, "googleads.g.doubleclick.net")] }) eth: EthernetFrame { source_mac: MacAddress([64, 112, 9, 133, 209, 167]), dest_mac: MacAddress([48, 82, 203, 107, 118, 95]), ethertype: IPv4 } ipv4: IPv4Header { version: 4, ihl: 20, tos: 0, length: 114, id: 51085, flags: 2, fragment_offset: 0, ttl: 57, protocol: UDP, chksum: 47324, source_addr: 209.18.47.62, dest_addr: 192.168.0.24 } udp: UdpHeader { source_port: 53, dest_port: 43195, length: 94, checksum: 33904 } dns: Response(Response { answers: [("googleads.g.doubleclick.net", CNAME("pagead46.l.doubleclick.net")), ("pagead46.l.doubleclick.net", A(172.217.14.66))] }) eth: EthernetFrame { source_mac: MacAddress([48, 82, 203, 107, 118, 95]), dest_mac: MacAddress([64, 112, 9, 133, 209, 167]), ethertype: IPv4 } ipv4: IPv4Header { version: 4, ihl: 20, tos: 0, length: 60, id: 45283, flags: 2, fragment_offset: 0, ttl: 64, protocol: UDP, chksum: 51388, source_addr: 192.168.0.24, dest_addr: 209.18.47.62 } udp: UdpHeader { source_port: 33734, dest_port: 53, length: 40, checksum: 35194 } dns: Request(Request { questions: [(AAAA, "www.google.com")] }) eth: EthernetFrame { source_mac: MacAddress([64, 112, 9, 133, 209, 167]), dest_mac: MacAddress([48, 82, 203, 107, 118, 95]), ethertype: IPv4 } ipv4: IPv4Header { version: 4, ihl: 20, tos: 0, length: 88, id: 41776, flags: 2, fragment_offset: 0, ttl: 57, protocol: UDP, chksum: 56659, source_addr: 209.18.47.62, dest_addr: 192.168.0.24 } udp: UdpHeader { source_port: 53, dest_port: 33734, length: 68, checksum: 49539 } dns: Response(Response { answers: [("www.google.com", AAAA(2607:f8b0:4007:80c::2004))] }) eth: EthernetFrame { source_mac: MacAddress([48, 82, 203, 107, 118, 95]), dest_mac: MacAddress([64, 112, 9, 133, 209, 167]), ethertype: IPv4 } ipv4: IPv4Header { version: 4, ihl: 20, tos: 0, length: 569, id: 20264, flags: 2, fragment_offset: 0, ttl: 64, protocol: TCP, chksum: 30553, source_addr: 192.168.0.24, dest_addr: 172.217.4.164 } tcp: TcpHeader { source_port: 46596, dest_port: 443, sequence_no: 766031290, ack_no: 3289351807, data_offset: 8, reserved: 0, flag_urg: false, flag_ack: true, flag_psh: true, flag_rst: false, flag_syn: false, flag_fin: false, window: 229, checksum: 42372, urgent_pointer: 0, options: None } tls: ClientHello { hostname: Some("www.google.com") } eth: EthernetFrame { source_mac: MacAddress([48, 82, 203, 107, 118, 95]), dest_mac: MacAddress([64, 112, 9, 133, 209, 167]), ethertype: IPv4 } ipv4: IPv4Header { version: 4, ihl: 20, tos: 0, length: 57, id: 45378, flags: 2, fragment_offset: 0, ttl: 64, protocol: UDP, chksum: 51296, source_addr: 192.168.0.24, dest_addr: 209.18.47.62 } udp: UdpHeader { source_port: 48260, dest_port: 53, length: 37, checksum: 40572 } dns: Request(Request { questions: [(A, "badsite.com")] }) eth: EthernetFrame { source_mac: MacAddress([64, 112, 9, 133, 209, 167]), dest_mac: MacAddress([48, 82, 203, 107, 118, 95]), ethertype: IPv4 } ipv4: IPv4Header { version: 4, ihl: 20, tos: 0, length: 89, id: 8256, flags: 2, fragment_offset: 0, ttl: 57, protocol: UDP, chksum: 24643, source_addr: 209.18.47.62, dest_addr: 192.168.0.24 } udp: UdpHeader { source_port: 53, dest_port: 48260, length: 69, checksum: 26142 } dns: Response(Response { answers: [("badsite.com", A(104.200.23.95)), ("badsite.com", A(104.200.22.130))] }) eth: EthernetFrame { source_mac: MacAddress([48, 82, 203, 107, 118, 95]), dest_mac: MacAddress([64, 112, 9, 133, 209, 167]), ethertype: IPv4 } ipv4: IPv4Header { version: 4, ihl: 20, tos: 0, length: 57, id: 45384, flags: 2, fragment_offset: 0, ttl: 64, protocol: UDP, chksum: 51290, source_addr: 192.168.0.24, dest_addr: 209.18.47.62 } udp: UdpHeader { source_port: 57772, dest_port: 53, length: 37, checksum: 61497 } dns: Request(Request { questions: [(AAAA, "badsite.com")] }) eth: EthernetFrame { source_mac: MacAddress([64, 112, 9, 133, 209, 167]), dest_mac: MacAddress([48, 82, 203, 107, 118, 95]), ethertype: IPv4 } ipv4: IPv4Header { version: 4, ihl: 20, tos: 0, length: 125, id: 46568, flags: 2, fragment_offset: 0, ttl: 57, protocol: UDP, chksum: 51830, source_addr: 209.18.47.62, dest_addr: 192.168.0.24 } udp: UdpHeader { source_port: 53, dest_port: 57772, length: 105, checksum: 44123 } dns: Response(Response { answers: [] }) eth: EthernetFrame { source_mac: MacAddress([48, 82, 203, 107, 118, 95]), dest_mac: MacAddress([64, 112, 9, 133, 209, 167]), ethertype: IPv4 } ipv4: IPv4Header { version: 4, ihl: 20, tos: 0, length: 371, id: 25136, flags: 2, fragment_offset: 0, ttl: 64, protocol: TCP, chksum: 38509, source_addr: 192.168.0.24, dest_addr: 104.200.23.95 } tcp: TcpHeader { source_port: 43706, dest_port: 80, sequence_no: 3479674440, ack_no: 2159468974, data_offset: 8, reserved: 0, flag_urg: false, flag_ack: true, flag_psh: true, flag_rst: false, flag_syn: false, flag_fin: false, window: 229, checksum: 33053, urgent_pointer: 0, options: None } http: "GET http://badsite.com/ HTTP/1.1" Request { method: "GET", uri: "/", version: "1.1", host: Some("badsite.com"), agent: Some("Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0"), referer: None, auth: None, cookies: None } eth: EthernetFrame { source_mac: MacAddress([64, 112, 9, 133, 209, 167]), dest_mac: MacAddress([48, 82, 203, 107, 118, 95]), ethertype: IPv4 } ipv4: IPv4Header { version: 4, ihl: 20, tos: 0, length: 1040, id: 62478, flags: 2, fragment_offset: 0, ttl: 53, protocol: TCP, chksum: 3314, source_addr: 104.200.23.95, dest_addr: 192.168.0.24 } tcp: TcpHeader { source_port: 80, dest_port: 43706, sequence_no: 2159468974, ack_no: 3479674759, data_offset: 8, reserved: 0, flag_urg: false, flag_ack: true, flag_psh: false, flag_rst: false, flag_syn: false, flag_fin: true, window: 235, checksum: 55524, urgent_pointer: 0, options: None } remaining: "HTTP/1.1 302 Found\r\nServer: openresty/1.13.6.1\r\nDate: Mon, 24 Jun 2019 11:52:24 GMT\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 0\r\nConnection: close\r\nLocation: http://www6.badsite.com/?s_token=1561377144.1272041333&kw=Best+Personal+Credit+Cards&term=Best%20Personal%20Credit%20Cards&term=Fast%20Online%20College%20Degrees&term=Job%20Posting%20Boards&term=Movie%20Media%20Server&backfill=0&tdfs=1\r\nX-Mtm-Path: 0\r\nVary: Accept-Language\r\nContent-Language: en\r\nSet-Cookie: mtm_delivered=WyJiYWRzaXRlLmNvbSIsImh0dHA6Ly93d3c2LmJhZHNpdGUuY29tLz9zX3Rva2VuPTE1NjEzNzcxNDQuMTI3MjA0MTMzMyZrdz1CZXN0K1BlcnNvbmFsK0NyZWRpdCtDYXJkcyZ0ZXJtPUJlc3QgUGVyc29uYWwgQ3JlZGl0IENhcmRzJnRlcm09RmFzdCBPbmxpbmUgQ29sbGVnZSBEZWdyZWVzJnRlcm09Sm9iIFBvc3RpbmcgQm9hcmRzJnRlcm09TW92aWUgTWVkaWEgU2VydmVyJmJhY2tmaWxsPTAmdGRmcz0xIiwxLCIyMDE5LTA2LTI0IDExOjUyOjI0IiwiMTU2MTM3NzE0NC4xMjcyMDQxMzMzIiw3NCxudWxsLG51bGxd:1hfNWK:v7-Oji2CCHg8ECfi3-6CthImT5w; expires=Mon, 24-Jun-2019 12:52:24 GMT; Max-Age=3600; Path=/\r\n\r\n"
Всего за несколько секунд прослушивания трафика я узнал об операционной системе, отправляющей запрос, запрашиваемый сайт и даже ответ от сайта, закодированный в HTML. Я даже могу видеть поисковую систему, используемую по умолчанию, для выполнения этого запроса.