专栏首页FreeBuf照弹不误:出站端口受限环境下反弹Shell的思考

照弹不误:出站端口受限环境下反弹Shell的思考

“是否允许出站”这件事我一直以为无需过多思考,无非限制出站协议,或者限制出站端口,对于限制端口的目标十有八九也会保留 80、443,向这两个端口反弹基本能拿到 shell,直到遇到这个目标,引发我对出站端口受限的环境下,如何成功反弹 shell 的思考。

这次遇到的目标,通过 nday 轻松拿到 webshell,打点的过程毫无波澜,甚至有一丝无聊:

webshell 虽然赋予我执行命令、管理文件的能力,但毕竟不是真正的 shell,无法执行交互式命令、无法控制进程状态、无法补全命令等等,非常不利于提权操作以及横向移动,所以,必须反弹 shell。

肌肉记忆让我没有过多思考,攻击端监听端口 12321:

目标上执行反弹命令:

等待许久,攻击端就是不见回连信息,显然,一定是目标上的某种防御在作祟。导致反弹失败的因素很多,反弹命令不存在、禁止出站 IP、流量审查等等都有可能,于是,我从积累的知识库中搜索所有可能,再逐一验证。比如,我在目标上确认 bash 命令的确存在:

在攻击端能收到目标发起的 ping 探测,攻击端能收到 icmp 记录:

用 SSL 加密回连流量仍然反弹失败:

我陷入沉思,这台内网机器,既然公网可见,说明它的边界处有个防火墙作公网 IP 映射:

一般来说,防火墙可能干两件事,一是限制出站协议、一是限制出站端口。协议方面,前面已经验证过 ICMP 可以出网而 HTTP 不行,所以,我可以尝试用 ICMP 隧道反弹,即便可行,效率肯定也不高;端口方面,目标通过防火墙配置出站端口策略,若限制端口黑名单较大或允许端口白名单较小,则攻击者很难猜测出哪些端口有效。从以往的经验判断,80、443 是两个可能性较大的允许出站的端口,于是我又依次尝试向 80、443 反弹,失败!

捋一捋,通过漏洞获取了 webshell,该主机只开放了 HTTP 服务的 80 端口,要获得 shell 有两种方式,正向连接、反向连接。正向连接,目标上用 nc 监听的端口对攻击端不可见,只得利用类似 reGeorg 建立 HTTP 隧道;反向连接,目标上用 nc 回连攻击端 IP 及端口。前者效率低下,聚焦后者,目标允许向外访问任意 IP,但严格限制只能访问外部某几个特定端口,攻击者必须找出有效端口,否则反弹 shell 的流量无法通过防火墙到达攻击端。所以,我需要猜解出站端口。

猜解出站端口,思路与 SQLi 或 CMDi 盲注的带外信道手法差不多,即,攻击端监听某个端口,目标访问攻击端的该端口,若攻击端出现端口访问记录则说明该端口是目标允许的出站端口。思路简单,但实现不一定容易,要成功猜解出有效端口,需要关注三方面事宜:目标的端口探测命令、猜测的端口范围、攻击端的端口请求记录。

目标的端口探测命令

说到端口状态探测,第一时间想到的肯定是 nmap、masscan、nc 这类专用工具。看下目标上有没有:

毫无悬念地没有;自己装个 masscan 试试:

权限又不够,即便有权限,估计也连接内网的镜像源;那我上传个与目标架构、发行套件一致的 nmap 呢:

缺失依赖出现段错误而无法运行。

没事,除了以上那些专用工具外,linux 中还有其他挺多可选的方式,可以利用 python、perl各类脚本语言探测端口,也能借助 curl、wget 这类 HTTP 客户端实现,只要能请求服务的命令均可,但是,环境就是那么苛刻,我要啥它没啥:

好嘛,这时,我觉得基本无解,不借助第三方命令不可能达到端口探测的目的。休息一会,是喝口水去打乒乓球哇,还是去打乒乓球喝口水呢。回过头,检查之前的反弹命令是否有误:

