假设网关主机的证书仍然有效,但主机已被攻陷。约束访客可以请求哪些页面的每条规则都仍然生效,而这些规则没有一条能限制攻击者现在从该主机向数据库子网发起的连接。正是这个缺口使得“仅 Web 入口”与“分段网络”并不是同一个主张。两种主张需要从不同的起点分别审查,否则任何一种都无法被诚实地说出来。

两个主张,而只有一个从访客开始

第一个主张关乎人:持有浏览器和有效会话的访客只能打开一个应用,打不开别的。仅 Web 入口能很好地回答这个主张,因为访客拿到的是页面而不是路由。这个答案值得保留,而且它也是大多数架构图记录的唯一个主张。

第二个主张关乎组件:假定网关或其背后的应用进程已在他人控制之下。基于这个假定,问题就从“允许哪些 URL”变成“该进程还能到达哪些目的地和身份”。

两个主张的负责人不同,产生的证据不同,失败方式也相互独立。身份团队可以用会话测试证明第一个;第二个则需要网络策略、服务账号审查和主机控制。只记录访客那一半的设计,在评审幻灯片上看起来完整,在事故中却显得单薄,因为攻陷之后真正重要的控制从未进入范围。要指明每项控制支撑哪个主张,否则一条网关规则会被同时记到两个主张头上。

一个完整走通的报销服务,以及它失败的两种方式

以一个报销服务为例:10.60.4.10 上的公共网关负责认证员工,并把批准的请求转发到 8443 端口上的应用监听器,该应用以 expenses_app 角色访问 10.60.4.20:5432 上的一个 PostgreSQL 监听器。员工本不应获得通用的内部访问权限。正常运行时,这个设计确实提供了应用专用的入口,同时没有在任何地方公开数据库监听器。这些地址很重要,因为本文后面的每项检查都会点名它们。

现在把网关从可信集合中移除。一旦 10.60.4.10 的进程归攻击者所有,它还能到达哪些目的地?约束访客的 URL 过滤器,对网关主机向数据库子网发起的连接只字未提。

改为移除应用进程,权限的形状就变了:expenses_app 角色、该服务器能到达的服务,以及该账号能读取的文件。两种情况下,前门都可以保持仅 Web,而后端边界却不存在。因此前门上的标签并不能回答这两个问题中的任何一个。

把各方实际掌握的权力画成图

按预期权限写的契约,往往只是把设计重复一遍。改写成持有的权力、证伪越权的那项检查,以及该检查的负责人,每一行就变得可测试了。下面这张表是对上述示例的提议,不是产品主张:

ComponentAuthority it actually holdsCheck that proves the denialOwner of the check
Identity providerIssues assertions and session cookies, and holds no network path of its ownA request to the application URL without a session is redirected to the login pageIdentity team
Public gateway hostTCP reachability to whatever its routing table and egress rules permitAn egress rule drops 10.60.4.20:5432 and the probe reports the port filteredNetwork platform team
Application roleSQL privileges granted to expenses_app inside the expenses databaseA privilege query shows no ownership or create right on any other schemaApplication team
Database listenerAccepts connections only from the source ranges named in its host-based rulesA connection from an unlisted address is refused before authenticationDatabase administrator
Management pathAdministrative access reserved for patching, monitoring and recoveryA staff workstation cannot reach the administrative port or jump through itPlatform owner

所有权跟着权力走。身份团队拥有断言,网络平台团队拥有路径,应用团队拥有数据库角色,数据库管理员拥有监听器及其基于主机的规则,平台负责人拥有管理平面。没有负责人的拒绝只是文档里的一句话,不是控制。

这种拆分还能防止重复计算。端口限制无法表达表权限,数据库角色也无法阻止主机向无关子网打开套接字。

与其断言,不如数一数网关能到达哪里

边界主张的价值取决于它背后的枚举。在网关主机上,三条命令分别覆盖路由选择、实时探测和出站策略:

ip route get 10.60.4.20
nc -zv 10.60.4.20 5432
sudo nft list chain inet filter output

按这个顺序读输出。路由说明 10.60.4.20 是否会被该主机选中;探测说明监听器是否有响应;规则列表则表明是策略拦住了数据包,还是它的路径上本来就没有任何东西。

从应用主机再重复一遍枚举。从那里看,数据库一侧就是以应用角色执行的一条查询:

psql -h 10.60.4.20 -U expenses_app -d expenses -c 'select rolname, rolsuper, rolcreatedb from pg_roles'

在无法读取其他 schema 的角色下连接成功,与在所有者角色下连接成功是两种不同的结果。只有后者才算发现。

记录被拒绝的结果,然后给评审标注日期

验收要写成结果而不是意图:员工会话无法到达监听器,网关主机无法到达无关子网,应用角色无法创建数据库。每一项都是带具名负责人和日期的独立检查。

让监控、补丁和恢复通过为其设计的管理路径保持可达。连自己人都挡住的边界会变成故障,而对这种故障的通常第一反应是把规则再放宽。CISA 的边界指南要求把入站和出站访问限制在有正当理由的端口和协议上,包括内部网络之间的流量,而这正是大多数架构图遗漏的、由后端发起的那个方向。

给评审标注日期并指明负责人。只要网关镜像、路由表或应用角色发生变化,就重新执行枚举和权限查询。

相关文章