удаленное чтение памяти через TCP/ICMP

В bugtraq’e, пестрящем в нынешние времена всякой малозначительной и не всегда соответсующей действительности ерундой, какими-то дырами в мало кому известных продуктах, иногда появляются забавные постинги, представляющие, правда, скорее академический, нежели «шкурный», практического свойства интерес. Вот как раз о таком «открытии» пойдет речь в этой небольшой заметке.

Есть возможность читать некоторые данные из памяти удаленной машины. Возьмем, для примера, следующий код, заполняющий достаточно большой кусок памяти буквами “А”:

int main(int argc, char **argv[], char **envp[]) { char *ptr=0;  int val, i; while(1) { sleep(1); val = 30000000; ptr = (char *)malloc(val); memset(ptr, 0x41, val-1); free(ptr); } }

Затем модифицируем всем нам знакомый nmap таким образом, чтобы в рамках фрагментированного сканирования он передавал в сеть только первый фрагмент данных (копаемся где-то в районе 687 строчки кода). Направив такой пакет, например, на нейкий Linux, в ответ получим сообщение ICMP TTL Exceeded. Поскольку Linux включает в такие пакеты намного больше данных, чем другие системы, нам досталось аж целых 20 байт “познавательного” чтения. Глядим в snort:

12/11-00:34:34.290903 127.0.0.1 -> 127.0.0.1 ICMP TTL:255 TOS:0xC0 ID:29812 TTL EXCEEDED 00 00 00 00 45 00 00 24 A2 15 20 00 3E 06 BC BC ....E..$.. .>... 7F 00 00 01 7F 00 00 01 E1 C1 01 91 FB 73 6B E2 .............sk. 00 00 00 00 50 02 08 00 41 41 41 41 41 41 41 41 ....P...AAAAAAAA 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAA
12/11-01:02:30.170720 127.0.0.1 -> 127.0.0.1 CMP TTL:255 TOS:0xC0 ID:31185 TTL EXCEEDED 00 00 00 00 45 00 00 24 32 25 20 00 3B 06 2F AD ....E..$2% .;./. 7F 00 00 01 7F 00 00 01 AA 1E 01 11 50 FE C6 45 ............P..E 00 00 00 00 50 02 08 00 41 41 41 41 41 41 41 41 ....P...AAAAAAAA 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAA

Чтобы убедиться, что это не глюки snort’а, а мы действительно получили искомые «AAAAA…», самопроверимся с помощью tcpdump:

01:06:02.640246 lo < 127.0.0.1 > 127.0.0.1: icmp: ip reassembly time exceeded [tos 0xc0] 45c0 0054 7b85 0000 ff01 4161 7f00 0001 7f00 0001 0b01 77a3 0000 0000 4500 0024 d3e5 2000 3306 95ec 7f00 0001 7f00 0001 c027 055a 5fa5 73a5 0000 0000 5002 0800 4141 4141 4141 4141 4141 4141 4141 4141

 

уязвимые системы

Сдается мне, что эта проблема характерна для любой системы, содержащей в себе хоть что-нибудь помимо стека TCP/IP :)

применение

Находки, полученные таким образом, могут оказаться просто шикарными: фрагменты shadow-файла, различные пароли в plain-text, куски кода, URL’ы да мало ли что еще там в памяти болтается…

как с этим бороться

Хмм… универсальных рецептов и патчей вы от меня не дождетесь, но вот что могу посоветовать: 1.Блокировка памяти для важных для жизни системы вещей, паролей например. 2.Модификация ядра таким образом, чтобы во время простоя затиралась неиспользуемая память. 3.Можно написать маленькую программку, вроде той, что использовалась в нашем примере, которая забивает неиспользуемую память нулями. 4.Внести исправление в код реализации сети, дабы незначимые «хвосты» в пакетах обнулялись. Это, правда, наверняка замедлит работу, плюс к тому упростит удаленную идентификацию вашей ОС – по одной пробе будет видно, что у вас Linux :) 5.Фильтровать различные ICMP-сообщения, но делать это надо с умом, как бы вообще все не попортить.

Комментарий Fyodor'а*: Попробую угадать, что произошло в этом конкретном случае: после того, память из разделяемого сегомента была освобождена (free()) в пользовательской зоне, она вернулась в область ядра и была заново распределена. В тот момент, когда формировалось ICMP-сообщение, участок памяти просто еще не был инициализирован. Таким образом огрызки данных, что там сидели, остались в пакете. Сомневаюсь, что в содержимом таких пактов вы сможете обнаружить что-то действительно ценное.Приложения. работающие с защищенными паролями (shadow), криптографическими ключами и паролями просто обязаны блокировать память и зачищать участки памяти после освобождения! В противном случае вы можете получить всю эту радость не даже не прибегая к вышеописанным «пакетным ухищрениям», но просто локально – через malloc().

Комментарий редактора:Ну что тут сказать… Нам в редакции не удалось реконструировать эксперимент Эндрю, однако было бы интересно узнать, получилось ли у кого-нибудь добыть таким образом что-то мало мальски интересное. Если у вас получится – обязательно пишите – мылом или на веб (в конференцию письма читателей)

* для тех, кто не в курсе: Федор (Fyodor) известен главным образом как автор знаменитого сканера nmap


Andrew Griffiths



Сетевые решения. Статья была опубликована в номере 01 за 2002 год в рубрике технологии

©1999-2024 Сетевые решения