Skip to content

实战

前言

如果没有丰富的红队经验, 可能看完关于gogo的功能细节的介绍也无法完全理解那一长串的解释.

接下来将会结合一些红队常见的场景去介绍gogo如何成为红队人员的衍生的"手与大脑"

基本场景

场景1 从webshell 入口开始

这应该是红队与hw中最常见的场景.

拿到一个webshell之后, 除去被动信息收集, 接下去就要在内网开始横向了, hw中大部分目标并没有非常强的防护. 这种情况下, 大规模扫描才是一个可接受的选项.

如果是一些同类工具, 可能能做的只有指定一个b段, 然后等扫描结束收菜.

而gogo, 在这里能可以体验到高度可控对扫描行为的改变.

以一个内网ip地址为172.16.2.2的webshell 为例.

第一步 对当前c段进行探测

一般来说, 存在对外web服务的网段在子网规划时都至少会划分一个C段, 如果不是, 可以通过查看当前网络配置进行修改.

而同一个网段(vlan)之内的流量是很难部署探针或者将流量镜像到安全设备. 绝大部分情况都是在流量的出入口, 也就是交换机之间部署防火墙, 或者在核心交换机上做流量镜像. 因此, 对自身所在网段的扫描是一个相对安全的选择

当然, 如果存在edr, hids, rasp等在终端上的设备, 或者存在大量的内网蜜罐. 我们的扫描行为还是有可能被监控到. 不过考虑到使用gogo的对象,大多数不具备较强的网络防护能力, 这种风险还是可以接受的.

并且这种edr, hids,rasp对高并发流量并不敏感, 而蜜罐也几乎每时每刻都发生着各种误报. 理论上任意的syn包就能触发告警, 在实际上实践中, 这种相对低危的告警会被防守人员忽略.

因此, 这时候, 扫描可以稍微大胆一些.

gogo -i 172.16.2.1/24 --af

--af为自动生成文件名, 并将扫描结果导出到该文件中.

当然也可以手动指定文件名 gogo -i 172.16.2.1/24 -f 1.dat

这么做的原因是, webshell很可能接受不了大量log输出, 导致卡死. 并且导出到文件是一个鼓励将文件下载回来离线保存, 并用作后续分析处理的行为.

输出的文件是deflate压缩的, 需要使用gogo -F 1.dat 进行格式化, 格式化后的数据将按照ip进行分类并排序. 还可以配合--filter对扫描结果进行筛选. 如gogo -F 1.dat --filter port::22

默认情况下, 将输出格式化的纯文本数据, 如果需要导入到其他工具, 或者用作进一步分析.

可以通过-o 指定输出格式. 例如:

gogo -F 1.dat --filter frame::weblogic -o url | weblogic_exp

或者导出json文件还可以提供给gogo自身

gogo -F 1.dat --filter frame::weblogic -o json -f weblogic.json

如果其中存在蜜罐, 有经验的攻击者基本上可以根据gogo收集的信息进行除初步的判断, 可以将扫描结果过滤后再进行进一步的主动指纹识别以及漏洞扫描.

当然也提供了懒人的解决方案, 也是我自身比较常用的方式.

gogo -i 172.16.2.1/24 --af -ev -p common

不管内网有没有蜜罐, 直接对着当前c段的常见端口一波开启主动指纹识别, 主动漏扫的暴力探测.

第二步: 对B段进行测绘

如果通过第一步成果在相邻的网络资产中横向到一些成果, 建议后续的扫描使用这些成果作为跳板, 防止部署防火墙, 流量探针直接抓到我们的入口地址.

不过就算没有横向到其他机器, 也没有关系. 经过一段时间的实践, 发现就算部署了较强防护的内网, 对于高并发的处理大多数也不是封禁, 而且告警. 可能是因为正常的业务中也会存在一些高并发行为. 并且, 直到现在, 也没遇到蜜罐部署在网关上(可能今天说完之后就有了lol). 因此, 对内网的网段进行发现是一个相对安全的行为. 防守方可能早就被内网中的各种误报弄得疲倦, 并不会因为一些高并发, 但是没有任何攻击性的行为进行应急.

