Inspect Your Gadget

 

Michael Howard and David Ross

June 2007

The last section, "Consider Non-HTML Sidebar Gadget Development Models," was updated in January 2010.

Today, the Windows Vista Sidebar hosts Gadgets built from HTML, JavaScript, and potentially ActiveX controls, and because Gadgets are HTML, they are subject to Cross-site Scripting style bugs. These bugs are extremely serious because script in the Sidebar is capable of running arbitrary code in the context of the locally logged-on user.

This document outlines some of the secure programming best practices that should be considered when building Windows Vista Sidebar Gadgets.

Never Trust Input

This is the same advice we have given for years, and it still holds true for Sidebar Gadgets. Many Gadgets read, manipulate, and then display untrusted data, such as that coming from an XMLHttpRequest object or an ActiveX control. All such input needs to be validated.

Validate Untrusted Input

There is no replacement for a good input checker. You should build a function or functions that include regular expressions to verify that the input is correctly formed, and if it is not, you should reject the data. Below is a loose example that only allows numbers, brackets, dashes, and spaces between 6 and 14 characters long.

// returns null on failure
function isValid(str) {
  var regexp = /^[\d\-\(\)\s]{6,14}$/gi;
  return regexp.exec(str);
}

Sanitize Untrusted Input

After the untrusted data is deemed well-formed, the data should be sanitized prior to rendering in case an attacker attempts to inject malicious content that your input checker does not catch.

function sanitizeHTML(s) {
  var d = document.createElement('div');
  d.appendChild(document.createTextNode(s));
  s = d.innerHTML;
  s = s.replace(/'/g,"'");
  s = s.replace(/"/g,""");
  return s;
}

Avoid constructing HTML and injecting it into the DOM by using methods such as insertAdjacentHTML. A better approach is to create an HTML element by using the createElement method, populate its properties, and then inject it into the DOM by using the appendChild or insertBefore methods, as shown below:

var oAnchor = document.createElement("A");
oAnchor.href = ValidateUrl(inputUrl);
oAnchor.innerText = "Click Here!";
document.body.appendChild(oAnchor);

Enclose Untrusted Data in Quotes

You should always enclose untrusted data in quotes when using it as an attribute's value. Also, validate that URLs are prepended with a safe URL scheme such as HTTP or HTTPS. This will prevent attacks where a URL allows script, such as:

<A HREF= "javascript:[Malicious Script]">Link</A>

Use an allow list of safe URL schemes because there are other lesser-known unsafe URL schemes such as the vbscript: URL scheme.

Set the Gadget's Code Page

This is critical because it can help mitigate many canonicalization bugs due to an undefined code page. For example, UTF-7 escapes are invalid if a Gadget's Web page is set to UTF-8.

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

Prevent Man-in-the-Middle (MitM) Attacks

Even if your Gadget obtains data from what is perceived to be a trusted source (for example, a web service), that data may be modified in transit if it is transferred in plain text. Even if it is transferred by using a secure protocol, your Gadget may not verify that it is receiving the data from a trusted source. And even if the source is verified, it makes no sense for a user's traffic alert provider to be able to execute code on the Gadget user's PC on their behalf.

You should follow the "never trust input" guidance above for all external data, even sources that seem to be trustworthy.

Don't reference non-local content in SCRIPT blocks. Also avoid referencing non-local cascading style sheets (CSS) as they may contain script.

Review a Gadget for Security Bugs

As a first order analysis, the following should be carefully reviewed to make sure they are not introducing security bugs:

  • Verify that all innerHtml constructs render only trusted or sanitized data.
    You can use the innerText property to add untrusted data into the DOM safely.
  • Verify that all document.write method calls render only trusted or sanitized data.
    Again, use the innerText property to add untrusted data into the DOM safely.
  • Verify that all calls into the Gadget object model or ActiveX controls instantiated in the Gadget pass validated data. As an example, be careful when calling System.Sidebar.Execute.
  • Verify that all calls to eval() pass validated data.
  • Verify that all ActiveX controls used by the Gadget are secure (no buffer overruns, integer overruns, and such).

Call ActiveX Controls

When launching an ActiveX control, the Windows Vista Sidebar does not check for Safe-for-Scripting or Safe-for-Instantiation; it is therefore imperative that Gadget developers make sure the ActiveX controls they use are used appropriately.

Consider Non-HTML Sidebar Gadget Development Models

It is possible to write gadgets using other technologies, including Silverlight or the Windows Presentation Foundation (WPF). Each of these technologies has security benefits and challenges that you need to be aware of. For more information, see Silverlight Security and Windows Presentation Foundation Security.