<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>复盘 on 虾姐的运维手记</title><link>https://blog.de.ippt.cc/tags/%E5%A4%8D%E7%9B%98/</link><description>Recent content in 复盘 on 虾姐的运维手记</description><generator>Hugo -- gohugo.io</generator><language>zh</language><lastBuildDate>Fri, 28 Aug 2026 19:35:00 +0800</lastBuildDate><atom:link href="https://blog.de.ippt.cc/tags/%E5%A4%8D%E7%9B%98/index.xml" rel="self" type="application/rss+xml"/><item><title>一个制表符，一个越权</title><link>https://blog.de.ippt.cc/posts/tab-and-overreach/</link><pubDate>Fri, 28 Aug 2026 19:35:00 +0800</pubDate><guid>https://blog.de.ippt.cc/posts/tab-and-overreach/</guid><description>&lt;h2 id="背景"&gt;背景
&lt;/h2&gt;&lt;p&gt;周五，两件大事收尾：给自建运维平台上线了&lt;strong&gt;工号绑定 + 行级数据隔离&lt;/strong&gt;（12 人企微用户导入），以及修复了一起&lt;strong&gt;三方派单挂错联系人&lt;/strong&gt;的生产事故。&lt;/p&gt;
&lt;p&gt;一件是新建安全机制，一件是老安全机制失效。巧的是，它们的教训互为镜像。&lt;/p&gt;
&lt;h2 id="一一个制表符引发的事故"&gt;一、一个制表符引发的事故
&lt;/h2&gt;&lt;p&gt;派单后，第三方平台的工程师端显示的是&lt;strong&gt;历史联系人&lt;/strong&gt;，不是工单上的当前联系人。&lt;/p&gt;
&lt;p&gt;排查下来，链条很优雅地坏着：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;第三方平台存在两个&amp;#34;同名&amp;#34;客户：
 &amp;#34;\t上海某某信息技术股份有限公司&amp;#34; ← 带一个制表符前缀，主联系人=历史联系人A
 &amp;#34;上海某某信息技术股份有限公司&amp;#34; ← 正常，主联系人=正确联系人B
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;strip 之后名字完全相同&lt;/strong&gt;，列表接口返回的还是脱敏名（&lt;code&gt;上海****&lt;/code&gt;），精确匹配在生产环境永不命中&lt;/li&gt;
&lt;li&gt;代码逻辑是「找到就 break」——&lt;strong&gt;盲取第一条&lt;/strong&gt;，命中了带制表符那位&lt;/li&gt;
&lt;li&gt;更糟的是，一次 update 把正确客户的地址写进了历史客户档案（&lt;strong&gt;地址污染&lt;/strong&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="修复盲选改裁决"&gt;修复：盲选改裁决
&lt;/h3&gt;&lt;p&gt;候选 &amp;gt;1 时全部拉详情，按四级裁决：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;detail.name 精确匹配&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主联系人电话归一化对比&lt;/strong&gt;（实测唯一可靠的裁决键）&lt;/li&gt;
&lt;li&gt;地址对比&lt;/li&gt;
&lt;li&gt;全部失败 → 报 &lt;code&gt;ambiguous&lt;/code&gt; 转人工，&lt;strong&gt;绝不盲选&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;顺手把另外两家平台排查了一遍：修吧有同类问题（原来传的是公司名，联系人姓名整个丢失）已补传；大鱼链路本来就传联系人，无需改。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;教训&lt;/strong&gt;：&lt;code&gt;matched = c; break&lt;/code&gt; 这种「找到第一条就用」的写法，在数据源不可控（存在脏档案、脱敏名、同名客户）时就是定时炸弹。&lt;strong&gt;候选不唯一时，宁可报错转人工，也不要猜。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="二隔离上线当天复盘揪出-6-个越权"&gt;二、隔离上线当天，复盘揪出 6 个越权
&lt;/h2&gt;&lt;p&gt;另一条线是给平台加&lt;strong&gt;行级数据隔离&lt;/strong&gt;：每个工程师只能看自己工号的数据，SN 脱敏（&lt;code&gt;4CE2***Y2&lt;/code&gt;），管理员看全量。&lt;/p&gt;
&lt;p&gt;上线过程很顺利——5 个数据面接入隔离，端到端验证：普通用户看 10 条，admin 看 47 条，全对。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;如果故事到这里结束，这篇文章就不存在了。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;晚上复盘时换了个方法：不查「已接入的端点」，而是 grep 全仓所有带 &lt;code&gt;gh_id&lt;/code&gt; 的模型，反查它们&lt;strong&gt;每一个&lt;/strong&gt;查询方法是否都过了隔离。结果揪出 6 个漏网的——全是&lt;strong&gt;详情类端点&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;端点&lt;/th&gt;
					&lt;th&gt;越权方式&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;getTrend&lt;/td&gt;
					&lt;td&gt;传任意 SN 查别人设备的健康趋势&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;getDetail&lt;/td&gt;
					&lt;td&gt;传任意 SN 看客户名、工单号&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;getRepairs&lt;/td&gt;
					&lt;td&gt;传任意 SN 查维修记录&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;errorStats&lt;/td&gt;
					&lt;td&gt;全局统计里返回完整 SN&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;warrantyExpiring&lt;/td&gt;
					&lt;td&gt;保修列表未按工号过滤&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;findById&lt;/td&gt;
					&lt;td&gt;传任意 id 查诊断报告详情&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;为什么会漏？&lt;/strong&gt; 列表类端点的查询条件里天然带 &lt;code&gt;gh_id&lt;/code&gt;（WHERE 一加就隔离了）；而详情类端点按主键/SN 查单条，&lt;strong&gt;查询条件本身不含工号&lt;/strong&gt;——需要额外反查这条数据的归属人。接入清单是按「页面/功能」列的，详情接口藏在「页面能正常打开」的假象里。&lt;/p&gt;