一般来说, 在没有其他情报的情况下, 对于当前所在的网段进行测绘优先级最高.

如果当前webshell的ip为172.1.1.2, 那么可以优先对172段进行网段发现.

gogo -w 172b 发现172.16.0.0/12中存活的b段.

(数据均为随机生成)

[*] workflow 172B starting , 2022-11-16 18:48.11
[*] Current goroutines: 4000, Version Level: 0,Exploit: , PortSpray Scan: false , 2022-11-16 18:48.11
[*] Starting task 172.16.126.116/12 ,total ports: 3 , mod: ss , 2022-11-16 18:48.11
[*] ports: 80,443,8080 , 2022-11-16 18:48.11
[*] Spraying 172.16.126.116/12 with ss, Estimated to take 2 seconds , 2022-11-16 18:48.11
[*] Smart port probes: icmp , Smart IP probes: [1 254] , 2022-11-16 18:48.11
[*] Found 172.22.28.1/16 , 2022-11-16 18:48.11
[*] Found 172.28.28.254/16 , 2022-11-16 18:48.11
[*] Found 172.25.29.1/16 , 2022-11-16 18:48.11
[*] Found 172.21.30.1/16 , 2022-11-16 18:48.11
[*] Found 172.16.31.254/16 , 2022-11-16 18:48.11
[*] Found 172.30.32.1/16 , 2022-11-16 18:48.11
[*] Found 172.31.32.254/16 , 2022-11-16 18:48.11
[*] Found 172.26.35.254/16 , 2022-11-16 18:48.11
[*] Found 172.27.36.254/16 , 2022-11-16 18:48.11
[*] Found 172.18.37.254/16 , 2022-11-16 18:48.11
[*] Found 172.17.38.1/16 , 2022-11-16 18:48.11
[*] Found 172.19.43.1/16 , 2022-11-16 18:48.12
[*] Found 172.20.49.1/16 , 2022-11-16 18:48.12
[*] Found 172.23.28.1/16 , 2022-11-16 18:48.12
[*] Found 172.29.6.1/16 , 2022-11-16 18:48.12
[*] Found 172.24.27.254/16 , 2022-11-16 18:48.12
[*] Alived: 16, Totoal : 8160 , 2022-11-16 18:48.14
[*] Time consuming: 2.100150675s , 2022-11-16 18:48.14
[*] B CIDRs result: /root/bins/.172.16.126.116_12_top1_ss_bcidr.dat1 , 2022-11-16 18:48.14

可以看到发现了不少存活的B段, 并且数据会自动保存到对应的文件中.

这个文件是deflate压缩的. 直接打开是个二进制文件, 需要通过gogo -F result.dat 进行格式化.

当然, 如果只是给gogo自身使用不需要这一步, 直接通过-j 将结果再次输入即可使用上次的扫描结果.

例如, 对存活的B段启用smart进行扫描.

gogo -j .172.16.126.116_12_top1_ss_bcidr.dat1 -w s

默认的网关ip为1,254, 可以通过--ipp 1-2,253,254进行自行修改.

默认的探测方法为ICMP协议, 而在部分网络环境会有禁ping的规则, 可能需要修改为其他协议, 可修改为--sp 80,443,23,161这种网关常见的开放端口进行探测. 只需要任意B段中发现至少一个端口响应, 即可判定当前B段被使用, 并且不进行后续扫描.

这种探测方式大体上是安全的, 在不同的项目中我们曾与防守方核对攻击路径时, 防守方都没有发现这一阶段的扫描行为(其中部分防守方已经是业内的安全标杆).

而如果当前的网段为192段这种B类地址, 那么-m ss就无法发挥作用.

可以直接进入到下一阶段.

第三步, 对c段进行测绘

这里gogo已经根据不同场景做了不少优化. 不论是172, 10还是192都能找到对应的workflow, 如果是一些特殊网段, 也可以自行指定.

如果已经进行了第二步, 可以在第二步的基础上继续.

gogo -j bcidr.dat -m s --no --af

如果需要合并2,3两步则更为简单.

gogo -w 10c 探测10段内存活的c段

