作者:余弦(@evilcos)

0x01. XSS获取明文密码的多种方式

我已经感受到Web潮流带来的巨大革新,尤其是最近HTML5越来越火。浏览器们在客户端瓜分着这个Web OS,只要是对用户体验好的功能,浏览器之间就会互相学习,然后去实现,但是实现总是存在一些差异,有些差异是用户体验上的,有些则可能带来安全问题。

这篇文章是想深入描述下浏览器记住用户密码这种机制带来的安全问题与实现上的一些差异性。黑客们如何通过技巧获取到浏览器保存的密码,明文。

先回到XSS本身上,XSS获取明文密码的方式有哪些?

1.通过DHTML钓鱼方式

比如document.write出一个登陆页面,或一个登录框。也就是目标网站的登录方式是怎样的,就通过DOM模拟出怎样的。用户很难区分同域内的钓鱼,如果再次输入密码登录时就悲剧了。

2.通过JavaScript hook住密码框

满足某个事件(如onsubmit/onblur/onchange等)就记录之。

3.通过JavaScript实现键盘记录器的功能

监听用户在表单里的击键事件,记录击键的值,有时候这个效果会非常不错。

上面这三个方法都是大家在用的,效果各有千秋,这次我要提一种新的方式:通过利用浏览器保存密码这个机制来达到获取明文密码的目的,效果显得更加直接。

0x02. 浏览器记住密码的机制

现在回到浏览器的这个机制上,最早是哪个浏览器实现的,我懒得去考证了,可能是IE。在用户登录的时候,浏览器会提示保存密码,可以在下面这个地址在线查看我测试的8个浏览器截图:

http://evilcos.me/lab/xss_pwd/

注:这也是本文的demo地址,测试的浏览器有:

Chrome(v 16.0.912.75 m)
IE9
IE8
Firefox(v 9)
Opera(v 11.60)
Safari(v 5.1.2)
Maxthon(v 3.2.2.1000)
Sogou(v 3.0.0.3000)

保存密码是为了提高用户体验,省去了每次登录需要输密码的麻烦,在这个机制之前经常是通过身份认证的本地Cookie来实现的,也许是因为并不是所 有网站都采用持久化Cookie,浏览器才开始选择了这样的方式。而且现代浏览器大多有一个机制:云同步,除了书签、个人偏好外,还可以同步浏览器记住的 密码,使得用户在任意地方都可以同步自己的“习惯”。有的身份认证Cookie是绑定IP的,这样的话同步Cookie就不好使了。简而言之吧,密码这东 西就是方便,可也太滥用了,滥用有风险,而且还来了个云同步,黑客兴奋了。

在浏览器记住密码机制之前大家应该都知道还有一个很火热的机制:表单自动填充!曾经出现的安全风险是:由于这个自动填充的值是跨域共享的,攻击者可以在自 己的域放一个页面,用户的浏览器访问后,会自动填充这个页面的表单(比如Email、家庭地址、手机号等等,如果用户的浏览器记住过这些值的话),然后这 个页面的JavaScript就可以获取到这些值了。这些值还好,攻击者并不一定很喜欢,可是明文密码就不一样了。

记住密码机制需要遵循同源策略,但是如果有XSS就可以忽略这个同源策略,注入JavaScript去得到这个明文密码:P

下面我以Chrome为例深入说明说明,攻击者通过这个机制是如何得到你的明文密码的。Opera与IE的机制相对来说是最安全的,而搜狗浏览器在这方面的安全性最差。

0x03. 获得Chrome记住的密码

先来看Chrome,demo地址:http://evilcos.me/lab/xss_pwd/。可以输入admin/1234567,然后LOGIN试试。浏览器弹出保存密码提示时,选择保存。重新载入这个demo地址,可以看到浏览器已经自动填充了密码。点击按钮“see ur pwd”会弹出你输入的密码明文。

