从 posix_spawn() 函数窥探漏洞逃逸
posix_spawn() 函数是用来在Linux上创建子进程的,头文件是 #include <spawn.h> ,语法如下:
#include <spawn.h>
int posix_spawn(pid_t *pid, const char *path,
const posix_spawn_file_actions_t *file_actions,
const posix_spawnattr_t *attrp,
char *const argv[], char *const envp[]);
我们可以看到一共要传入六个参数,语法参数说明如下:
- 子进程 pid(pid 参数指向一个缓冲区,该缓冲区用于返回新的子进程的进程ID)
- 可执行文件的路径 path(其实就是可以调用某些系统命令,只不过要指定其完整路径)
- file_actions 参数指向生成文件操作对象,该对象指定要在子对象之间执行的与文件相关的操作
- attrp 参数指向一个属性对象,该对象指定创建的子进程的各种属性。
- argv 和 envp 参数指定在子进程中执行的程序的参数列表和环境
详细文档可以通过 man posix_spawn 查看相关文档:

既然我们知道了这些参数,我们该如何利用这个呢?
我们先给一个 Demo 看看:
/*
* @Author: python
* @Date: 2020-01-12 17:28:31
* @Last Modified by: python
* @Last Modified time: 2020-01-12 17:32:28
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <spawn.h>
#include <sys/wait.h>
/*
int posix_spawn(pid_t *pid, const char *path,
const posix_spawn_file_actions_t *file_actions,
const posix_spawnattr_t *attrp,
char *const argv[], char *const envp[]);
*/
extern char **environ;
void run_cmd(char *cmd)
{
pid_t pid;
char *argv[] = {"sh", "-c", cmd, NULL};
int status;
printf("Run command: %s\n", cmd);
status = posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ);
if (status == 0) {
printf("Child pid: %i\n", pid);
if (waitpid(pid, &status, 0) != -1) {
printf("Child exited with status %i\n", status);
} else {
perror("waitpid");
}
} else {
printf("posix_spawn: %s\n", strerror(status));
}
}
int main(int argc, char* argv[])
{
run_cmd(argv[1]);
return 0;
}
运行结果如下图所示:

我们从结果可以看到,/bin/sh 的效果就类似于 sh 脚本中开头的 #!/bin/sh,指定了系统命令 sh 的路径,argv 就类似于 shell 脚本中要执行的代码,比如这里执行 sh -c cmd,而 cmd 参数由用户输入。
我们以 xman 第三界冬令营选拔赛 shellmaster 为例,由于环境已经宕机了,所以我找出题人拿到了源码,有兴趣的可以尝试用源码重新复现一下环境。
import os
import sys
import time
blacklist = [
"$",
"-",
"_",
"{",
"}",
"*",
"2",
"4"
]
def handler():
print "Oops, are you a master?"
os._exit(0)
print "Welcome to shell master!"
print "Start to wake up the shell ..."
time.sleep(3)
sys.stdout.flush()
while True:
sys.stdout.write("master@ubuntu:~$ ")
sys.stdout.flush()
cmd = raw_input().upper()
'''
for i in blacklist:
if i in cmd:
print "blacklist: "+i
handler()
if len(cmd) > 16:
print "len:"+len(cmd)
handler()
'''
cmd += " 2>&1"
print os.system(cmd)
我们从源码可以看到,输入的命令中所有字母都被替换成了大写字母,所以你如果通过 nc 连接之后,会发现无论输入什么命令,你会发现输入的所有字母都被替换成了大写字母,没法进行任何操作。
在这里,我们不得不提到一个有意思的东西,$0。
这个 $0 是什么东西呢,我们可以尝试打印一下:

我们可以看出,$0 事实上就是调用当前的 shell 了,是不是都是这样呢?
我们尝试自己写个例子看看:

我们可以看到,执行并且测试以后,发现输出的结果正好是当前脚本的名字,当前的 $0 就是 ./test.sh。
我们从以上这个例子可以看出,在 shell 脚本中,通过使用 $0 就可以获取到脚本的名字或者说脚本本身。
既然这玩意能直接调用当前的 shell,利用方式就有很多种了。
我们可以通过 posix_spawn 这个函数,创建一个子进程,这个子进程可以是系统的默认的命令(进程实质上就是一个程序嘛),这个子进程如果调用的是当前的 shell,我们就可以直接利用这个 shell 来获取相关权限的信息,从而实现逃逸这一过程。
我们可以尝试通过系统的一些方法传入 $0 来实现逃逸这一过程。
那我们既然已经知道了这一点,我们就可以尝试去
那么什么时候会调用
posix_spawn函数?由于
posix_spawn函数是C语言中system.c创建线程默认调用的功能模块。
C 源码官方下载:http://ftp.gnu.org/gnu/libc/,定义 system 的 c 文件在 glibc/sysdeps/posix/system.c,当然我们也可以在 https://code.woboq.org/userspace/glibc/sysdeps/posix/system.c.html 在线查看。
到这里为止,我们基本思路已经很清楚了,我们可以通过使用 system 模块来调用 posix_spawn 函数来创建子进程,让这个子进程调用当前的 shell,也就是使用 $0 ,然后获取到相关的权限信息,实现逃逸这一过程。我们可以直接写相关的 C 程序来解决。
而在 python 中,os.system 是通过调用 C 语言中的 system 函数来实现其功能的:

