---
title: UI Security - Thinking Outside the Viewport
author: Abdulrahman Alqabandi
date: 2021-06-02 7:00:00 -0700
categories: [Vulnerabilities]
tags: [UI]
math: true
author_twitter: qab
---
# Introduction
When it comes to an application’s user interface (UI), one may care for the
aesthetics, design consistency, simplicity, and clarity to ensure a good UI.
However, an application like a browser where untrusted content is loaded,
parsed, and given APIs to invoke all sorts of UIs then a new layer of concern
appears: Designing secure UI.
Over the years it has become apparent that browser UIs will be abused in
techniques such as phishing campaigns and tech support scams. Usually, the goal
in these attacks isn’t to execute code on the victims’ machine, but rather to
gain the trust of the victim and convince (or scare) them into simply calling a
number. These kinds of techniques are often referred to as social engineering
attacks, and they are hard to fully mitigate since any untrusted page can
display any image they like. Even still, it is important to ensure that a
browser’s UI does not facilitate such attacks. As we will see, unsecure UI
design can even lead to the extraction of private information from the user;
including credit cards, passwords and addresses. Along with these logical
security issues we will see, like any large C++ project, memory safety problems
can be present even in the UI code.
In this blog post I will share a general guide on how to spot UI security issues
and then discuss some of the bugs that have been found relating to UI security.
# UI Security Checklist
Ask yourself the following set of questions when assessing if a given UI is
secure or not. It usually takes multiple of the following checks to fail to
constitute an abusable UI security bug.
## 1. Does it cross the visible viewport (AKA [Line of Death](https://textslashplain.com/2017/01/14/the-line-of-death/) )?
a. Browser prompts (think alert box, permission prompts and friends) should
always cross the line of death to signify they are legitimate and originate from
the browser. This is to ensure the UI cannot be spoofed within a webpage, since
webpages cannot (or should not) be able to cross the line of death using
JS/HTML/CSS.
b. On the other hand, webpage UI (think autofill entries, dropdown selector,
color picker and friends) **should not** cross the line of death. Make sure they
only appear within the visible viewport. This is to ensure pages cannot cover
important browser UI (omnibox,
[shyUI](https://techcommunity.microsoft.com/t5/discussions/dev-channel-update-to-84-0-488-1-is-live/m-p/1325973)
and permission prompts) or enable webpages to spoof browser UI.
Scrolling down a bit and activating the autofill again we could get:
Not secure design. The proper behavior should instead look like:
Note: Alternatively, the page could scroll up and then show the autofill UI
## 2. Does it contain untrusted content?
If your UI displays text or images that are influenced by an untrusted external
source, usually the visited webpage, then your UI should make that distinction
clear. The end user should be able to discern between what the browser is saying
vs. what the webpage is presenting.
For example, let's take the Javascript alert box. It's a browser prompt that
presents text provided by a webpage, but currently, it makes sure to mention
that 'example.tld says:' at the very top. This makes it clear to the user that
the text after that string is coming from the website and not the browser.
Furthermore, these alert boxes
[will be blocked](https://www.chromestatus.com/feature/5148698084376576) from
being called within cross-origin frames since they have been abused to confuse
users via spoofing.
Everything in red is untrusted. Let’s go one by one:
1. **Tab title**: Untrusted text taken from the web page, basic sanity checks
like ensuring no new lines in the title lead to text displaying outside its
intended text box. Ensuring no HTML is rendered in there. This is also where
the favicon of the website is rendered and ensuring the image is rendered and
displayed safely so if there was any image processing memory corruption it
won't affect the browser process.
2. **Address bar**: Important part of any browser which all users rely on to
know what website they are on. Since this URL is taken from an untrusted
source then extra care needs to be taken to ensure it is displayed clearly to
end users.
3. **Alert origin**: Domain name is untrusted, and some sanity checks should
occur to make sure the domain name is clear.
4. **Alert text**: This is text presented in browser UI which is taken from the
untrusted page. Same checks as in (1) should be made here.
5. **Web content**: This is the web page content; nothing here can be trusted.
## 3. Does it focus on a dangerous button/option?
If the UI is asking the user to make a choice between options, then it should
always default the focus on the least dangerous one. Alternatively, default
focus should not be given to anything at all. For example, the permission prompt
to allow a webpage access to a user’s geographic location shows two options:
'Allow' and 'Block'. If you press 'enter' as soon as the prompt shows, then you
will notice the 'Block' choice was chosen.
Otherwise, if the default focus is on a dangerous choice, attackers can use this
to fool users into making that choice. Usually done by asking the user to hold
down ‘enter’ and then showing the prompt.
[This](https://bugs.chromium.org/p/chromium/issues/detail?id=637098) is one
example of such a bug that affected multiple browsers.
## 4. Can it be called multiple times?
If the UI can be made to appear on demand by a webpage, then you should ensure
it cannot be shown repeatedly in a short period of time. This is to prevent
abusive phishing pages from repeatedly calling a UI to appear in a way that will
confuse or scare the user and at worst trap them in a malicious page.
## 5. Can it be called without a user gesture?
Sometimes the UI needs to appear without a user gesture (for user ergonomics),
if not, it's best to only allow it to be shown if the user explicitly sends a
mouse/keyboard/other
[gesture](https://textslashplain.com/2020/05/18/browser-basics-user-gestures/).
Ensuring it consumes the user gesture will also help in mitigating any further
abuse (with tricks like gesture laundering). In other words, one gesture per
one displaying of UI.
If such a vulnerable UI is found, then attackers could use it to trap users and
prevent them from leaving a website. If coupled with (4) it may prevent normal
use of the the entire machine.
# UI Security Bugs
When it comes to bugs that fail the (1.a)/(1.b) checklist, usually it is due to
miscalculating the visible viewport.
Take this example where the visible viewport has a red border.
Scrolling down a bit and the visible viewport is the same. The part of the
document that is not visible should never be considered as the visible viewport.
However, we are dealing with web content that has access to CSS as well as the
ability to embed frames to other documents. Let’s look at the first example.
## [CVE-2020-15985](https://bugs.chromium.org/p/chromium/issues/detail?id=1099276): Cursor hijacking mitigation bypass
The mouse cursor is a piece of UI just like any other UI and webpages can
automatically replace the cursor with a custom image. This feature has been
abused to
[trap users](https://bugs.chromium.org/p/chromium/issues/detail?id=880863) by
[spoofing the real mouses](https://bugs.chromium.org/p/chromium/issues/detail?id=640227)
location.
As a result, the following update was landed:
_"[Deprecation] Custom cursors with size greater than 32x32 DIP intersecting
native UI is deprecated and will be removed in M75, around June 2019. See
https://www.chromestatus.com/features/5825971391299584 for more details."_
In other words, if a webpage replaces the cursor with a custom image greater
than 32x32, then that custom image cannot cross into the browsers native UI in
such a way that it can trick users. Some pixels are allowed to cross but not
enough to create any reasonable attack.
However, it was found that when Chromium made the calculations of what is native
browser UI vs what is visible web content, there was a possibility to confuse it
by having an iframe host a page that replaces the cursor and then using CSS to
make that frame start above the visible viewport of the main frame. Effectively
bypassing the mitigation put in place.
```html