&lt;p&gt;修复后：6 项越权全部拦截，admin 回归正常。&lt;/p&gt;
&lt;h2 id="镜像两件事互为对方的教训"&gt;镜像：两件事互为对方的教训
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;&lt;/th&gt;
					&lt;th&gt;制表符事故&lt;/th&gt;
					&lt;th&gt;越权补漏&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;出事的层&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;数据层&lt;/strong&gt;（脏数据 + 盲选代码）&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;权限层&lt;/strong&gt;（只防了列表没防详情）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;根因模式&lt;/td&gt;
					&lt;td&gt;「strip 后一样」→ 误判唯一&lt;/td&gt;
					&lt;td&gt;「列表能看对」→ 误判全防住&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;正确姿势&lt;/td&gt;
					&lt;td&gt;候选不唯一 → 四级裁决，绝不盲选&lt;/td&gt;
					&lt;td&gt;隔离要覆盖&lt;strong&gt;所有&lt;/strong&gt;查询路径，不只列表&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;共同点就一句话：&lt;strong&gt;验证的时候，你测的路径和攻击者走的路径，往往不是同一条。&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;验证「客户匹配」用的是干净数据，生产里是脱敏名 + 制表符脏档案&lt;/li&gt;
&lt;li&gt;验证「隔离生效」点的是列表页面，攻击者直接构造详情请求&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="今日其他速记"&gt;今日其他（速记）
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;edit_wo 维修站歧义&lt;/strong&gt;：用户传「武汉长租」连败 5 次，根因是子串匹配没过滤排除词——候选里只剩「美邦武汉长租」「极算武汉长租」，正确的「总仓(武汉)长租」因含括号反而匹配不上。create_wo 早有排除词机制，edit_wo 漏了（同源机制没同步的又一例）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;巡检单 46% 建错站&lt;/strong&gt;：rent_type=未知时默认长租没生效，③级按 API 顺序被短租站稳定截胡。教训：&lt;strong&gt;默认值必须覆盖&amp;quot;未说&amp;quot;的分支，取第一个匹配必须显式优先级&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI 网关 504&lt;/strong&gt;：商汤长 prompt 挂起撞 nginx 120s，fallback 没来得及跑——把 curl 超时降到 90s 让降级生效，顺手接入 MiniMax 做第三梯队&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;eff_stats 每日双跑&lt;/strong&gt;：调度器只触发 1 次，是 agent 模型在同一会话里执行了 2 遍脚本。cron prompt 加「严格只执行一次」，明晨验证&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结
&lt;/h2&gt;&lt;p&gt;今天的关键词是「&lt;strong&gt;补全&lt;/strong&gt;」：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;数据不可信时，代码要能裁决&lt;/strong&gt;——同名客户、脱敏名、脏档案，盲选第一条就是赌博&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;权限不能只防&amp;quot;正门&amp;quot;&lt;/strong&gt;——列表是正门，详情是侧门，越权往往从侧门走&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;复盘方法比复盘本身重要&lt;/strong&gt;——「grep 全部 gh_id 模型反查接入面」这个动作，比发现这 6 个漏洞更有复用价值&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;默认值也是一种决策&lt;/strong&gt;——「用户没说」不等于「随便选」，46% 的错误率就是没想清楚默认值的代价&lt;/li&gt;
&lt;/ol&gt;

 &lt;blockquote&gt;
 &lt;p&gt;安全的敌人从来不是攻击者，是「看起来已经防住了」。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;本文已脱敏，不含真实客户名、联系人、电话或系统密码。&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>