摘要
sfturing 的开源医院订单系统 hosp_order 存在访问控制缺陷。其订单中心接口 OrderUserCenter 直接采用客户端传入的订单标识与用户标识执行更新与查询,相关数据访问未将订单归属绑定到当前会话用户,致使未经认证的调用者可对他人订单发起水平越权访问。攻击行为本身不需要账户或会话 cookie,前提是应用构建自脆弱版本且端点网络可达。该结论基于提交 627f426 的单一构建运行时观测,受限于特定种子数据,修复版本未经验证。已观测影响包括修改订单提交状态、覆写疾病信息字段及在响应中泄露受害者就诊记录;未观测到代码执行或主机接管。
漏洞原理
按设计意图,OrderUserCenter 应当渲染当前用户的订单列表并仅更新本人订单。实际实现中,该处理逻辑直接将请求参数 id、userID 与 diseaseInfo 作为更新与查询的依据,且更新先于任何归属判断执行。
调用顺序
处理入口首先调用 updateOrderSta1 与 updateOrderdiseaseInfo,二者均以请求传入的 id 作为过滤条件执行更新;随后再以请求传入的 userID 查询订单并渲染到响应。两段操作之间不存在对调用者身份或订单归属的校验。
缺失的归属校验
对应的 SQL 语句分别仅按 id 或 userID 过滤,未将订单归属与会话用户关联。无论调用者是否持有有效会话,id 与 userID 完全由客户端控制。会话与请求参数之间缺少信任边界:服务端未验证传入 id 所标识的订单是否属于当前会话用户,也未从会话中派生 userID。
效果
由于更新操作仅凭 id 定位目标记录,攻击者提供他人订单 id 即可触发该订单的状态变更与疾病信息覆写;查询阶段按传入 userID 返回订单列表,使受害者就诊记录在响应中泄露。修改与读取均发生在同一未受保护的请求路径内,且不依赖任何会话状态。
触发条件与攻击逻辑
攻击行为本身不需要账户或会话 cookie;应用须构建自脆弱提交 627f426 或更早滚动版本,且 OrderUserCenter 端点须对攻击者网络可达。上游端点仅接受 POST 请求,测试中将 GET 归一化为 POST 属于实验室兼容层,并非原生应用行为,不应据此推断上游支持 GET。种子数据的创建路径仅为测试准备,非攻击前置条件。
概念上,攻击者向该端点提交他人订单 id 与任意 userID。因服务端在更新与查询前均不校验订单归属,id 直接定位并修改受害者订单,userID 用于返回其就诊记录,越权修改与信息泄露在单次请求内完成。上述运行时行为仅在 627f426 构建与特定种子数据下得到观测。
核心伪代码
handle OrderUserCenter: |
伪代码展示服务端在更新与查询前缺失会话归属校验的决策模型:处理入口直接以请求传入的 orderId 调用更新操作,再以请求传入的 userId 查询并渲染,全程未将订单或 userId 绑定至已认证会话用户,两处缺失共同使越权修改与信息泄露在同一请求内可达。
影响范围
报告受影响范围为滚动版本至提交 627f426 及更早历史版本,属建议性范围,未逐版本测试。运行时验证仅覆盖 627f426 单一构建与特定种子数据。源码比对基于 OrderController.java,确认 SQL 仅按 id 或 userID 过滤、无归属约束。修复版本未经验证,状态未知。
运行时观测到的影响限于 627f426 构建:订单提交状态由 0 变为 1、疾病信息字段被覆写、受害者就诊记录在响应中泄露。测试中未观测到代码执行或主机接管,但该否定观察不排除其他未测试向量。
修复与检测
修复建议(非厂商验证指导):在执行更新或查询前,校验所请求的订单 id 归属于当前已认证会话用户;从会话中派生 userID,而非接受客户端请求传入。在数据访问层增加以会话用户为约束的过滤条件,使 SQL 不可仅凭 id 或 userID 越权定位记录。
检测方面,本报告未提供检测观察。可作为调查线索的方向包括:监控对 OrderUserCenter 的未认证请求、同一请求中订单标识与 userID 来源不一致的访问模式,以及订单归属与变更发起者不匹配的更新记录。这些仅为调查方向,须与合法访问行为关联比对,不能单独作为入侵证据。截至报告时点,源码中未见厂商修复指导,须查询上游仓库确认补丁状态。