或者类似的gogo -w 172c or gogo -w 192c

如果是自定义网段, 可以使用 gogo -w sc -i 111.1.1.1/8

所有的workflow都自动开启了--af, 会自动在二进制文件目录下生成bcidr与ccidr两个文件, 分别为存活的B段与C段.

第四步, 对端口进行扫描

拿到存活网段信息, 可以根据经验选择一些高价值的目标进行端口扫描了.

使用上一步发现的存活C段进行端口扫描, 内网如果没有禁ICMP协议, 可以使用--ping参数加速扫描, 只对存活的ip进行端口扫描.

gogo -j ccidr.dat -p common --ping --af

当然, 依旧提供了合并2-4步的workflow. 只需要一个参数即可代替2-4步的全部行为.

gogo -w 10 默认开启了--ping, 如果禁止了ICMP协议, 需要替换成gogo -w 10noping .

172与192段同理. 当然自定义网段可以根据实际情况选用,

gogo -w ss -i 111.1.1.1/8

or

gogo -w s -i 111.1.1.1/16

如果网段小于16则建议使用-w ss ,如果大于等于16则建议使用-w s.

等待扫描完成后, 会发现目录下存在 ...json.dat的文件.

请务必将其保存到本地, 以便后续处理以及防止shell丢失扫描记录.

使用gogo -F json.dat 格式化扫描结果.

对于有经验的红队, 到这一步基本就足够了, 后续就是选择集权服务器或者向着域发起冲锋.

第五步, 对资产进行深入探测

但对于hw这种需要刷分的场景, 可以就需要对内网进行一个批量的漏洞扫描与弱口令/默认口令爆破.

对于gogo来说就是-e (漏洞扫描)与-v(主动指纹识别)

需要注意的是, 如果使用-ev扫到了蜜罐, 不论防守方反应多慢, 也能意识到内网有不速之客了. 所以使用-ev需要谨慎.

使用第四步的扫描结果进行开启了主动指纹识别与漏洞扫描的再次扫描.

gogo -j json.dat -ev --af -t 200

注意

因为这次扫描的所有目标都是存活的, 所以建议调低线程数, 防止过大的流量阻塞网络.

同样的, 也存在一个一行就能解决2-5步的解决方案.

gogo -w 10 -ev 172, 192以及自定义网段同理.

这一行命令更像是github上的同类工具, 简单且粗暴. 使用需谨慎!

gogo的poc已经删除了所有的攻击性, 并且对单个端口同时只用一个tcp链接, 因此绝大多数情况下不会发生对被扫描目标造成伤害. 但实战中复杂的场景依旧不排除造成恶劣后果的情况. 请使用者请一定要谨慎使用.

当然对于较高防护能力的目标, 执行完这一步也意味着攻击者的暴露, 可以根据gogo的特征进行快速溯源反制.

场景2 各种场景下的启发式扫描最佳实践

结合在启发式扫描原理中提到的各种细节, 可以总结出各种场景下的最佳实现.

为了能够自由的控制启发式扫描, 引入了近10个参数, 以及3-5个输出文件, 使用变得复杂, 也有好多人与我反馈了这个问题。

又为了简化启发式扫描的使用, gogo给大部分使用场景添加了workflow解决方案, 现在大部分情况只需要一个参数就能解决了。

网段发现

  1. 从B段中发现存活的C段(C段喷洒), gogo -ip 192.168.1.1/16 --mod s -no or gogo --workflow 192c
  2. 从A段中发现存活的B段(B段喷洒), gogo -ip 10.1.1.1/8 --mod ss -no or gogo --workflow 10b
  3. 从A段中发现存活的C段(A段的启发式C段喷洒), gogo -ip 10.1.1.1/8 --mod sc or gogo --workflow 10c
  4. 自定义B段的C段喷洒, gogo -l b.txt --mod s -no or gogo --workflow c -l b.txt
  5. 自定义A段的B段喷洒, gogo -l a.txt --mod ss -no or gogo --workflow b -l a.txt

