凌晨五点二十七分,医院的白光像一条不肯松手的绳,把所有人的神经勒得更紧。
林昼站在取证室门口,耳边是门里密密麻麻的键盘声,门外是走廊尽头偶尔滚过的推车轮子声,两种声音叠在一起,像两条不同方向的流水,最后都汇进同一个点――那条正在路上的转运链。
手机屏幕亮了一下,来电号码没有备注,但他一眼就认出来:随车安保的专线。
“林先生。”对方的声音压得很低,像怕惊动空气,“车队在高架下匝道口临停了四十秒。”
林昼的指尖瞬间收紧:“原因?”
“前方两辆车一前一后卡位,像是普通变道,但压着我们不让出。司机按预案换线,后车突然跟上来,打灯、别停,动作很熟练。”安保停了一下,“我们没让他们靠近转运车,但对方在匝道下留了一辆摩托,骑手盯着我们,像在确认什么。”
“确认什么?”林昼嗓子发紧。
“确认你们的‘笨功夫’是不是做满了。”安保说,“他们发现随车保安是双人配置,车牌也不是本院救护车的常规号段,就没敢硬来。”
林昼的胸口那口气没有松开,反而更沉。他太清楚了――对方不硬来不等于放弃,硬来的成本太高,就会改成“软的”。软的东西不响,不炸,却最容易被写进“正常”。
“现在呢?”他问。
“已换辅路。”安保答,“两分钟内到接收医院后门。路口有人想引导我们走主入口,我们没听。你之前说过,入口越显眼,‘正常’越容易被安排。”
林昼“嗯”了一声,喉咙像被砂纸磨过。他挂断电话后没有立刻把手机收起,而是把录音界面保持在亮屏状态――这不是警惕,这是把自己钉在现实里:每一次异常,都要留痕。
视野边缘,系统提示冷冷跳出。
回执04-04:转运链在途
异常:匝道临停=40秒(已固化)
建议:镜像指纹对照(优先级:高)
倒计时:134216
“镜像指纹对照。”
这几个字像一根新的钉子,提醒他今晚的战场已经从医院走廊,延伸到了更深、更隐蔽的地方:不是谁进了icu,而是谁在某个看不见的角落,动过“签名”的手。
取证室的门终于开了。
梁组长走出来,眼睛里布着红血丝,但神色比之前更冷、更稳。他身后跟着一名戴眼镜的年轻人,背着电脑包,衣领还没整理好,像是半夜被从床上拎起来的。
“这是集团信息安全的周工。”梁组长开门见山,“他负责镜像签名与仓库审计。你要的‘镜像指纹’,他能做。”
周工的声音很轻,却很硬:“你们抓到‘幽灵签名’的那份工单了?”
林昼没有寒暄,直接把封存袋放到桌上:“编号、哈希、导出见证都有。你要什么?”
周工把电脑打开,没看封存袋,先问:“你们要追的是谁?”
这个问题问得太直,林昼一时没答。他不是不知道要追谁,他是知道“谁”从来不是一个人,而是一条链:二号室、外包维保、信息科权限、监控策略、临时通行卡、1920通知邮件、tok+0900时区字段、托管协议摘要……每一个节点都像一枚细小的钉,钉到最后,才会把真正的手掌钉在板上。
梁组长替他回答:“追‘允许它发生的人’。不是执行者,是授权者。”
周工点点头:“那就别从‘人’开始,从‘指纹’开始。”
他把电脑屏幕转过来,屏幕上是两串看起来像乱码的哈希值与一行行时间戳。周工的指尖在触控板上飞快滑动:“你们现在手里有两类东西:医院系统侧的工单与权限日志,和平台侧的镜像拉取、签名、发布链路。‘幽灵签名’一般发生在发布链路。”
林昼盯着那些数字,心里却在想父亲――那台呼吸机是不是还在稳,药箱封条有没有被动过,接收医院后门有没有人等在那里。他强迫自己把注意力拽回来:要守住命,就要把手伸向刀柄。
“你说的发布链路,具体是什么?”他问。
周工没有用太多术语,像在给一个非安全岗的人解释,但每句话都带着落点:“镜像不是凭空出现的。它从构建机出来,打包成层,生成清单,再签名。签名不是‘写名字’,是把某个‘钥匙’对应的证明绑在这个镜像上。镜像被拉取时,会验证这个证明。只要签名是真的,镜像就被当成可信。”
梁组长冷笑:“所以他们不需要改医院系统,只要改你们平台推送过来的镜像,就能在医院里‘正常运行’。”
周工点头:“对。最可怕的是,它看起来仍然是你们签过的东西。像有人用你的印章盖在另一份合同上。”
林昼的后背一阵发凉。印章这个比喻太贴近他今晚的感受:院办的“协调”就是印章,二号室的“急用补充”就是盖章后的工单。盖一次,就把责任挪走一点。
“那怎么追?”林昼问。
周工敲了敲屏幕:“追‘镜像指纹’。镜像的每一层都有摘要,构建环境也会留下痕迹。哪怕他们重打包,只要对照足够多的特征,总能找到同一只手的‘纹路’。”
他说着把一个窗口打开,里面是几条对照线:同一份镜像在不同时间被发布,但其中一层的摘要反复出现一个极短的偏差――像同一把刀每次切下去都多出一丝毛边。
“这就是指纹?”林昼问。
“这是指纹的一部分。”周工说,“更关键的是签名链。”
他点开另一份记录:“你们提到‘中间证书更新’。更新不是错,错的是更新发生在敏感窗口,而且更新后签名验证策略从严格变成了宽松。宽松一开,就给幽灵留下了门缝。”
梁组长的眼神更沉:“你能证明是谁把门缝开出来的吗?”
周工没有立刻回答,反而把一条日志放大:“看这个。0405。签名动作发生在一个不是常规构建机的节点上,节点名称像是临时跑出来的:runner-tk-07。你们平时的构建节点命名规则更规整,这个像外来的。”
林昼的心脏猛地一跳:“0405……我们之前也提到过这个时间。”
他想起那种被夜色切开的感觉――夜里最安静的时候,最容易发生“以为没人看见”的动作。
“你们能把这个runner定位到哪里?”梁组长问。
周工摇头:“不靠ip定位,那太容易伪装。靠它使用过什么钥匙、从哪里拉过代码、向哪里推送过镜像、用了谁的令牌。令牌就像手指,印在每一次请求上。”
“令牌在你们那边?”林昼问。
“理论上不该在任何人手里长期存在。”周工说,“但现实里,总有人为了省事,把钥匙挂在门口。”
他说完抬头看林昼,目光第一次像真正落在人身上:“你今晚做的那些编号、封条、双人见证,本质就是把钥匙从门口拿走。现在我们要做的,是把平台侧的钥匙也拿走。”
林昼没说话。他忽然意识到,自己今晚像在和两套世界搏斗:医院里的流程世界,平台里的签名世界。两套世界都用同一个词来掩盖动作――“保障”。
保障谁?保障病人?保障系统?还是保障某些人的安全落地?
“开始对照吧。”梁组长说,“需要什么授权,我来签。”
周工点头,手指再次飞快敲击键盘。他从封存袋里取出导出的签名记录与镜像摘要,把它们导入到一个对照工具里。屏幕上很快滚出一串串结果,像夜里翻涌的潮水。
过了大约三分钟,周工忽然停下。
“有意思。”他低声说。
“什么?”林昼的声音不自觉紧了。
周工指着屏幕上一行红色标记:“这份幽灵签名用的不是你们常规发布钥匙,而是一个被标记为‘应急’的密钥。应急密钥权限更大,审核更少,启用条件是‘重大故障窗口’。”
梁组长的眼神像刀:“谁能启用?”
“按流程,需要两方确认。”周工说,“但系统上显示,这次启用只记录了一方确认。另一方确认字段被填充为‘自动通过’。”
“自动通过?”林昼几乎咬住这四个字,“谁允许自动通过?”
周工没有抬头,像怕自己的答案太尖:“允许它发生的,不是某个工程师。是策略。策略背后要么是高层授权,要么是流程被人为改写。”
梁组长看向林昼:“这就是你要追的‘允许它发生的人’。”
林昼的胃里像被拳头攥住。他忽然想到院办女人那句“别搞得太僵”,想到二号室那张“急用补充”,想到那条陌生短信“回潮已确认”。这些话里都藏着同一种底气:他们不是怕你吵,他们是怕你把“策略”从暗处拎到白灯下。
周工继续往下翻,突然又停住。
“还有一个指纹。”他说。
屏幕上显示:应急密钥启用的请求来源,在日志里被标注为“协调终端(2)”。
林昼的眼神一瞬间凝固:“协调终端(2)?”
梁组长的声音像从喉咙深处挤出来:“二号室。”
门里门外,两套世界的同一个编号,竟然在同一条链上对上了。
这不是巧合,这是把刀柄递到了同一只手里。
林昼的掌心渗出汗。他没有立刻兴奋,反而更冷:如果二号室既能在医院系统里下“急用补充”,又能在平台侧启用应急密钥签名镜像,那就意味着二号室不是某个房间,而是一个权限集合――一个可以跨系统、跨机构、跨城市的权限集合。
权限集合背后的人,才是真正的“回潮”。
“能把这个终端定位到具体设备吗?”梁组长问。
周工摇头:“终端标识可以伪装。但终端用过的证书、握手指纹、tls特征、系统时钟漂移、甚至键盘输入节奏……都能形成更细的指纹。只是我们要更多数据。”
“要什么数据?”林昼问。
周工把需求列得很清晰:“第一,签名服务的握手日志。第二,应急密钥启用的审批链记录。第三,runner-tk-07构建节点的环境快照。第四,镜像仓库推送的原始请求头。”
梁组长点头:“我去协调。你继续对照,把能固化的先固化。”