在战争中,CornerShot 是一种武器,它能让士兵在不暴露自己的情况下,窥视墙角另一边(并可能进行射击)。 同样,CornerShot 软件包允许用户无需在远程主机上拥有任何特殊权限,即可探知该主机的网络访问情况。
使用 CornerShot,一个源主机(能通过网络访问载体主机)可以判断载体与目标之间是否存在针对特定端口 p 的网络访问。
例如,假设一个红队正试图从“被攻陷”的源主机 A 传播到目标主机 X,而主机 A 无法直接访问 X。 如果他们通过主机 B 传播,那么只有在之后他们才会发现主机 B 与 X 之间没有网络访问。
通过使用 CornerShot,该团队可以发现主机 C 实际上可以访问目标 X,因此传播到目标 X 应首先经过主机 C。
+-----+ +-----+ +-----+
| | | | filtered | |
| A +--------> B +----X--->(p) X |
| | | | | |
+-----+ +-----+ +-(p)-+
源 载体 目标
+ ^
| |
| +-----+ |
| | | open |
+---------->+ C +-------------+
| |
+-----+
与 nmap 类似,CornerShot 区分以下端口状态:开放、关闭、过滤 和 未知(如果无法确定)。
以下演示展示了针对两个载体主机 172.0.1.12 和 172.0.1.13 运行 CornerShot,以判断它们能否访问 192.168.200.1:

