晒登机牌被盗号:我实测了二维码要遮多少才真的扫不出来
一张票根能问出多少东西
先讲一个真实案例,这不是假设情境。
安全记者 Brian Krebs 在 2015 年写过一篇分析:一位读者 Cory 看到朋友把登机牌拍照贴上 Facebook,他截图、把条码放大,丢进网络上免费的条码解码网站。几秒钟之后,他手上有了那位朋友的常旅客账号信息。
接下来发生的事情才是重点。Cory 可以查看那个账号底下所有未来的航班、更改已购票乘客的座位、甚至取消任何一趟未来的班机。更麻烦的是,这些信息足以协助通过航空公司「忘记 PIN」流程的前半段验证。
朋友只是开心地晒了一张登机牌。
很多人忽略了一件事:条码跟二维码不是装饰图案,它们是可被机器读取的数据容器。你看到的是一堆黑白方块,扫描器看到的是订座代号、姓名、航班、日期、座位。这个落差,就是整个风险的来源。
遮一半没有用:我实测了要遮到多少
这是我最想讲的一段,因为错误的处理方式比不处理更危险——你以为安全了,于是放心贴出去。
二维码在设计上就内建了强大的容错与还原能力。它的规格允许在一定比例的区块毁损、脏污、被遮挡的情况下,扫描器依然能还原出完整数据。这个特性在现实世界很实用(票券被折到、印刷有瑕疵都还扫得到),但用在「我遮一半应该就没事了吧」这种场景,它就变成漏洞。
所以我决定自己测一遍。
到底要遮多少面积
测试方法可以重现。我用 Python 的 qrcode 库生成一组模拟票券凭证的二维码(内容是带订单编号与核销码的网址),分别用 M(15%)、Q(25%)、H(30%)三种容错等级各产一张,然后对每张施加四种遮挡方式、七种面积比例,最后用 OpenCV 的 QRCodeDetector 尝试解码。能还原出完整原始网址才算「扫得出来」。
结果比我预期的更糟。
| 遮挡方式 | M(15%)失效门槛 | Q(25%)失效门槛 | H(30%)失效门槛 |
|---|---|---|---|
| 中央实心方块 | 遮 15% 面积 | 遮 20% 面积 | 遮 25% 面积 |
| 右下角方块 | 遮 20% 面积 | 遮 25% 面积 | 遮 25% 面积 |
| 横线划过 | 遮 10% 面积 | 遮 20% 面积 | 遮 20% 面积 |
| 中央马赛克 | 遮 15% 面积 | 遮 20% 面积 | 遮 25% 面积 |
表格读法:门槛是「开始失效」的比例,低于这个数字都还扫得出来。
三个发现值得记下来。
第一,高容错等级的票券,遮掉五分之一的面积照样能扫。H 等级在遮挡面积 20% 时,中央方块、角落方块、马赛克三种方式全部还原成功。你在截图上涂掉一个看起来不小的方块,实际上什么都没挡住。
第二,马赛克跟实心方块的表现几乎一模一样。这推翻了「马赛克至少比不遮好」的直觉——在我的测试里,两者的失效门槛在三个等级上完全相同。模糊化并没有比涂黑更安全,它只是让你看起来做了处理。
第三,横线划过反而是四种方式里最有效的。M 等级只要一条占 10% 高度的横线就扫不出来了。原因是横线横跨整个符号宽度,破坏的数据区块分散在多个编码区段,而集中在一处的方块反而刚好落在容错能力的守备范围内。
坦白说,第三点跟我原本要写的结论相反。安全机构提醒「画线涂黑不等于作废」是对的——那句话讲的是票券的有效性与数据可读性,而不是说画线一定无效。但如果你问的是「哪种涂法比较挡得住扫描器」,这批数据给的答案是横线赢过方块。这种差别只有实际测了才知道。
遮哪里,比遮多少更重要
真正实用的发现在最后一组测试。
二维码的三个角落有大方块,那是定位图案(finder pattern),扫描器靠它判断方向与边界。我把左上角那一个盖掉,结果三种容错等级全部无法解码——而它只占整张图面积的 2.0% 到 3.6%。
换句话说:遮住 2% 的正确位置,胜过遮住 20% 的错误位置。
务必注意这个测试的边界。我用的是 OpenCV 的解码器、单一 payload、单一版本的二维码;商用扫描器或手机相机的实现不同,容错还原能力可能更强。所以请把上面的门槛当成下限,不是保证值——真实世界的攻击者用的解码器,很可能比我的测试环境更宽容。
那实务上该怎么办?标准只有一个:整块完全覆盖,盖到超出边界。不是遮一角、不是画几条线、不是打马赛克。如果条件不允许(例如只能用手机内置的涂鸦工具),至少确保三个定位角有一个被完整盖掉。
一句话:遮不干净,等于没遮。
旅游场景里的三层泄漏面
我把旅游常见的截图分成三层来看,风险性质完全不同,处理方式也不一样。
| 层级 | 常见来源 | 泄漏内容 | 最坏情况 |
|---|---|---|---|
| 第一层:可扫描凭证 | Klook/KKday 电子凭证、演出电子票、登机牌 | 票券本体、订座代号、常旅客账号线索 | 票被别人先用掉、账号被接管 |
| 第二层:文字识别信息 | 携程/Agoda 订房确认单、订单编号、房号 | 姓名、入住日期、住宿地址 | 冒名致电酒店、社会工程攻击 |
| 第三层:影像内嵌数据 | 直接翻拍屏幕的照片 | EXIF 中的 GPS、拍摄时间、设备 | 推知你当下位置或住家 |
第一层最急。电子凭证的价值就在那个码本身,被抢先扫走,你到现场才会发现票已失效。也发生过歹徒窃取网上的演出票券照片,变造后拿去诈骗想买票的人——受害的不只是晒票的人,还有被骗的买家。
第二层看起来人畜无害,实际上是社会工程的燃料。姓名 + 入住日期 + 酒店名称,足以让人打电话到前台冒充你更动订房,或是反过来冒充酒店打给你要求「重新确认信用卡」。这类诈骗在旅游旺季特别多。
第三层最常被漏掉。手机的截图通常不含 GPS,但如果你是拿另一支手机拍屏幕,那张照片就会带上你拍摄当下的坐标。这种情况比想象中常见,尤其是要把电脑画面传给别人的时候。
那我想给同行的人看行程怎么办
这是最实际的问题。行程信息本来就需要协作,同行者要知道集合时间、票券内容、住宿地址。
优先顺序是这样的:
第一选择是用平台原生的分享功能。 Klook、携程、Agoda 这类平台多半支持把订单分享或转赠给同行者,走官方渠道的话,凭证的有效性由平台控制,不会产生一张到处流传的截图。
第二选择是传文字,不传图。 「9/26 早上 9 点,正门集合,票我带」——这句话包含所有必要信息,零风险。
第三选择才是分享图片,而且要加保护。 如果真的需要传画面(例如复杂的行程表、地图截图),用有访问控制的方式,不要贴在公开帖子里。
用 lpic.cc 的话,可以在上传时设一组查看密码,拿到的短链接就算被转发出去,没有密码的人也打不开。密码是经过 bcrypt 哈希存储的,不是明码比对。对「只想给这五个人看」的行程截图来说,这比丢进群里让它自由流传可控得多。
限制一样要说在前面:单张图片上限 8MB,文件在最后一次被查看后保留 30 天,而且上传的文件会自动压缩优化,原图不会保留。另外——密码保护能挡住不该看的人,但挡不住有权限的人截图转发。任何分享机制都有这个天花板,别把它当成万能。
最后一道防线还是那句老话:真正敏感的凭证,一开始就不要变成图片文件。
常见问题
Q1:我已经把登机牌贴出去很久了,现在删掉还有用吗?
删掉能减少后续曝光,但不能假设没人抓过。务必做的是另外两件事:立刻更改该航空公司账号的密码与安全问题答案,并检查未来订座有没有被异动。Krebs 那个案例里,攻击者能做的第一件事就是改座位跟取消班机。
Q2:Klook 的电子凭证被别人扫过,我到现场还能入场吗?
看票种。一次性核销的凭证被抢先使用,到现场就会显示已使用。这种情况要立刻联系平台客服说明,但处理结果不保证,而且旺季客服响应慢。这是为什么预防远比补救重要。
Q3:把二维码打上马赛克够吗?
不够,而且我实测过它几乎没有比较好。在三种容错等级下,马赛克与实心方块的失效门槛完全相同——高容错等级的票券要遮到 25% 面积才扫不出来。要遮就用不透明实心色块完整覆盖整个码区,或者更好——拍照当下就用实体物件挡住。
Q4:订房确认单只有订单编号跟名字,这样也有风险吗?
有。姓名加上订单编号在某些平台足以查询订单状态,加上入住日期就构成完整的社会工程材料。这是真实案例里反复出现的模式:攻击者不需要拿到密码,只需要搜集到足够的片段信息去说服客服。
Q5:那旅游照片本身呢?也要处理吗?
照片的风险主要在 EXIF 的 GPS 坐标,性质跟票券不同。多数社交平台上传时会清掉 EXIF,但用网盘或「发送原始文件」分享时通常会完整保留。想确认各服务怎么处理,站内有一篇逐字段检查 8 个图床 EXIF 保留情况的实测报告。