详细文档可以参考:https://docs.python.org/3/library/os.html
于是我们就可以进行如下更加简便的操作:
- 先调用 os.system 调用 C 语言中的 system 函数

- 然后执行 system 模块中的 posix_spawn 函数

- 最后调用当前的 shell

这道题目如果没有屏蔽掉黑名单的话,还是有其他解题思路的,可以直接通过通配符来解决问题,payload 如下:
/???/???/?38?
从 posix_spawn() 函数窥探漏洞逃逸的更多相关文章
- Memcached‘do_item_get’函数安全漏洞
漏洞名称: Memcached‘do_item_get’函数安全漏洞 CNNVD编号: CNNVD-201401-175 发布时间: 2014-01-15 更新时间: 2014-01-15 危害等级: ...
- Memcached‘process_bin_delete’函数安全漏洞
漏洞名称: Memcached‘process_bin_delete’函数安全漏洞 CNNVD编号: CNNVD-201401-174 发布时间: 2014-01-15 更新时间: 2014-01-1 ...
- PHP ‘scan’函数拒绝服务漏洞
漏洞名称: PHP ‘scan’函数拒绝服务漏洞 CNNVD编号: CNNVD-201311-464 发布时间: 2013-12-06 更新时间: 2013-12-06 危害等级: 中危 漏洞类型 ...
- Linux Kernel‘ieee80211_radiotap_iterator_init()’函数拒绝服务漏洞
漏洞名称: Linux Kernel‘ieee80211_radiotap_iterator_init()’函数拒绝服务漏洞 CNNVD编号: CNNVD-201312-041 发布时间: 2013- ...
- WordPress ‘get_allowed_mime_types’函数安全漏洞(2)
漏洞名称: WordPress ‘get_allowed_mime_types’函数安全漏洞 CNNVD编号: CNNVD-201309-169 发布时间: 2013-09-13 更新时间: 2013 ...
- WordPress ‘get_allowed_mime_types’函数安全漏洞
漏洞名称: WordPress ‘get_allowed_mime_types’函数安全漏洞 CNNVD编号: CNNVD-201309-170 发布时间: 2013-09-13 更新时间: 2013 ...
- Linux kernel ‘fib6_add_rt2node’函数安全漏洞
漏洞名称: Linux kernel ‘fib6_add_rt2node’函数安全漏洞 CNNVD编号: CNNVD-201307-265 发布时间: 2013-07-16 更新时间: 2013-07 ...
- Linux kernel ‘ip6_sk_dst_check’函数拒绝服务漏洞
漏洞名称: Linux kernel ‘ip6_sk_dst_check’函数拒绝服务漏洞 CNNVD编号: CNNVD-201307-070 发布时间: 2013-07-05 更新时间: 2013- ...
- Linux Kernel KVM 'apic_get_tmcct()'函数拒绝服务漏洞
漏洞版本: Linux Kernel 漏洞描述: Bugtraq ID:64270 CVE ID:CVE-2013-6367 Linux Kernel是一款开源的操作系统. Linux KVM LAP ...
随机推荐
- supersockets单个 listener
在下面的配置中,你可以配置服务器的监听 ip/port: <superSocket> <servers> <server name="TelnetServer& ...
- Element-ui学习笔记3--Form表单(一)
Radio单选框 要使用 Radio 组件,只需要设置v-model绑定变量,选中意味着变量的值为相应 Radio label属性的值,label可以是String.Number或Boolean. & ...
- 运行项目npm run dev时报错: ~Error: Cannot find module 'webpack-cli/bin/config-yargs', 原因是
webpack@3.X运行项目npm run dev时报错: ~Error: Cannot find module 'webpack-cli/bin/config-yargs' 我的原因是: web ...
- linux的iptables和firewall的区别
firewall是centos7里面的新的防火墙命令,它底层还是使用 iptables 对内核命令动态通信包过滤的,简单理解就是firewall是centos7下管理iptables的新命令 Linu ...
- Django入门7--博客撰写页面开发
- Wannafly挑战赛15 C“出队”(约瑟夫环类问题)
传送门 •参考资料 [1]:浅梦无痕 [2]:Esquecer [3]:My CSDN •题意 n 个人围成一圈,1,2 报数,报 1 的离队,求编号为 x 的第几次出队: •对博文[1]的理解 第一 ...
- tensorflow在文本处理中的使用——TF-IDF算法
代码来源于:tensorflow机器学习实战指南(曾益强 译,2017年9月)——第七章:自然语言处理 代码地址:https://github.com/nfmcclure/tensorflow-coo ...
- linux /proc 接口
无论何时一个硬件中断到达处理器, 一个内部的计数器递增, 提供了一个方法来检查设备 是否如希望地工作. 报告的中断显示在 /proc/interrupts. 下面的快照取自一个双处理 器 Pentiu ...
- CF161BDiscounts
CF161B 题目大意;要购买\(n\)件物品,有\(A\)\(B\)两种类型,要求分成\(k\)组,其中如果其中一组含有\(A\)类物品,那么这一组最便宜的一件物品就会半价 怎么分组最小化代价? 我 ...
- 阿里云基于OSS的云上统一数据保护方案2.0正式发布
近年来,随着越来越多的企业从传统经济向数字经济转型,云已经渐渐成为数据经济IT新常态.核心业务系统上云,云上的业务创新,这些都产生了大量的业务数据,这些数据也成为了企业最重要的资产.资源.阿里云基于O ...