突然,我注意到 /dev/tcp 后面的 12321 端口,( ⊙ o ⊙ )#,这不就是在探测端口么。一切皆文件!linux 下探测端口状态竟如此简单,比如,探测 baidu.com 的 443 端口,一定存活:

但由于这不是专门的端口探测工具,所以存在三个问题,一是如何批量输入端口,二是如何控制任务超时,三是如何查看探测结果。于是,我开始在本地探索解决思路。

批量端口问题。这个不难,使用 bash 的 for 语句即可:

若目标过滤大括号,可考虑:

若目标过滤小于号,可考虑:

甚至无需任何特殊字符:

解决了第一个问题。

超时控制问题。当我用 /dev/tcp 去探测某个存在的端口时,命令将立即返回,而探测某个不存活端口时,命令将挂起,直到强制退出:

所以,必须得想个法子让它超时时自动结束。超时,timeout,哇,这么简单啊。比如,本来要执行 8s 的命令:

借助 timeout命令可以实现超时控制:

第二个问题搞定。

查看探测结果。你知道,在 bash 中命令执行结果可以通过环境变量 ? 查看,成功为 0、是否非 0,换言之,我需要找个方式判断 ? 是否为 0,常规方式用 if 语句,或者,更优的方式,短路运算符 && 和 ||:

第三个问题也不是问题了。

解决了以上三个问题,我在不借助任何外部命令情况下,实现了批量探测端口:

虽然这次关于出站端口探测的思考是由 linux 的目标引起的,但从知识体系完整性考虑,我应该把 windows 系统也考虑进去。windows 命令行环境条件苛刻,几乎没有专门用于端口探测的内部命令,只能借助那些访问服务的命令间接实现,另外,我仍然需要解决批量端口、超时控制等问题。

批量输入端口,cmd 中的 for 语句可以实现:

控制任务超时,linux 有 timeout 命令,本质上,一旦超时则向目标进程发送 KILL 信号,达到控制进程运行时长的目的。win 也有 timeout,但语义完全不同,类似 linux 的 sleep 命令,没关系,参考 linux 版 timeout 原理,搭配 taskkill 命令也能间接实现:

其中,ping -n 32 127.0.0.1 模拟长时间运行的进程,timeout /t 1 为等待时长,一旦等待时长到期则用 taskkill /im ping.exe 杀死进程。虽然不及 linux 优雅,聊胜于无。

具体到端口探测,大概有 tnc 模块和 telnet 命令两种方式。

tnc 模块方式。tnc 也就是 powershell 的 Test-NetConnection 模块,专门用于网络连接性测试:

其中,tnc 默认先用 ICMP 探测 IP 存活性,通过指定 -InformationLevel 选项为 Quiet 参数,可忽略 IP 探测,只关注端口是否存活,类似 nmap 的 -Pn 选项,以提高端口探测效率。

telnet 命令方式。服务器上基本安装了 telnet,也可用于探测端口状态:

用 telnet 命令访问攻击端的 [440, 445] 的端口,每次访问限时 1s。

猜测的端口范围

目标既然允许访问外部的几个端口,一定是那些端口提供目标所需服务,那么,我没必要一开始就到 [1, 65535] 中去找有效端口,而是根据服务的常见程度,将所有端口划为几个层次,依次逐层猜解。

第一层,最常见端口。经验来看,DNS 的 53、HTTP 服务的默认端口 80、HTTPS 的 443 是三个最常见的出站端口。

win 下执行如下命令行确认出站端口:

linux 下执行:

第二层,较常见端口。大概包括如下几类:

web 服务, HTTP 的 80、HTTPS 的 443; 中间件服务,weblogic 的 7001/7002、webshpere 的 9080/9090、jboss 的 8080; 远程管理服务,SSH 的 22、telnet 的 23、SNMP 的 161、RDP 的 3389; 数据传输服务,FTP 的 21、SCP/SFTP 的 22、SMB 的 137/138/139/445; 数据库服务,mssql 的 1433、mysql 的 3306、oracle 的 1521、LDAP 的 389; 缓存服务,redis 的 6379、memcached 的 11211; 邮件服务,SMTP 的 25、POP3 的 110、IMAP 的 143; 其他服务,DNS 的 53、NTP 的 123、kerberos 的 88;