实际上你查看页面源代码是看不到密码的,这个密码是浏览器判断页面加载后,发现表单中有密码项,就自动填充最近一次记录的用户名与密码,就像(或者说就 是)一次DOM操作,动态填充。既然是DOM操作,那么在这之后我们控制JavaScript也来一次DOM操作,这次是读,将密码项里的value值读 出来,是不是就得到了明文密码?对……是这样!

知道这个过程后,邪恶的想法诞生了……

这个机制遵循同源策略,那么如果在一个域内,任意页面存在XSS,就应该可以通过DOM动态创建一个包含一模一样的用户名与密码表单项的表单出来,然后等待浏览器自动填充密码后,再通过DOM操纵得到密码项里的值。
开始实验!

这个页面http://evilcos.me/lab/xss_pwd/的表单是这样:

<form method="post" action=".">
<label for="username">USER: </label><input id="username" name="username" type="text" class="text" value="" />
<label for="password">PASS: </label><input id="password" name="password" type="password" class="text" value="" />
<input type="submit" class="submit" value="LOGIN" />
<input type="hidden" name="next" value="" />
</form>

浏览器是如何记住这个表单的,以确保唯一性?有几个关键值(不同浏览器有差异,不过影响不大):

1.为了遵循同源策略,需要域名:evilcos.me

2.需要一个<form>标签

3.需要id或name为username的用户名<input>表单项

4.需要id或name为password的密码<input>表单项

如果是这样,攻击者发现同域内XSS后,就要开始构造一段payload,这个payload用于自动创建出这样的表单,这个表单浏览器要能够认识(认为 是之前记住密码的那个表单:P),并且必须在浏览器开始自动填充密码之前出来(否则得不到填充值),最后必须在浏览器填充完密码后开始获取表单项的值(否 则获取到的值是空的)。

条件好像很苛刻,哪个步骤时间把握不好,攻击就失败了。针对这个场景我构造了一个payload,如下:

function create_form(user) { /*获取明文密码*/
var f = document.createElement("form");
document.getElementsByTagName("body")[0].appendChild(f);
var e1 = document.createElement("input");
e1.type = "text";
e1.name = e1.id = "username";
e1.value = user;
f.appendChild(e1);
var e = document.createElement("input");
e.name = e.type = e.id = "password";
f.appendChild(e);
setTimeout(function () {
alert("i can see ur pwd: " + document.getElementById("password").value);
}, 3000); // 时间竞争
} create_form('');

也可以查看http://evilcos.me/lab/xss_pwd/xssme.html的 代码,create_form函数的执行优先于整个document文档的完全解析,这时会自动创建一个登录表单(和之前记住密码的表单关键部分是一样 的,这就足够了),然后等待3000毫秒,待整个document文档解析结束(此时浏览器已经完成了密码填充),最后获取密码表单项里的值,成功!

3000毫秒不靠谱就来个for循环直到获取到密码值才退出。

0x04. 插一个题外点:时间竞争

这个话题很大,就是谁先谁后的问题,不仅和浏览器解析处理整个DOM树的顺序有关系,也和我们要达到的目的有关,比如浏览器解析顺序的一个经典例子:

<script src='http://remote/x.js'></script>
<body></body>

是先解析完远程的js脚本,还是先解析<body>标签?

如果这样呢?

<script id='rfi'></script>
<script>
document.getElementById('rfi').src = 'http://remote/x.js';
</script>
<body></body>

我们最好对“时间竞争”心里有数,搞清楚浏览器解析的机制,这样我们的payload才能达到我们的目的。

0x05. 各浏览器的差异

我已经习惯差异了,而且喜欢差异,因为这样很可能会带来一些安全问题,不过前端工程师们就不喜欢了:&,下面我只讲关键的差异,那些小的,大家自己试验,自己发现。

1 Safari浏览器

只有Safari默认是关闭这个机制的。如果开启后,效果和chrome一样,非常好用!

2.Opera浏览器

Opera好像很安全,记住密码后,浏览器并不会自动填充密码,而是要用户自己点击地址栏左边的钥匙图标,才会开始填充并登录。

