前一段时间,有不少关于用CSS构建的“键盘记录器”的讨论(源代码见:github.com/maxchehab/C…html
有些人要求浏览器“修复”它。 另有一些人挖掘得更深一些,发现它只影响使用React及相似框架编写的网站,并为此指责React。 不过真正的问题在于第三方内容是否是“安全的”。git
下面咱们逐一分析这些第三方内容。github
<img src="https://example.com/kitten.jpg">
复制代码
若是由于我信任example.com
,就在本身的代码中包含上述内容。那么 他们可能会删除资源,从而给我返回一个404,使个人网站看起来支离破碎,从而辜负了这种信任。同时他们也有可能会用一些不恰当的内容取代原来的图片。数据库
不过图像的影响仅限于元素自己的内容框。 我能够向本身的用户解释“这是来自example.com
的内容,若是它变冒犯了你,那是他们的错,可别来找我”,并寄但愿于用户们可以相信我。 可是这种事确定不会影响我数据库中密码字段之类的东西。vim
<script src="https://example.com/script.js"></script>
复制代码
与图片相比,第三方脚本有更多的控制权。 若是个人代码中包含上述内容,就会给example.com
彻底控制本身的网站的机会。 他们能:浏览器
“原始存储”位很是重要。 若是脚本影响了IndexedDB或缓存存储API,即便你把脚本删掉,攻击也可能会仍然继续。缓存
若是你在本身的代码中引用了来自其余来源的脚本,那么必须绝对信任它们,并保证其安全性。安全
若是遇到恶意脚本,则应使用 Clear-Site-Data
标头清除全部站点数据。服务器
<link rel="stylesheet" href="https://example.com/style.css">
复制代码
CSS的做用更接近于脚本而不是图像。和脚本同样,它适用于整个页面。 它能够:
CSS不能修改原始存储,你不能用CSS写一个挖矿程序(也有可能,或许我还不知道),但恶意CSS仍然能够形成很大的破坏。
我们从最开始的那个问题开始
input[type="password"][value$="p"] {
background: url('/password?p');
}
复制代码
若是输入的 value
属性以 p
结尾,上面的代码将触发对 /password?p
的请求。 对每一个字符都会执行此操做,这样你会得到大量键盘输入的数据。
默认状况下,浏览器不会将用户输入的值存储在 value
属性中,所以攻击每每在同步这些值的内容时发生,例如React。
为了缓解这种状况,React可使用另外一种同步密码字段的方法,或者浏览器能够限制与密码字段的 value
属性匹配的选择器,但这仅仅是一种虚假的安全感。 你只不过是解决了一个特定的问题,但其余状况下一切照旧。
若是 React 切换到使用data-value
属性,则上述手段将失败。若是站点将输入更改成type ="text"
,那么用户能够看到他们正在输入的内容,则这种手段失败。 若是站点建立<better-password-input>
并将值做为属性公开,一样上述手段失败。
此外,还有许多基于CSS的攻击:
body {
display: none;
}
html::after {
content: 'HTTP 500 Server Error';
}
复制代码
这是一个极端的例子,但想象一下,若是第三方代码为你的一小部分用户作了这种事,会出现什么样的后果:将会侵蚀掉用户对你的信任,同时很难排查问题到底出在何处。
更加腹黑的黑客可能会偶尔删除“购买”按钮,或着从新排列内容中的段落。
.price-value::before {
content: '1';
}
复制代码
哎呀,你这么快就涨价了!
delete-everything-button {
opacity: 0;
position: absolute;
top: 500px;
left: 300px;
}
复制代码
把一个有“删库跑路”功能的按钮设为不可看,而后再把它放在用户可能会点击的地方。
值得庆幸的是,若是按钮执行的是后果很是严重的操做,该网站可能会首先显示确认对话框。 不要紧,只需使用更多的CSS来诱骗用户单击“是的我肯定!”按钮而不是“哦天呐!不是!”按钮。
想象一下,若是浏览器确实试图消除“键盘记录”这种小伎俩的影响。攻击者还能够在页面上放一个非密码文本输入框(多是搜索字段)并将其覆盖在密码输入框之上,呵呵,如今他们又回来了。
你担忧的可不只仅是密码。 一些私有内容可能会保存在属性中:
<input type="hidden" name="csrf" value="1687594325">
<img src="/avatars/samanthasmith83.jpg">
<iframe src="//cool-maps-service/show?st-pancras-london"></iframe>
<img src="/gender-icons/female.png">
<div class="banner users-birthday-today"></div>
复制代码
全部这些均可以被CSS选择器设为目标,而且能够把结果发到某个服务器上。
.login-button:hover {
background: url('/login-button-hover');
}
.login-button:active {
background: url('/login-button-active');
}
复制代码
能够将hover和active等动做发送回服务器。 适当的使用CSS,你能够很好地了解用户想要干什么。
@font-face {
font-family: blah;
src: url('/page-contains-q') format('woff');
unicode-range: U+71;
}
html {
font-family: blah, sans-serif;
}
复制代码
在这种状况下,若是页面包含q
,将发送请求。 你能够为不一样的文字建立大量的这种请求,并能够定位特定的元素。 字体还能够包含连字,所以还能够检测字符序列。 你甚至能够将字体技巧与滚动条检测相结合,从而能推断出更多相关内容的信息。
这些只是我所知道的一些技巧,我相信还会有更多相似的小技巧。
第三方内容在其沙箱中具备很高的影响力。 虽然图像或沙盒iframe有着很是小的沙箱,但脚本和样式的做用范围却影响你的整个页面,甚至是整个站点。
若是你担忧用户会欺骗你的网站去加载第三方资源,可使用CSP(内容安全策略)保证安全,从而限制从中获取图像,脚本和样式的位置。
还可使用子资源完整性来确保脚本/样式的内容与特定的哈希匹配,不然将没法执行。
若是你对这种安全技术感兴趣,包括滚动条技巧的更多细节,能够去看看Mathias Bynens在2014年的演讲,Mike West在2013年的演讲,或Mario Heiderich等人的2012年论文。 没错,这些技术并非最新的。