win 下探测:

linux 下探测:

第三层,top100 常见端口。nmap 默认扫描 top1000 常见端口,通过 —top-ports 选项可以指定扫描更多常见端口:

也就是说,nmap 内部梳理了一份已知服务默认端口列表,并且还能按常见程度排序,简直巴适,要获取 top100 常见端口:

win 下探测:

linux 下探测:

采用相同思路,我可以持续探测 top200、top400 常见端口。

攻击端的端口请求记录

从目标发起的端口访问请求,攻击端必须得配合记录,否则即便找到有效的出站端口,我也无法获悉。

思路一,单个逐次监听端口。对于少量端口的探测,攻击端很容易记录。比如,要验证 windows 目标的 8088 端口是否为出站端口,我先在攻击端用 nc -n -v -lp 8088 监听 8088,指定 -v 选项观察实时访问记录,再在目标上用 telnet 192.168.56.8 8088 连接攻击端的 8088 端口,最后在攻击端查看端口访问记录,若有则该端口是有效出站端口:

若无则重复以上步骤继续验证其他端口。

对于 top100 甚至 top1000 这样大规模的端口探测,当前验证目标的 80 端口,那么攻击端也要联动监听 80,验证 81 则联动监听 81,手工执行 nc 不断监听不同端口是不现实的,这就需要一个脚本,控制攻击端的监听动作和目标端的探测动作,倒是可以写个这样的脚本,但通用性不强,我得找寻更加普适性的方法。

思路二,批量捆绑监听端口。试想一下,如果能够把攻击端的多个端口流量转发至单个汇聚端口,就只需监听单个汇聚端口,目标上发起多个端口探测,只要在攻击端转发的多个端口的范围内,那么,一旦找到有效出站端口,攻击端的汇聚端口一定有访问记录。说到端口转发,系统自带的 ssh、iptables,三方的 frp、nps,这些工具都能高效实现,于是,我从这四个工具中找寻具备端口捆绑能力的那位,简单查阅资料,iptables 就是我需要的。只需一条命令行即可实现端口捆绑,如下:

sudo iptables -A PREROUTING -t nat -p tcp --dport 1:65535 -j REDIRECT --to-port 4442

这样,就把 65535 个全量端口捆绑至 4442 端口。

验证下,在攻击端将全量端口捆绑至 4442 端口:

监听 10086 端口:

靶机目标取消所有出站限制,访问攻击端的 10086 端口:

显示端口不存活!这正是端口捆绑的必然结果,因为攻击端接收到的 10086 端口访问流量已被转发至 4442 端口,而 nc 并未监听 4442,所以没有访问记录。接下来,nc 监听 4442:

目标端再次访问 10086:

你看,攻击端收到访问记录了:

验证完毕,不再需要端口捆绑,恢复先前规则:

安逸哇,这样我监听单个端口即可获取全量端口的探测记录。如果再结合结合 MSF 的 reverse_tcp_allports 载荷,甚至可以省去找寻有效端口的步骤,直接反弹 shell。

windows 环境的模拟实验

简单模拟实战中反弹 shell 的场景。先看 windows 环境。

第一步,查看环境信息。靶机 IP 为 192.168.56.9,如下:

攻击端 IP 为 192.168.56.8,如下:

第二步,配置出站策略。在操作系统自带防火墙中增加出站策略,只允许 2048 端口出站,即禁止 1-2047 及 2049-65535,规则管理界面中配置即可:

攻击端监听 2047 端口:

从目标访问攻击端的 2047 端口,结果为不存活:

攻击端重新监听 2048 端口:

从目标访问攻击端的 2048 端口,结果为存活:

说明只放行 2048 端口的出站策略已生效。

第三步,攻击端端口捆绑。为了便于接收目标发起的端口探测,将攻击端的全量端口捆绑至 4442 端口:

并在攻击端监听汇聚端口 4442:

