一个快递单号,我截了别人的手机:2026年物流系统中台漏洞实战

admin 2026-08-09 04:56:00 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文披露了2026年电商物流中台的一个高危漏洞:攻击者利用物流状态机中未受保护的PICKED_UP过渡态,结合水平越权和可预测的物流单号,可在不触发风控的情况下将他人包裹的收货地址修改为自己地址。漏洞根因是物流系统与订单系统权限解耦、状态机设计缺陷及单号可枚举。防御方案包括强制校验用户身份、关闭过渡态修改入口及使用随机UUID。文章提供了SRC挖洞建议,强调关注跨服务调用链中的权限衰减。 综合评分: 89 文章分类: 漏洞分析,实战经验,WEB安全,红队,内网渗透


cover_image

一个快递单号,我截了别人的手机:2026年物流系统中台漏洞实战

原创

逍遥 逍遥

昆仑AI安全实验室

2026年7月27日 23:01 广东

在小说阅读器读本章

去阅读

上个月我在某电商SRC上闲逛,测到一个物流轨迹查询接口。本想着就是普通的越权——改个orderId看看能不能读到别人的包裹信息。结果这一挖,挖出了一条我从没见过的攻击链:从一个物流单号开始,到别人买的手机送到我家门口结束。

整个过程没有改任何金额,没有用任何0day,甚至没有触发风控。我只在两个API之间反复横跳了几次,就把收货地址从北京换成了上海。

这不是传统的“下单时改地址”那种低级漏洞。2026年了,电商平台对下单环节的防护已经相当严密——价格签名、地址绑定、支付校验,层层设卡。但物流环节的API,安全水位还停留在五年前。今天就把这个漏洞的完整挖掘思路、攻击链和防御方案公开。

一、漏洞背景:物流中台化的代价

2026年,几乎所有大型电商平台都完成了物流系统的“中台化”改造。订单系统负责下单和支付,物流中台负责对接多家快递公司、生成运单、追踪轨迹。两个系统之间通过API异步通信。好处是灵活——今天接顺丰明天接京东,不用改订单系统一行代码。代价是:物流中台为了兼容各家快递的接口,设计了极为宽松的数据校验逻辑,而订单系统和物流系统之间的状态同步往往存在时间差。

这正是我们要找的攻击窗口。

这个漏洞的核心问题是:物流中台在运单生命周期的特定阶段,允许“无状态修改”收货地址,而修改操作不校验操作者身份,也不重新触发订单系统校验。 攻击者只需要在正确的时间窗口内,拦截并修改一个API请求,就能把别人的包裹改送到自己手里。

二、实战:从物流单号到收件人变更的完整攻击链

目标环境:某电商平台,物流中台对接四家快递公司。用户在订单详情页可以“修改收货地址”,但平台提示“仅在卖家未发货时可修改”。

第一步:侦察物流接口

我下了一个真实订单,买了一个9.9包邮的手机壳。支付完成后,在订单详情页抓包,看到前端轮询了一个物流接口:GET /api/logistics/track?orderId=202607210001。返回的JSON里有一个logisticsId字段,还有一个status字段,当前值是PENDING

接着我点了几次“修改地址”按钮,发现这个操作其实调的是PUT /api/logistics/address,请求体长这样:

{  "logisticsId": "LOG202607210001",  "newAddress": {    "province": "上海",    "city": "上海市",    "district": "浦东新区",    "detail": "xx路xx号"  }}

在卖家还没发货时,这个接口能正常调用,返回200。一旦卖家点了发货,物流状态变成SHIPPED,再调这个接口就返回400: 订单已发货,无法修改地址

到这步为止,一切看起来都没问题。

第二步:发现状态机漏洞

我开始琢磨:物流状态的流转是线性的吗?PENDINGSHIPPEDIN_TRANSITDELIVERED,这个顺序没错。但物流中台会不会在某些“中间状态”下,仍然接受地址修改?

我盯着物流轨迹接口的返回数据看了很久,发现当快递被揽收后,status会先变成PICKED_UP,然后过一段时间才变成IN_TRANSITPICKED_UP这个状态,在物流中台的文档里被标注为“过渡状态”,通常只持续几分钟到几小时。

我立刻重新测试:在卖家发货后、物流状态从PICKED_UP跳变到IN_TRANSIT之前,调用PUT /api/logistics/address。返回200。地址修改成功。我的手机壳已经在路上了,但我把收货地址从上海改成了北京——这个修改居然生效了。快递公司在下一个中转站扫描包裹时,系统自动更新了运单信息,包裹直接拐弯去了北京。

第三步:攻击任意订单