更多信息请阅读 这里。
识别网络中主机 B 能否访问主机 C 这个看似简单的任务,可能需要大规模部署网络传感器、设备代理,或者收集大量防火墙规则、路由器配置和主机策略。
CornerShot 可以通过使用一个(或极少数)代理来查询网络中的其他主机,以确定它们对远程主机的访问权限,从而简化这一过程。
利用 BloodHound 来发现并缓解网络中权限提升路径的安全团队,往往被 BloodHound 发现的数百万条逻辑路径所困扰。
ShotHound 是一个将 CornerShot 与 BloodHound 集成在一起的工具,用于发现由网络访问支持的切实可行的路径。
CornerShot 可以作为软件包使用,也可以作为独立模块使用。唯一的要求是 Python 3 和 impacket 包。
pip install cornershot
基本使用需要有效域用户的凭据、FQDN 域名、载体 IP 和目标 IP。
python -m cornershot <user> <password> <domain> <carrier> <target>
要扫描一组载体对一组目标的访问,子网或 IP 范围可以用逗号分隔的列表形式提供:
python -m cornershot <user> <password> <domain> 192.168.1.10-192.168.1.20 192.168.5.0/24,192.168.6.0/24
默认情况下,CornerShot 会尝试扫描以下端口:135、445、3389、5985、5986。用户可以提供逗号分隔的端口和端口范围列表:
python -m cornershot -tp 22,8080,45000-45005 <user> <password> <domain> <carrier> <target>
在代码中,需要使用有效域用户的用户名、密码和域名实例化一个 CornerShot 对象。 通过 add_shots 方法添加载体、目标和端口。准备就绪后,可以调用 open_fire 方法,该方法将根据所需端口仅执行相关的 RPC 调用。
from cornershot import CornerShot
cs = CornerShot("username", "password", "fqdn")
cs.add_shots(carriers=["192.168.1.1"],targets=["192.168.1.2","192.168.1.3"])
results = cs.open_fire()
open_fire 的返回值是一个字典,键是载体,每个载体又包含以目标为键的字典,最后每个目标包含一个端口及其状态的字典。 以下是结果格式的示例:
{'carrier_1':
{'target_1':
{135: 'unknown', 445: 'filtered', 3389: 'filtered', 5986: 'filtered', 5985: 'filtered'},
'target_2':
{135: 'unknown', 445: 'open', 5985: 'unknown', 5986: 'filtered', 3389: 'open'}
},
'carrier_2':
{'target_1':
{3389: 'filtered', 135: 'filtered', 5985: 'filtered', 445: 'filtered', 5986: 'unknown'},
'target_2':
{5985: 'filtered', 5986: 'filtered', 445: 'filtered', 135: 'filtered', 3389: 'open'}
}
}
CornerShot 依赖多种有据可查的标准远程过程调用(RPC)方法,这些方法被各种微软服务所使用。 通过使用仅需域中已认证账户即可调用的方法,CornerShot 能够从载体主机向目标主机触发网络流量。
CornerShot 通过测量 RPC 调用的耗时以及各 RPC 方法的不同错误码,来判断远程端口的状态。
读者可能熟悉由 Lee Christensen 发现的 “打印机漏洞”(“printer bug”)。虽然它被称为漏洞,但实际上是打印服务的一个有据可查的行为,允许任何经过身份验证的用户使用 RpcRemoteFindFirstPrinterChangeNotificationEx 方法强制远程服务器向任何机器进行身份验证。
CornerShot 使用了来自多个微软协议的以下 RPC 方法(还有更多方法,将在未来版本中实现):
这些协议本身的实现依赖于优秀的 impacket 包。
该方法接收一个 printerName 参数。 printerName 可以是本地文件路径、远程文件路径甚至网络打印机的路径。通过提供符合 WEB_PRINT_SERVER 格式的名称,可以查询任何远程端口。 一个示例的 Web 打印服务器名称格式是:"http://<target_ip>:<target_port>/printers/ppp/.printer",这将触发向远程主机和端口的 HTTP 流量。
使用该方法需要两步:首先,在远程主机上打开一个注册表项——这将返回一个有效句柄;其次,尝试将该句柄的备份保存到远程文件。 BaseRegSaveKey 方法接收一个文件路径,用于保存注册表的备份,这会向目标触发 SMB 流量(使用端口 445,备选端口 135)。 CornerShot 打开的注册表项是 HKEY_CURRENT_USER,该键在大多数客户端主机上默认允许读取。
此函数尝试将 Windows 事件备份到文件路径,该路径可以是远程的——在这种情况下,服务将尝试访问远程主机和路径。
与 EVEN 方法类似,只是该方法使用了不同版本的 Windows 事件协议,直接通过 TCP 进行——无需 SMB 端口开放。
CornerShot 根据 RPC 方法或底层传输返回的响应时间和错误消息来估计远程端口的状态。 通过在多种 Windows 主机和不同 RPC 协议上的实验,我们总结出三种在不同网络环境中均有效的定时阈值。 这些阈值通过下图展示:
+ + +
| | |
unknown | open / closed | filtered | open
/ | | |
open | | |
| | |
+-------------+------------------+-----------------+--------------+
0 0.5 20 40 Seconds
MIN FILTERED UPPER
MIN 阈值为 0.5 秒,低于此阈值的响应要么表示底层 RPC 方法或传输出错,要么表示已从目标主机收到响应。
低于 FILTERED 阈值(20 秒)的回复可能表示端口开放或关闭,具体取决于该方法接收到的错误消息类型。
回复时间在 FILTERED 阈值和 UPPER 阈值(40 秒)之间,对于所有测试过的方法(目前而言)均表示端口被过滤。而超过 UPPER 阈值的请求表示持久的开放 TCP 连接。
对不同操作系统版本和配置执行 CornerShot 会得到不同的结果。并非所有 Windows 版本都具有相同的命名管道,或者在使用相同 RPC 方法时行为一致。 大多数 Windows 默认不会在网络上暴露 SMB 和其他 RPC 服务,但经验表明,在大型环境中,这些端口往往对大多数资产是开放且可访问的。
下表展示了各种 RPC 协议的默认支持情况,前提是相关端口对载体主机可访问,且主机未进行配置更改:
* 如果客户端机器上运行了 Webclient 服务,则可以扫描其他端口。目前 CornerShot 不支持此选项。
** 服务器主机支持 RPRN 协议,但打开远程 Web 打印机无效(因此无法扫描任意目标端口),直到我们找到解决方案为止 😉
欢迎添加额外的 RPC 注入方法或任何其他贡献!
所有 RPC 方法均实现于 /shots 目录下,并继承自名为 BaseRPCShot 的抽象类。 /example 文件夹展示了如何创建自定义 RPC 注入方法并在代码中使用。
CornerShot 基于 Apache 2.0 许可证发布。更多详情请参见 LICENSE。
我们期待您的反馈! 如果发现错误、有补丁或对此软件包有建议,请通过 [email protected] 联系我们。
| 操作系统 | 支持的 RPC 协议 | 载体主机需要开放的端口 | 可扫描的目标端口 |
|---|
| Windows 7 | EVEN, EVEN6 | 445 / 135 及 even6 TCP 端口 | 445* |
| Windows 8 | EVEN, EVEN6 | 445 / 135 及 even6 TCP 端口 | 445* |
| Windows 10 | EVEN, EVEN6, RPRN | 445 / 135 及 even6 TCP 端口 | 任意 |
| Server 2008 | EVEN, EVEN6, RRP, RPRN** | 445 / 135 及 even6 TCP 端口 | 445 |
| Server 2012 | EVEN, EVEN6, RRP, RPRN** | 445 / 135 及 even6 TCP 端口 | 445 |
| Server 2016 | EVEN, EVEN6, RRP, RPRN** | 445 / 135 及 even6 TCP 端口 | 445 |
| Server 2019 | EVEN, EVEN6, RRP, RPRN** | 445 / 135 及 even6 TCP 端口 | 445 |