TLDR
盗刷集团通过注入攻击可以实现bypass issuer的防御,直接由card network来进行STIP,完成盗刷。
这种类型的攻击,我们能做的只有定期检查statement,及时发现,及时report fraud。freeze、限额都不管用,都能绕过去。
尤其是万事达卡。
Disclaimer
本文所有关于东大部分,皆为客观事实或者高可信度的舅舅rumor。所有关于西大部分,皆为推测,如与事实不符,欢迎指出。
前情提要
https://mp.weixin.qq.com/s/KSazaiyE3uVd9tAcdCXh_Q
前几天小戏精上疯传浦发的万事达卡出现大规模盗刷,情况跟前几年的bilt以及上半年的茶色IHG非常相似:大量持卡人中招,其中相当一部分是从来没在别的地方用过的抽屉卡
相比较西大的两家银行默默装死的态度,东大的这波动作还是很快的,东8区凌晨发公告安抚大家。
太平洋两岸出现这种事情,大家普遍的推测都是觉得银行被脱裤了,造成了数据大面积泄漏。但是脱裤说其实解释不了的一个现象是:
一般被脱裤的数据很少有最新的直接流出来的。这得是直接某个有很高权限的账号leak了,不然没道理会知道最新的卡号。所以脱裤说其实一直是有一些疑问的。
舅舅说
刚好呢,我有一个舅舅,是东大银行系统某个关键IT负责人,是能直接接触到银行系统内的一些general的风险预警以及事故调查报告的。
浦发这件事,问了下舅舅,舅舅也刚好在周末的时候加班开会听了初步的调查报告。趁着周一摸鱼给泥潭分享一下。
可能涉及到犯罪集团的一些犯罪方法,请勿模仿,请勿以身试法。
莫伸手,伸手必被抓!
莫伸手,伸手必被抓!
莫伸手,伸手必被抓!
支付链路
先借用 @LeonGT 老师的这张图
在正常的支付链路中,当持卡人刷卡消费时,交易请求会通过收单机构、卡组织(Card Network)最终发送至发卡行(issuer)的授权系统进行验证。发卡行系统会根据账户状态、余额、风险规则等因素,决定批准或拒绝该笔交易,并返回相应的应答码(Authorization Response Code)。 例如, 00 =“批准”,51 =“余额不足”,05 =“不予承兑”。
虽然按照L老师的说法,
但是逻辑上,一笔交易最终得以通过,是需要issuer approve的。
代授权STIP
为了解决这个问题, 代授权Stand-in Processing (STIP) 应运而生。
当在支付链路中,Card Network无法联系上issuer,或者issuer在规定的时间内(通常是几秒钟)没有有效的响应,为了提高acceptance,Card Network就会挺身而出,代替issuer来对这笔交易做出临时的授权决定。这就是代授权Stand-in Processing (STIP) 。
浦发这次事故的源头,就出在STIP上。
在万事达的应答码中,一共有3个应答码可以触发STIP。分别是:
- 91: 授权系统或发卡系统无法正常运作 (Authorization System or issuer system inoperative)
- 92: 无法路由此笔交易 (Unable to route transaction)
- 96: 系统错误 (System error)
当issuer的系统无响应或者返回这些应答码时,万事达的系统会解读为发卡行正处于非正常状态,从而介入并启用STIP。
Card Network并不掌握你的准确的balance,也没有你的完整的用户画像,更重要的是,issuer需要对STIP批准的交易承担fraud liability。
还记得L老师的那句话吗?
这才是真·躺着approve就能赚钱 ![]()
因此,基于数据的缺失、以及不需要承担liability、满足消费者的支付需求提高conversion,多重影响下,STIP的拒绝率,或者说风险控制能力,是远低于issuer的。甚至因为Card Network不掌握你实时的balance,在STIP中又认为issuer处在不正常的状态之中,approve的交易会远超过你的available credit.
大离谱!浦发沙宣卡被大规模盗刷 9.12日中午收到3笔刷… 小红书
复制后打开【小红书】查看笔记!
当然了,所有命运馈赠的礼物,都已在暗中标好了价格。在事后,这些交易记录都会被发送给issuer,进行最终的入账和清(che)算(pi) ![]()
猎杀时刻
理解了STIP的原理之后,盗刷集团就开始制造并利用STIP了。从这里可以看出,盗刷集团对于整个支付网络的理解非常深入。
IC卡
IC卡的数据结构比传统的磁条卡复杂得多,这也是泥潭普遍认为IC卡几乎不存在被复制的可能性的前提。IC的整个数据结构像一个微型电脑里的文件系统。通常称之为数据元(Data Elements),这些数据元通过标签(Tag)来识别。
一张IC卡芯片中存储着大量的数据元,可以分为几大类:
-
卡片和应用基础信息 (Card and Application Basics):
- 应用标识符 (AID - Tag
4F): 用来识别卡片上的应用,比如A0000000031010代表Visa Credit,A0000000041010代表Mastercard。一张卡可以有多个应用(比如东大特色的双标卡)。 - 主账号 (PAN - Tag
5A): 就是我们熟知的卡号。 - 卡片持有人姓名 (Tag
5F20): 持卡人的姓名。 - 应用有效期 (Tag
5F24): 卡片的有效日期。 - 服务代码 (Tag
5F30): 定义卡片使用范围和服务类型(比如是否限本国使用、是否支持ATM等)。
- 应用标识符 (AID - Tag
-
公钥与证书信息 (Public Key and Certificates):
- 发卡行公钥证书 (Tag
90): 用于验证发卡行签名的合法性。 - IC卡公钥证书 (Tag
9F46): 用于验证卡片自身的合法性。 - 静态数据认证标签列表 (Tag
9F4A): 用于离线数据认证,确保关键数据未被篡改。这部分是芯片卡安全的核心,用于防止卡片被轻易复制和伪造。
- 发卡行公钥证书 (Tag
-
风险管理与验证参数 (Risk Management and Verification):
- 卡片风险管理数据对象列表 (CDOL - Tags
8C,8D): 这是卡片的一个“指令清单”,它告诉POS机在交易时需要从POS机和卡片自身收集哪些数据(如交易金额、终端国家代码等)来生成交易密文。 - 持卡人验证方法列表 (CVM List - Tag
8E): 定义了验证持卡人身份的优先级顺序,比如“优先使用联机PIN”、“其次是签名”、“特定条件下无需验证”。 - 应用交易计数器 (ATC - Tag
9F36): 一个“里程表”,卡片每进行一次交易,这个计数器就会加一。这是一个关键的安全特性,可以防止交易重放攻击。
- 卡片风险管理数据对象列表 (CDOL - Tags
-
交易处理数据 (Transaction Processing Data):
- 这部分数据不是固定存储在卡上,而是在交易过程中动态生成的,然后被打包发送给银行。而这些动态数据的主要载体,就是55域(Field 55)。
也就是说,一张IC卡上,除了Field 55上的信息,其他信息都是静态的,可以动手脚的空间很小。而Field 55因为是动态的,可以有效的防止交易链路被hack。但是古尔丹,代价是什么呢?极其复杂的结构意味着解析它的程序也必须非常严谨,任何一个环节出错都可能导致问题。
55域(Field 55)
Field 55的特殊性在于:
-
动态生成性 (Dynamic): 55域的内容不是固定存储在卡芯片里的。它是在每次交易时,由卡片芯片、POS终端和交易金额等实时信息共同参与计算和组合后生成的。它是一份为当前交易量身定制的repo。
-
内容高度复合 (Composite): 它是一个包含了几十个TLV(Tag - Length - Value)格式数据元的“数据容器”。这份报告详细记录了交易的方方面面,最重要的内容包括:
-
应用密文 (Application Cryptogram - Tag
9F26): 这是55域的灵魂。它是由卡片芯片使用内部密钥,对本次交易的关键信息(如金额、日期、终端随机数、卡片交易计数器ATC等)进行加密运算后得出的一个签名。issuer后台收到后会用同样的密钥和数据进行验算,以确保交易信息未被篡改,且确实是这张合法的卡片发起的。 -
应用交易计数器 (ATC - Tag
9F36): 把卡片当前的“里程数”放进来,告诉issuer这是这张卡的第N次交易。 -
终端验证结果 (TVR - Tag
95): POS机在交易过程中进行多项检查(如是否支持SDA/DDA、持卡人验证是否失败等)后得出的一个状态报告。 -
发卡行应用数据 (IAD - Tag
9F10): 包含了issuer自定义的一些风险信息和密文相关数据。
-
-
承载安全核心 (Security Core): 因为包含了无法伪造的“应用密文”,55域是验证交易真伪的核心依据。这也是为什么芯片卡能有效防范传统磁条卡复制盗刷的原因。
特洛伊木马
根据舅舅的确认信息,初步的调查报告认为,盗刷集团直接利用了Field 55的结构复杂性,精心制作了一个特洛伊木马,打崩了浦发的系统。
他们用了空白的IC卡, 将已知的卡号(PAN)、有效期等基础信息写入卡片对应的静态数据元中。 然后编程修改了这张卡响应POS机指令的行为逻辑。当POS机请求卡片生成交易数据(即Field 55内容)时,这张被篡改的卡片不会进行正常的加密计算(当然他们也没有能力让这张卡进行正常的加密计算,因为他们hack不了issuer的加密算法),而是会按照预设的恶意脚本,返回一个自定义的、包含格式错误的Field 55数据炸弹。
这里他们具体怎么实现的,舅舅没有说。但是我能想到的有:
-
类型不匹配 (Type Mismatch): 比如,某个Tag的Value按照规范应该是纯数字(Numeric),但盗刷集团故意在里面塞入了字母或特殊字符。
- e.g.: 假设某个Tag
9F36(应用交易计数器) 的值应该是00 01(代表第1次交易),攻击者可能把它改成XX 01。当后台系统读取到XX并试图将其作为数字处理时,就会出问题。
- e.g.: 假设某个Tag
-
长度与声明不符 (Length Mismatch): 声明的长度(Length)和实际数据(Value)的长度不一致。比如,L字段声明后面有16个字节的数据,但实际上只提供了8个字节。解析程序在读取时可能会发生内存溢出或读到不该读的脏数据。
-
格式或编码错误 (Format/Encoding Error): 某些数据值需要遵循特定的编码格式,比如BCD码或ASCII码。盗刷集团可以故意提供一个无法被正常解码的字节序列。
-
超长数据注入 (Buffer Overflow): 针对某个特定Tag,提供一个远超常规长度的Value。如果后台系统的程序没有做严格的长度校验,在接收这个超长数据并尝试存入一个固定大小的内存或数据库字段时,就会导致缓冲区溢出。
好戏登场
最终,当这个精心制作的特洛伊木马进入到issuer的授权系统时,如果issuer的系统没有做很好的防注入/by pass错误的交易,可能就会产生一系列不可知的应急反应。而金融系统,遇到这类系统搞不定的紧急情况时,通常为了避免产生更严重的问题,往往会采取的措施是——保护性关闭。
在浦发这起事故中,被修改的Field 55信息,最终击穿了浦发的授权系统,造成了系统的保护性关闭。而盗刷集团等来了他们期盼已久的应答码:91。
而且,值得注意的是,这个应答码并不是针对这一笔交易的,而是由崩溃的进程向它的上层(交易路由或交换模块)返回一个代表系统级故障的状态。这个状态最终被映射为ISO 8583报文中的应答码 91 - Authorization System or issuer system inoperative(授权系统或发卡系统无法正常运作)
按照前面STIP普及的知识,大家就该知道,这时候,对card network来说,针对浦发银行这个issuer的STIP服务启动了。在一段时间内,所有的通过万事达来传递的交易,都会由万事达的STIP服务来approve.
这时候,盗刷集团只需要根据卡bin,疯狂的穷举所有可能的卡号就可以了。通常来说,只要单笔金额没有超过限额,且被穷举的卡号不在万事达的黑名单库中,这笔交易被approve的概率极大。这也就是为什么一些抽屉卡,甚至是刚换发的新卡还在途中就被盗刷的原因。
结语
以上,是根据舅舅的信息,对本次浦发银行事件的初步调查。我不负责任瞎猜,bilt和Chase IHG,也遭遇了类似的事情,否则真的很难解释前面提到的奇奇怪怪的现象。
关于浦发这件事,东8区有主流媒体报道
但是普遍没有get到问题的实际。
因此,本文不鼓励转载,避免对舅舅造成不必要的困扰。