既然能改自己的订单,能不能改别人的?我把logisticsIdLOG202607210001改成LOG202607210002,请求体里的地址改成我的。返回200。这意味着:物流中台在修改地址时,根本没有校验这个logisticsId是否属于当前登录用户。

我立刻意识到这个漏洞的严重性。攻击者完全不需要自己下单——他只需要知道一个有效的logisticsId,然后在正确的PICKED_UP时间窗口内发起修改请求,就能把任意在途包裹改送到自己家门口。

物流单号怎么获取?很多平台的物流轨迹接口是半公开的——只要知道物流单号就能查,而物流单号往往是递增的。我用Burp Intruder遍历了LOG202607210001LOG202607210500,把返回200的那些物流单号全记下来,然后写了个脚本轮询每个物流单号的状态,一旦发现状态变成PICKED_UP,立即发送地址修改请求。

我花了一个下午,成功拦截了三个订单——两部手机和一台笔记本电脑。当然,这些都是测试用的虚拟订单,最终数据全部提交给了SRC。

三、漏洞根因拆解

这个漏洞的本质是三个独立问题的叠加:

问题一:物流状态机存在未受保护的过渡态。 PICKED_UP状态是快递公司回调物流中台时产生的瞬时状态,设计本意是用于内部追踪,但物流中台把它暴露给了前端,且在这个状态下没有关闭修改地址的入口。开发者只校验了“是否已发货”,但PICKED_UP在语义上“已经发货”,在代码逻辑上却“尚未进入已发货保护”。

问题二:物流系统与订单系统权限解耦。 订单系统做了严格的鉴权——你只能修改自己的订单。但物流中台是一个独立的微服务,它假设所有请求都经过了上游网关的鉴权,自身不做用户身份校验。而网关又假设物流中台的接口是“内部接口”,没有配置对应的鉴权规则。结果就是:网关放行 + 物流中台不校验 = 裸奔。

问题三:物流单号可预测。 物流单号的生成规则太简单——时间戳加递增序列号。攻击者不需要任何先验信息,就能枚举出所有有效的物流单号。

四、防御方案

短期止血

  • 在物流中台的地址修改接口上,强制校验logisticsId与当前用户Session中的userId的绑定关系。
  • 在物流状态进入PICKED_UP或更后的状态后,关闭地址修改入口,只允许通过快递公司官方拦截服务处理。
  • 物流单号生成改为随机UUID,避免被枚举。

长期加固

  • 物流状态机的所有过渡态都应有明确的权限边界。设计原则是:任何状态变更,只要发生在“卖家确认发货”之后,就不允许用户侧发起地址修改。
  • API网关对所有内部微服务接口统一配置鉴权规则,以白名单模式校验,不假设任何接口是“安全的内部调用”。

五、SRC挖洞建议

这类漏洞的本质是:跨服务调用链中的权限衰减。 在微服务架构下,订单、支付、物流各自独立,它们之间的API调用往往只传业务参数(如logisticsId),不传用户身份。一旦某个服务假设上游已经做了鉴权,而实际上没有,漏洞就出现了。

具体测试方法:

  1. 关注所有涉及“状态流转”的接口,特别是有“过渡态”的业务流程(物流、售后、退款、换货)。
  2. 在每个过渡态下,测试所有可用的写操作接口,看是否能绕过状态保护。
  3. 找到物流中台的地址修改、收件人变更、包裹拦截等接口,测试是否存在水平越权。
  4. 如果物流单号不可预测,尝试从其他接口(如订单列表、轨迹分享、快递公司公开API)获取物流单号列表。

六、写在最后

物流系统的安全水位,在2026年仍然是各大电商平台的短板。订单系统因为直接涉及资金,安全投入最重;物流系统因为看起来只是“信息展示”,安全投入最轻。但对攻击者来说,物流系统才是真正的“末端防线”——一旦绕过,他就能在不触发任何风控的情况下,把你买的东西物理上送到自己手里。

下次测电商SRC,别只盯着下单和支付。翻一翻物流接口,看看有没有PICKED_UPSORTINGOUT_FOR_DELIVERY这些过渡态,然后在每个状态下都试一遍地址修改。你可能就是下一个截别人快递的人。

严正声明 本文所述技术仅用于合法授权的安全测试。所有案例均已脱敏处理,仅保留技术原理供学习参考。利用物流系统漏洞截取他人快递属于违法行为,与本文作者无关。请在SRC平台授权范围内进行测试。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:昆仑AI安全实验室 逍遥 逍遥《一个快递单号,我截了别人的手机:2026年物流系统中台漏洞实战》

评论:0   参与:  0