【转】扫描⼆维码登⼊安全吗?
昨天在知乎上看到了⼀个问题,本以为这是⼀个送分题,可是点开⼀看,竟然我仰慕的⾼票答主回答并没有给出我期望的回答,还有许多我关注的⼤⼤们点了赞。再⼀看,下⾯⼀排都在⽆脑喷阿⾥和腾讯,⼀点都没有认真答题的意思,⽓得我⼀个个点了反对+没有帮助。终于看到了⼀个,⼏乎感动得我热泪盈眶。其实我觉得他基本上把我能说的话都说了,不过我还是看热闹不嫌事⼤,再插⼀脚进来科普科普吧。
嫌太长不想看的直接翻到最后的“总结”部分吧。
登⼊⽹站是如何⼯作的?
先科普⼀下最简单的登⼊⼀个⽹站的过程是怎样的吧。
1. 当你的浏览器第⼀次访问⼀个⽹站的时候,这个⽹站会分配给你⼀个会话(Session)。
会话的信息都是存在服务器上的,也就是服务器有个⾃⼰的⼩本⼦记录了会话的信息。
服务器会把session_id返回给你的浏览器
之后每⼀次你访问这个⽹站的任何页⾯,你的浏览器都会把这个session_id发给服务器
服务器根据这个session_id就可以分辨不同的会话,同时,前⾯说了,也只有服务器⾃⼰知道和这个会话相关的任何信息
2. 在还未登⼊的时候,服务器看到你这个session_id对应的会话⾥⾯写着“还没有登⼊”,于是就给你展⽰了游客的内容。
3. 你进⼊了⽹站的登⼊界⾯,填写了账号密码,点击登⼊。
4. 你的浏览器把你的账号密码发送到了服务器。
5. 服务器从数据库⾥⾯查了查,发现你的账号密码是匹配的。于是服务器给session_id对应的会话设置了新的信息,⽐如“已登⼊、⽤户
ID……”
6. 之后你再访问这个⽹站,你的浏览器还是把同样的session_id发给服务器。服务器查⼀查⾃⼰的⼩本⼦,发现噢这个会话已经登⼊了,
并且⽤户ID是多少多少。于是就把属于这个⽤户(也就是你)的信息展⽰给你。
这⾥顺带提⼀下,session_id在浏览器这⾥的具体表现形式就是 Cookie ⾥的⼀个键值对。
扫码登⼊是如何⼯作的?
回顾⼀下,其实站在⽤户浏览器这边,基本上没什么事情好做。每次都只是拿着第⼀次访问服务器的时候服务器分配的session_id傻乎乎地去戳服务器,然后把服务器返回的信息呈现给⽤户。⽽服务器这边,每次都是根据会话信息的不同来决定返回什么内容给浏览器。
所以说,重点在于让服务器把会话信息改成已登⼊的信息。你想要让服务器把你的会话信息改掉,你总不能空⼝⽆凭吧?不然你不就可以进⼊任何⼈的淘宝了吗。在前⾯的例⼦⾥⾯,让服务器相信你就是⽤户本⾝的⽅法就是验证你的账号密码。扫码登⼊其实就是换了⼀种让服务器相信你确实就是你的⽅式。
作为⼀个(⾃称)全栈⼯程师,扫码登⼊是怎么⼯作的还是很容易想到的:
1. ⽤户打开登⼊页⾯的时候,他的浏览器与服务器产⽣了⼀个会话。服务器分配给他⼀个login_token并记下它对应的会话session_id,这
个login_token会作为某个验证登⼊的⽹址qr_verify_url的⼀个参数。让⽤户输⼊⼀⼤串⽹址太⿇烦了,于是服务器把qr_verify_url这个⽹址⽤⼆维码包装⼀下呈现给⽤户。
2. ⽤户⽤已经登⼊了的该⽹站⾃家的⼿机APP扫描⼆维码,得到⼀个qr_verify_url。
这⾥要注意的是,扫描这个⼆维码的软件不能是随随便便的APP,必须是这个⽹站⾃家的APP。
强调⾃家⼿机APP已经登⼊,说明⼿机APP上有⼀个服务器颁发的app_token。
3. ⼿机APP弹出提⽰,告诉⽤户这是⼀个登⼊请求,如果确认是本⼈的操作,那么点击登⼊按钮。
4. 点击了登⼊按钮之后,⼿机APP访问拿着login_token和app_token这两个令牌去访问qr_verify_url。
5. 服务器收到了请求,发现app_token和login_token都是有效的,于是到login_token对应的session_id。接下来的步骤就和正常登⼊⼀样范丞丞是洪金宝儿子
了,往这个session_id对应的会话⾥⾯写信息,⽐如说:登⼊成功、⽤户ID……
6. ⽤户的浏览器在这整个过程期间其实都在不断询问服务器:我这个会话session_id登⼊成功了吗?没有的话,就等⼀会⼉再问⼀次。⼀
旦服务器告诉它,登⼊成功了,浏览器就跳转到别的页⾯,结束了登⼊流程。
7. 这个时候因为服务器已经给会话session_id设置了相应的信息,所以服务器知道⽤户已经登⼊了,于是返回给⽤户的页⾯都是登⼊后的
结果。
举个例⼦
以登⼊淘宝为例。在登⼊界⾯看到了⼀个⼤⼤的⼆维码。
我们先不着急⽤⼿机淘宝扫它,我们先⽤看看这个⼆维码⾥⾯写着什么。
言承旭回应出柜
可以看到这是⼀个短链接。我们继续看看这个短链接⾥⾯是什么内容。
⾥⾯的“⽬标地址”就是前⾯说的qr_verify_url。红⾊框出来的就是login_token。值得注意的是,这个login_token和我们浏览器中的login_token是相同的。顺带提⼀下session_id就是访问服务器的时候那⼀⼤串的 Cookie ⾥⾯的⼀部分。
现在让我们⽤⼿机扫⼀扫⼆维码。扫描完了之后会有安全提⽰。点击确认登⼊,然后我们就开⼼地登⼊了。
注册引⼊新的隐患?
知道了这个登⼊的流程,我们不妨站在攻击者的⾓度考虑⼀下有没有什么空⼦可以钻。在这⾥,我想说明的是,就算没有提升安全性,扫码登⼊相⽐起传统密码登⼊也没有引⼊新的安全隐患。
替换⼆维码(中间⼈攻击)
1. 攻击者⽤⾃⼰的浏览器访问登⼊页⾯,得到⼀个⼆维码
2. 攻击者⽤某种⽅法劫持⽤户流量,当⽤户打开登⼊页⾯时,将⼆维码替换成⾃⼰的⼆维码
3. ⽤户扫描⼆维码,并且⽤户并不知道这个⼆维码不是服务器给的⽽是攻击者替换过的,于是点了确认登⼊
4. 攻击者成功登⼊
这是最容易想到的攻击⽅式。不过这种攻击⽅式放在今天,尤其是⼤⽹站的情况下,⼏乎不可能发⽣。现在⼤⽹站的登⼊页⾯基本上都采⽤了https协议,相⽐起普通的http协议,https流量都是加密的。并且以现在计算机乃⾄超级计算机的算⼒,想要破解是⼏乎不可能的。
也就是说,⿊客完全不知道你访问了登⼊页⾯,更不⽤说在登⼊页⾯上做⼿脚了。这条路⾏不通。
替换⼆维码(恶意浏览器插件或者病毒)
1. ⽤户不⼩⼼安装了恶意的浏览器插件或者中了病毒
2. 登⼊页⾯的⼆维码在本地被替换为攻击者的⼆维码
3. 中招
这个⽅法可⾏。但是,这并不是把密码登⼊换成扫码登⼊带来的问题。⽤密码登⼊同样也会遇到这样的问题:病毒可以把登⼊页⾯替换成攻击者的钓鱼⽹站,或者直接把⽤户密码发送给攻击者……
⼆维码公开地显⽰在屏幕上被别⼈扫⾛
(⿊⼈问号脸)那不是你就登⼊了攻击者的账号吗,你不亏啊,⽽且为啥攻击者要送呢?
主动跳进坑⾥
1. 攻击者在朋友圈贴了⼀个⼆维码
2. 你扫描,强⾏忽略“请确认是本⼈登⼊”的字样,看到那个⼤⼤的按钮就是很想按下去
3. 中招
你硬要把钱塞给我,我也没法不要呀╮(╯_╰)╭
另外,从技术上来说,也是困难的。像淘宝的登⼊⼆维码过期速度飞快,似乎⼀分钟就过期了(我前⾯⼏张图截图慢了点,于是⼆维码过期token 对不上了,只好再全部重新截图⼀次)。那么问题来了,这个攻击者⼈⽓得多⾼才能在发完朋友圈的⼀分钟之内⽴马有⼈扫码登⼊呢?
⼿机丢了被别⼈捡⾛
所以说攻击者捡到了你的⼿机之后,打开淘宝登⼊页⾯,⼼想“哈哈哈,我不⽤密码就能登⼊了。”于是在你的⼿机上打开了⼿机淘宝,扫码登⼊……
(⿊⼈问号脸)攻击者为啥不直接⽤你的⼿机淘宝啊?这并不是把密码登⼊换成扫码登⼊带来的问题,本来⼿机丢了之后就会有很直接的安全问题,还轮不到扫描登⼊来背锅。鹿鼎记演员表张一山版
扫码进⼊恶意⽹站
1. 攻击者制作⼀个诱⼈的⼴告或者(克服重重困难)以某种⽅式替换了登⼊⼆维码,指向某恶意⽹站
2. 扫码中招
你扫了码,然后发现没有⼀个让你点击“确认登⼊”的地⽅,你还会继续吗?
就算攻击者做了⼀个长得⼀模⼀样的恶意⽹站,骗你点击“确认登⼊”。可是⼿机淘宝发现这个⽹站不是来⾃taobao,于是就不会把⼿机上的app_token发出去。所以攻击者什么都得不到。
扫码下载病毒
1. 攻击者制作⼀个诱⼈的⼴告或者(克服重重困难)以某种⽅式替换了登⼊⼆维码,指向某恶意软件下载地址
2. 扫码中招
这个是扫码本⾝的问题,不是扫码登⼊带来的。扫码登⼊的时候弹出了⼀个下载,你不会觉得很奇怪吗?怎么还会继续下载、运⾏病毒呢?企业培训合同
破解⼿机APP
1. 攻击者通过某种⽅式进⼊了你的⼿机(可能是远程地),破解了⼿机淘宝
2. 到了⼿机淘宝保存在本地的app_token
3. 拿着app_token伪装是你本⼈操作,发送登⼊确认信息
对攻击者来说,这⾥变数⾮常多,这三点都是很困难的。
1. 在不接触你的⼿机的情况下要进⼊你的⼿机、然后获得⾮常⾼的权限,这很困难。
2. 数据加密。要到正确的解密⽅式需要⼀番波折。
3. 发送给服务器的信息可能⾮常多,即还需要搞定别的验证信息。
⽽且这些问题都是⼿机APP原先就可能存在的安全隐患,和扫码登⼊⽆关。
扫码登⼊带来的些许好处
避免密码泄露
在不考虑电脑中毒的情况下,输⼊密码也有可能被攻击者⾁眼看到或者拍摄到。⽽扫码登⼊,尽管⼆维码是公开的,但只有你⾃⼰⽤⼿机APP扫描才有⽤。
原先的核⼼验证信息是账号密码,是暴露在外界的。现在的核⼼验证信息变成了⼿机⾥的app_token,⽽这是外界看不到的,只有⼿机APP⾃⼰知道。就这点来说,安全性确实提⾼了。
⽤专⽤令牌替换通⽤令牌
许多⼈都会⽤同样的密码登⼊不同的⽹站,这样⼀旦任何⼀个⽹站被攻破,攻击者拿到了你的密码,他就可以尝试并成功登⼊其他⽹站。⽽扫码登⼊的话,就算攻击者拿到了app_token,也到了伪造请求的正确⽅法,他也只能登⼊⼀个⽹站,对其他⽹站束⼿⽆策。
⽤短期令牌替换长期令牌
⽤户名密码可以看成是过期时间⽆穷或者⾮常⼤的令牌(毕竟修改密码的频率很低,甚⾄⼤多数⼈是不会去修改密码的)。扫码登⼊的⼆维码有效期⾮常短(⽐如⼀分钟)。⼿机APP上的app_token也可以设计成快速过期(⽐如半个⽉不打开⼿机APP则失效),也可以吊销(“删除该设备”)。
短期令牌总是不⽐长期令牌糟糕的。
便捷性
很多⼈其实是记不住⾃⼰的密码的,每次登⼊总要试个半天,或者有的⼈密码很复杂然后打字⼜慢,这个时候扫⼀扫就能登⼊难道不是很诱⼈的选择吗?
理想很丰满
现实却很⾻感。上⾯说了这么多的好(或者说起码不差),这都是建⽴在⼀些前提上的,⼀旦这些前提不满⾜,攻击者就能从很多⾓度攻击。
没有完全强制 HTTPS
举⼏个例⼦:
攻击者迫使⽤户使⽤ HTTP 进⾏连接江米包粽子需要泡多长时间
CDN 部署有问题,导致 HTTPS 降级,⼆维码被替换
服务器没有使⽤ HSTS,允许夹杂 HTTP 协议的内容,攻击者趁机在 HTTP 访问的 Javascript 脚本中插⼊恶意代码
程序逻辑漏洞
举⼏个例⼦:
⼿机APP没有验证页⾯来⾃⾃家服务器,就把app_token发了出去
⼿机APP没有强制使⽤ HTTPS 连接⾃家服务器
⼆维码过期时间过长
⽤户⾃⾝素质问题
举⼏个例⼦:
容易使得⾃⼰的电脑/⼿机中毒
轻易被攻击者引导
扫码⾃动下载并运⾏了病毒的安装程序,竟然还主动点击“安装”
不看提⽰,⽆脑点击,主动把⾃⼰卖了
总结
在我看来,扫码登⼊⽐起密码登⼊并没有引⼊新的安全隐患,甚⾄从侧⾯提⾼了⼀定的安全性。但是这需要⼚商、⽤户共同努⼒。⼚商不能犯低级错误,⽤户要提⾼⾃⾝素质。这难吗?
尽管⼤家⾮常喜欢抨击BAT,但是还是要相信⼤⼚的安全⼈员还是不会犯低级错误的。
⽤户⽅⾯,只要⼚商把⾃⼰的事情做好了,⽤户的素质并需要多⾼。另外,随着这些科技不断深⼊⽇常⽣活,⽤户素质也会逐渐提⾼的。