第四步,目标端猜解出站端口。现在,我的身份恢复为攻击者,假定先前通过漏洞拿到目标 192.168.56.9 的命令执行权限,且执行结果有回显。尝试在 nmap 定义的 top100 常见端口范围内找寻允许出站的端口,很快找到 2048 为有效端口:

第五步,反弹 shell。首先,攻击端取消端口捆绑:

然后,攻击端生成反弹端口为 2048 的 ps1 脚本木马:

并启动 MSF 监听 2048 端口:

接着目标上执行 ps1 木马:

最后顺利反弹 shell:

拿下真实目标

现在,我把本地推演的思路应用到目标环境中。

第一步,攻击端捆绑端口至 12321,并监听该端口:

第二步,目标上探测 top100 常见端口,执行:

啊( ⊙ o ⊙ )啊!居然报错,不应该,难道是 webshell 中无法执行复杂的 shell 语句?不急,把它写入个脚本文件中执行看看,新建脚本文件 x.sh:

写入完整命令行:

赋予执行权限后执行:

很快即可查看到结果:

无一存活!

第三步,继续尝试 top200、top300 的端口,仍然没找到;尝试 top400:

哈哈哈哈,还真找到了它,42510,唯一允许出站的那个端口!

第四步,反弹 shell。攻击端取消端口捆绑,监听 42510 端口接收 shell:

目标向攻击端的 42510 端口反弹:

攻击端成功接收 shell:

呵呵,这下心情舒畅了,晚上整火锅。

好了,以后遇到能 ping 通外网但无法反弹的目标,得多个心眼考虑是否限制了出站端口,用上述手法尝试猜解,或许,能找到唯一的答案!

*本文原创作者:yangyangwithgnu,本文属于FreeBuf原创奖励计划,未经许可禁止转载

本文分享自微信公众号 - FreeBuf(freebuf),作者:yangyangwithgnu

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 等保测评2.0:Windows入侵防范

    这一条比较容易理解。即仅安装该服务器需要的组件和应用程序,非必需的组件和应用程序应该删除或者停用。

    FB客服
  • 浅谈内网端口转发

    在渗透测试过程中,我们经常会用到端口转发,利用代理脚本将内网的流量代理到本地进行访问,这样极大的方便了我们对内网进行横向渗透。最常见的端口转发工具不限于以下几款...

    FB客服
  • 使用Egressbuster测试防火墙出站规则

    我已经使用Egressbuster有段时间了。从我的使用体验来讲Egressbuster非常的实用,因此我想在这里把它介绍给大家。 Egressbuster -...

    FB客服
  • 3389管理器怎么管理端口?

    iis7远程桌面小编在开始讨论什么是端口之前,让我们先讨论一下什么是端口?我经常在Internet上听到我的主机打开了多少个端口,这些端口会被入侵!或者说“打开...

    it妹
  • TCPView for Windows

    TCPView是一个用来显示系统中所有的TCP和UDP端点(endpoint)列表的Windows程序,包括本地和远程的网络地址,以及TCP连接的状态。在Win...

    张善友
  • 端口聚合和端口汇聚的区别

    端口聚合和端口汇聚这两个词看起来意思是一样的,但是实际含义却有差着十万八千里,所以我们在使用iis7监控工具之前之前,有必要了解一下什么是端口聚合和端口汇聚

    it妹
  • wordpress建站我们需要开放服务器的哪些端口?

    我们在购买了vps云服务器的时候,经常会发现安装网站之后打不开,无法访问,这其中容易被忽视的一个步骤就是服务器端口和安全组开放的问题。

    wordpress建站吧
  • Meterpreter 端口转发

    如何转发无法远程访问的本地端口。在本地计算机上运行特定服务。在本地网络上,这些服务通常是用于在本地计算机上访问,外网是不能访问的,比如MySQL服务器。出于安全...

    周俊辉
  • 计算机网络自学笔记:路由器工作原理

    ·输入端口。输入端口要执行将一条输入的物理链路端接到路由器的物理层功能。它也要执行需要与位于入链路另一端接口交互的数据链路层功能。它还要完成转发表查找与转发功能...

    云时之间
  • Windows基础 | 学员笔记

    HACK学习

扫码关注云+社区

领取腾讯云代金券