3.IE8/9浏览器

IE8/9及部分这个内核的浏览器(比如遨游的IE模式)很聪明,将每个登录表单绑定到所在的页面上(下面简称这个页面为绑定页面),由于绑定页面地址是唯一的,同域内其他页面就无法通过生成一个一模一样的表单来获取密码了。

如果就这样还是不安全:P,因为XSS可以动态iframe进这个绑定页面,然后注入JS进行任意DOM操作,同样非常容易获取到密码表单项的值,IE估 计是考虑到了这个,通过iframe调用绑定页面也无效。而且IE的机制还远没这样简单,即使在绑定页面内我也没成功得到密码,因为IE默认并不填充密 码,只有输入正确用户名后,并触发类似onblur事件,这个密码表单项才会填充进对应用户名的密码。这个过程我本想通过DOM来模拟进行的,但是没有成 功。感兴趣的同学可以试试。

4.其他浏览器

其他浏览器(除了搜狗浏览器)都和Chrome差不多了,大多是因为webkit内核。下面单独说说搜狗浏览器吧。

0x06. 搜狗浏览器“记住密码机制”的安全缺陷

搜狗浏览器在实现这个机制估计是下了一些苦工了,双核模式下都很好兼容,不过安全方面的实现存在一些问题,并没严格遵循同源策略。在我的测试中发现,搜狗没区分好不同端口及不同子域的同源问题。
比如在www.foo.com域下记住的密码,在a.foo.com与www.foo.com:8080域中都可以读取到。
还有一个有意思的,我们的payload甚至仅创建一个password表单项(<form>都可以不需要)就可以得到明文密码。看来搜狗浏览器在实现这个机制有偷工减料的嫌疑啊,用户体验虽然不错。

0x07. 如何防御

从三个方面进行:浏览器、网站、用户。

1.浏览器防御

IE的机制相对来说很不错了,其他浏览器可以借鉴,虽然这样会影响一些用户体验,我想为了更安全也值得了吧,需要特别注意的,IE这个机制有好几个关键点,不要到时候依葫芦画瓢,学不好让人笑了:P

2.网站防御

通常给表单的<form>标签设置autocomplete="off"即可,不过不是所有浏览器都兼容,我发现搜狗与遨游浏览器不买这个帐。或者不要<form>标签了,通过JS自提交登录。新浪微博采用了这两种方式,其他网站可以学学。

3.用户防御

意识为先吧,浏览器记住你的密码需谨慎,没必要的就不用记了。

0x08.总结

到这还没结束,大家可以试试给表单多增加一个项或者少一个项,不同浏览器还是存在很多差异,这个大家自己找吧。
这个安全问题我很早就发现,也公开过,不过没引起足够重视:P,如果一个SNS类的网站中传播XSS蠕虫,带上这样的payload,不知道能获取多少明 文密码……或者在定点渗透过程中,如邮箱XSS渗透,带上这样的payload,一定概率说不定可以拿到明文密码。怎么个危害,就看怎么个场景,怎么个利 用。