存活IP发现

  1. 使用ICMP协议发现A段中所有存活的IP, gogo -ip 10.1.1.1/8 --mod ss -p icmp or gogo --workflow 10ip(单端口的--m ss扫描做了特殊的优化, 具体见:

A段的启发式扫描-p只指定了1~2个端口的时候, 不进行C段喷洒, 直接进行端口扫描( C段喷洒约等于进行一次单端口全扫描)

  1. 使用ICMP发现B段中的所有存活的IP, gogo -ip 192.168.1.1/16 --mod s -p icmp or gogo --workflow 192ip

端口扫描

  1. 使用ICMP协议发现A段中所有的数据库, gogo -ip 10.1.1.1/8 --mod ss -p db or gogo --workflow 10 -p db 禁止ping内网需要使用 gogo --workflow 10noping -p db
  2. 使用80端口探测A段中所有的数据库, gogo -ip 10.1.1.1/8 --mod ss -sp 80 -p db gogo --workflow 10 -sp 80 -p db
  3. 启发式扫描B段常见端口资产, gogo -ip 192.168.1.1/16 --mod s -p win,top2,db or gogo --workflow 192
  4. 启发式扫描C段常见端口资产, gogo -ip 10.1.1.1/8 --mod ss -p win,top2,db or gogo --workflow 10
  5. 内网一把梭(慎用), 自动化探测172,192,10等常见内网网段, gogo --workflow interc

一些特殊情况的使用场景

  1. 假设80端口存在ACL的C段喷洒, gogo -ip 10.1.1.1/8 --mod s -sp 22,445,icmp -no or gogo --workflow 10c -sp 22,445,icmp
  2. 假设网关ip为1,253,254的B段喷洒 ,gogo -ip 10.1.1.1/8 --mod ss -ipp 1,253-254 -no or gogo --workflow 10b -ipp 1,253-254
  3. 假设禁ping情况下, 网关ip为1,253,254的B段喷洒, gogo -ip 10.1.1.1/8 --mod ss -sp 80,22 -ipp 1,253-254 -no or gogo --workflow 10b -sp 80,22 -ipp 1,253-254

特殊场景

场景1 k8s/ingress/Istio

在这个场景中, 资产分布与常见的内网有很大不同. 正常的内网中, 网段规划与ip是通过管理员手动配置后再交由DHCP服务或者static ip分配. 因此网段是非常有规律的, 这种规律被smart模式与supersmart完全概括, supersmart是这种模式下对A段大内网探测的理论最优解. 但对于云原生的环境中, ip的分配是随机的, 再由服务发现与均衡负载控制器进行流量分配. 一般情况下, 通过env命令可以判断是否为这种类型的内网. 这种类型的内网中会存在大量service_name=ip:port的配置, 并且ip为随机生成的ip.

因此这种场景下, 不管是扫C段还是supersmart还是手动探测都会有些不适应.

k8s默认的网段是10.0.0.0/8, 各种服务随机的分布在这整个大网络, 没有网关, 也没有集中存活的网段. 如果使用fscan之类的工具对这个网段进行探测, 因为只能使用ping去探测存活网关的原因, 将不会得到任何结果.

并且, 如果不使用ping网关的方式去探测, 对整个10段进行ping探测, 也不一定能得到全部结果. 因为k8s中的不同service之间并不一定能ping通, 只有同属于一个nameserver下才能直接ping通. 但ping不通的目标依然有可能访问, 通过k8s内部的域名, 依旧有可能访问到其他资产.

综上所述, 这个环境下, 最好的扫描策略是对全ip进行常见端口探测.

例如

gogo -i 10.0.0.0/8 -w s --sp 80,22,icmp

这种方式能获得大部分结果. 但如果配置了禁止ping策略, 并80与22端口不开放, 那么依旧有可能漏掉很多资产. 目前没有办法解决, 但可以配合手动信息收集进行特定策略的扫描.

注意.

不能使用-m ss或者-w 10等方式, 因为这种网络架构中没有网关的概念, 基于网关的探测方式均不能使用.

例如在Istio的sidecar架构或者某些运维监控服务会监听特定端口, 如zabbix的2000端口. 那么可以将存活探针指定为这个端口进行探测.

gogo -i 10.0.0.0/8 -w s --sp 2000

在某些特殊的场景可能连gogo都不起作用了. 就需要利用k8s内部的dns服务器进行探测. 借助ksubdomain或者dnsx进行dns爆破也能获得一些信息.

场景2 禁止ICMP协议的内网

禁止ICMP协议是某个时期经常被提起的网络策略, 但实际上整个内网配置禁止ICMP的场景并不算多. 但某些场景的禁止ICMP策略反而会被市面上的所有扫描器忽略.

注意.

禁止ICMP实际上有两种情况. 路由器/防火墙中设置了drop ICMP或者相关的网络配置导致网络不可达.

  1. 所有ICMP请求都会timeout.

  2. ICMP协议直接返回结果, 通常报错是destination host unreachable目标主机不可达.

这两种响应很难具体区分是什么原因导致的. 但在扫描结果上看会导致完全相反的结论.

全内网禁止ICMP

这个场景特征特别明显, 大多是网络设备的配置导致的, 能直接感受到使用fscan和gogo的某些workflow扫描不出任何结果, 但是一些被动信息收集的方式有证明某些网段存在资产. 这种异常大部分人都能感知到, 会快速修改扫描策略.

fscan中提供了no-ping选项, 直接关闭了ping的探测阶段进入到常见端口扫描, 这直接导致了扫描时间指数增长, 对一个B段扫个几天几夜都是常见情况. 这几乎是不可接受的, 更让扫描A段变成不可能, 就算有无限的时间, fscan也会因为迟迟无法解决的内存泄露问题导致内存耗尽报错退出.

gogo中提供了更加优雅的解决方案, 只需要修改启发式扫描探针即可.

supersmart下网关常见端口为 80,23,22 (实际上所有ss相关的workflow在noping模式下会自动将端口探针修改为80, 但为了适配网关的规律, 建议添加上23,22端口):

gogo -i 10.0.0.0/8 -w ssnoping --sp 80,23,22

smart下默认的探针端口为80,不需要修改.

gogo -i 172.16.1.1/16 -w snoping

在全网禁止ICMP的环境下, gogo依旧能保证相同的速度完成对整个内网的探测.

部分IP禁止ICMP

某些设备或者镜像会配置echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all 这将导致不会主动返回任何ICMP的响应. 也有可能是路由器/防火墙的配置导致某些子网段或单个ip无法ping.

这种情况如果使用fscan, 将导致直接忽略掉这些ip/网段, 因为fscan默认的扫描策略强依赖于ICMP协议, 并没有提供代替方案, 因此对使用者来说, 漏掉的这些资产是无感的. fscan的扫描策略类似-w ss模式的gogo的第一阶段.

如果使用gogo -i 172.16.1.1/16 -w snoping 则可以避免这种情况的同时保证扫描耗时不会有指数级的提升. 依旧能在半个小时左右扫完一个b段.

注意事项

  1. 这个流程并不是死板的标准公式, 很多时候可以合并其中几个步骤, 并且gogo都已经提供了快捷的workflow来帮助合并其中任意步骤.
  2. 任何扫描行为都有可能被发现, 需要根据实际情况评估当前需要进行何种探测行为
  3. 高并发的扫描行为有可能打挂当前服务器, 甚至打挂路由器, 需要根据实际情况调整并发数. 默认的linux4000并发, windows 1000并发是多年经验得出的较优解.
  4. upx后的gogo体积大约为2M

其他

之后将会介绍我们曾经遇到的各种场景下如何使用gogo.

gogo还提供了较为强大的拓展能力, 可以根据需求自行定义gogo的行为.

gogo通常作为唯二(另一个是shellcode loader)需要在内网落地的工具, 在之后我们也会提供更优的解决方案实现不落地情况下的高并发扫描. 如果你的C2实现的反射加载PE, gogo也可以不落地, 节省了免杀的成本.

gogo的扫描结果是后续渗透的核心支撑, 因此将会陆续公开 与webshell的联动, 与cs的联动, 与其他工具的联动的解决方案.

最后, 请确保在使用gogo的时候已经拿到了授权!