XSS攻击:获取浏览器记住的明文密码的更多相关文章

  1. 如何php防止XSS攻击

    什么是XSS:这里通俗的讲,就像是SQL注入一样,XSS攻击也可以算是对HTML和JS的一种注入.你本来希望得到是从用户那得到一段有用的文本文字,但用户提交给你的却是别有用心的可执行javascrip ...

  2. xss攻击入门

    xss表示Cross Site Scripting(跨站脚本攻击),它与SQL注入攻击类似,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在xss攻击中,通过插入恶意 ...

  3. 前端Hack之XSS攻击个人学习笔记

    简单概述 **        此篇系本人两周来学习XSS的一份个人总结,实质上应该是一份笔记,方便自己日后重新回来复习,文中涉及到的文章我都会在末尾尽可能地添加上,此次总结是我在学习过程中所写,如有任 ...

  4. web安全:防止浏览器记住或自动填写用户名和密码(表单)的终极解决方案

    最近项目上要求做到这一点,在网上搜了一圈,发现都是不完美的,不兼容全部的浏览器,于是只能自己摸索了,最终得出了终极解决方案: 涉及: disabled 或 readonly display:none; ...

  5. 获取windows凭证管理器明文密码

    1.运行cmdkey /list查看windows保存凭证 方法1.mimikaz mimikatz vault::cred 2.利用powershell尝试获取 windows 普通凭据类型中的明文 ...

  6. Vue单页面应用阻止浏览器记住密码

    Vue单页面应用阻止浏览器记住密码 ——IT唐伯虎 摘要: Vue单页面应用阻止浏览器记住密码. 现象1:路由切换时再次提示“是否记住密码” 登录页面有个密码输入框,输入账号密码进行登录: 登录完成后 ...

  7. 【源码阅读】Mimikatz一键获取远程终端凭据与获取明文密码修改方法

    1.前言 mimikatz框架是非常精妙的,粗浅讲一下修改的思路. 它的模块主要由各个结构体数组组成,根据传入的命令搜索执行相应命令的模块 mimikatz.c 部分代码: NTSTATUS mimi ...

  8. # 防止xss攻击,过滤script标签,获取出标签外的内容

    from bs4 import BeautifulSoups = '<h1>123</h1> <span>456<span>'soup = Beauti ...

  9. 转:获取windows凭证管理器明文密码

    1.运行cmdkey /list查看windows保存凭证 方法1.mimikaz mimikatz vault::cred 2.利用powershell尝试获取 windows 普通凭据类型中的明文 ...

随机推荐

  1. 如何区分 OpenStack Neutron Extension 和 Plugin

    Neutron 里面的 extension 和 plugin 是非常相似的两个概念,我花了好久才貌似搞懂了两者的区别,还不一定完全正确. 在OpenStack 的官网wiki中,可以找到它们两个的定义 ...

  2. mustache.js

    mustache.js 是一个 Mustache 模板系统的 JavaScript 实现. Mustache 模板语法的逻辑比较简单.它用于HTML,配置文件,源代码等.它的工作方式是通过通过以哈希值 ...

  3. please tell me the error about java Graphics

    this is the code: public class paint extends JFrame{ public paint(){ setLayout(new FlowLayout()); se ...

  4. 第九章:Java----泛型学习(最后过一遍)

    泛型:让集合记住里面元素的类型,避免取出时需要强制类型转换(大到小).   ClassCastException! 编译阶段就能发现错误.  语法更严格! 更不容易犯错! 1. 构造器的名字还是类名, ...

  5. uva12532 线段树单点更新

    #include<stdio.h> #include<string.h> #include<queue> using namespace std; #define ...

  6. BZOJ2121 字符串游戏

    Description BX正在进行一个字符串游戏,他手上有一个字符串L,以及其 他一些字符串的集合S,然后他可以进行以下操作:对于一个在集合S中的字符串p,如果p在L中出现,BX就可以选择是否将其删 ...

  7. iOS项目开发知识点

    前言部分 注:本文并非绝对原创 大部分内容摘自 http://blog.csdn.net/hengshujiyi/article/details/20943045 文中有些方法可能已过时并不适用于现在 ...

  8. leach和leach-c协议仿真

    http://blog.csdn.net/codingkid/article/details/7215216 1.复制leach_test为leach-c_test,修改里面的文件夹和输出文件名.并且 ...

  9. 哈希加密算法 MD5,SHA-1,SHA-2,SHA-256,SHA-512,SHA-3,RIPEMD-160 - aTool

    一.MD5哈希加密算法 atool.org MD5即Message-Digest Algorithm 5(信息-摘要算法 5),用于确保信息传输完整一致.是计算机广泛使用的散列算法之一(又译摘要算法. ...

  10. java变量作用域

      1.public:public表明该数据成员.成员函数是对所有用户开放的,所有用户都可以直接进行调用 2.private:private表示私有,私有的意思就是除了class自己之外,任何人都不可 ...