uri - Dave's Blog

Search
My timeline on Mastodon

Edge browser and JavaScript UWP app security model comparison

2018 Nov 29, 2:21

There are two main differences in terms of security between a JavaScript UWP app and the Edge browser:

Process Model

A JavaScript UWP app has one process (technically not true with background tasks and other edge cases but ignoring that for the moment) that runs in the corresponding appcontainer defined by the app's appx manifest. This one process is where edgehtml is loaded and is rendering HTML, talking to the network, and executing script. Specifically, the UWP main UI thread is the one where your script is running and calling into WinRT.

In the Edge browser there is a browser process running in the same appcontainer defined by its appx manifest, but there are also tab processes. These tab processes are running in restricted app containers that have fewer appx capabilities. The browser process has XAML loaded and coordinates between tabs and handles some (non-WinRT) brokering from the tab processes. The tab processes load edgehtml and that is where they render HTML, talk to the network and execute script.

There is no way to configure the JavaScript UWP app's process model but using WebViews you can approximate it. You can create out of process WebViews and to some extent configure their capabilities, although not to the same extent as the browser. The WebView processes in this case are similar to the browser's tab processes. See the MSWebViewProcess object for configuring out of process WebView creation. I also implemented out of proc WebView tabs in my JSBrowser fork.

ApplicationContentUriRules

The ApplicationContentUriRules (ACUR) section of the appx manifest lets an application define what URIs are considered app code. See a previous post for the list of ACUR effects.

Notably app code is able to access WinRT APIs. Because of this, DOM security restrictions are loosended to match what is possible with WinRT.

Privileged DOM APIs like geolocation, camera, mic etc require a user prompt in the browser before use. App code does not show the same browser prompt. There still may be an OS prompt – the same prompt that applies to any UWP app, but that’s usually per app not per origin.

App code also gets to use XMLHttpRequest or fetch to access cross origin content. Because UWP apps have separate state, cross origin here might not mean much to an attacker unless your app also has the user login to Facebook or some other interesting cross origin target.

PermalinkCommentsedge javascript security uwp web-security wwa

Changing the User Agent string in UWP WebView

2018 Oct 23, 9:32

There's no perfect way to change the user agent string for the UWP WebView (x-ms-webview in HTML, Windows.UI.Xaml.Controls.WebView in XAML, and Windows.Web.UI.Interop.WebViewControl in Win32) but there are two imperfect methods folks end up using.

The first is to call UrlMkSetSessionOption. This is an old public API that allows you to configure various arcane options including one that is the default user agent string for requests running through urlmon. This API is allowed by the Microsoft Store for UWP apps. The change it applies is process wide which has two potential drawbacks. If you want to be able to have different UA strings set for different requests from a WebView that's not really possible with this solution. The other drawback is if you're using out of process WebView, you need to ensure you're calling into UrlMkSetSessionOption in the WebView's process. You'll need to write third party WinRT that calls UrlMkSetSessionOption, create the out of proc WebView, navigate it to some trusted local page, use AddWebAllowedObject or provide that URI WinRT access, and call into your third party WinRT. You'll need to do that for any new WebView process you create.

The second less generally applicable solution is to use NavigateWithHttpRequestMessage and set the User-Agent HTTP header. In this case you get to control the scope of the user agent string changes but has the limitations that not all sub resource downloads will use this user agent string and for navigations you don't initiate you have to manually intercept and re-request being careful to transfer over all POST body state and HTTP headers correctly. That last part is not actually possible for iframes.

PermalinkCommentsuser-agent uwp webview

GoBack/GoForward in Win10 UWP WebView

2018 Oct 23, 9:18

The GoBack and GoForward methods on the UWP WebView (x-ms-webview in HTML, Windows.UI.Xaml.Controls.WebView in XAML, and Windows.Web.UI.Interop.WebViewControl in Win32) act the same as the Back and Forward buttons in the Edge browser. They don't necessarily change the top level document of the WebView. If inside the webview an iframe navigates then that navigation will be recorded in the forward/back history and the GoBack / GoForward call may result in navigating that iframe. This makes sense as an end user using the Edge browser since if I click a link to navigate one place and then hit Back I expect to sort of undo that most recent navigation regardless of if that navigation happened in an iframe or the top level document.

If that doesn't make sense for your application and you want to navigate forward or back ignoring iframe navigates, unfortunately there's no perfect workaround.

One workaround could be to try calling GoBack and then checking if a FrameNavigationStarting event fires or a NavigationStarting event fires. If a frame navigates then try calling GoBack again. There could be async races in this case since other navigates could come in and send you the wrong signal and interrupt your multi step GoBack operation.

You could also try keeping track of all top level document navigations and manually navigate back to the URIs you care about. However, GoBack and GoForward also restore some amount of user state (form fills etc) in addition to navigating. Manually calling navigate will not give this same behavior.

PermalinkCommentsuri uwp webview

Windows.Web.UI.Interop.WebViewControl localhost access

2018 Jul 25, 5:34

If you're developing with the new Windows.Web.UI.Interop.WebViewControl you may have noticed you cannot navigate to localhost HTTP servers. This is because the WebViewControl's WebView process is a UWP process. All UWP processes by default cannot use the loopback adapter as a security precaution. For development purposes you can allow localhost access using the checknetisolation command line tool on the WebViewControl's package just as you can for any other UWP app. The command should be the following:

checknetisolation loopbackexempt -a -n=Microsoft.Win32WebViewHost_cw5n1h2txyewy

As a warning checknetisolation is not good on errors. If you attempt to add a package but get its package family name wrong, checknetisolation just says OK:

C:\Users\davris>checknetisolation LoopbackExempt -a -n=Microsoft.BingWeather_4.21.2492.0_x86__8wekyb3d8bbwe
OK.
And if you then list the result of the add with the bad name you'll see the following:
[1] -----------------------------------------------------------------
Name: AppContainer NOT FOUND
SID: S-1-15-...

There's also a UI tool for modifying loopback exemption for packages available on GitHub and also one available with Fiddler.

As an additional note, I mentioned above you can try this for development. Do not do this in shipping products as this turns off the security protection for any consumer of the WebViewControl.

PermalinkCommentschecknetisolation loopback security uwp webview win32webview

Win10 PWA Terminology

2018 May 31, 8:26

Folks familiar with JavaScript UWP apps in Win10 have often been confused by what PWAs in Win10 actually are. TLDR: PWAs in Win10 are simply JavaScript UWP apps. The main difference between these JS UWP Apps and our non-PWA JS UWP apps are our target end developer audience, and how we get Win10 PWAs into the Microsoft Store. See this Win10 blog post on PWAs on Win10 for related info.

Web App

On the web a subset of web sites are web apps. These are web sites that have app like behavior - that is a user might call it an app like Outlook, Maps or Gmail. And they may also have a W3C app manifest.

A subset of web apps are progressive web apps. Progressive web apps are web apps that have a W3C app manifest and a service worker. Various OSes are beginning to support PWAs as first class apps on their platform. This is true for Win10 as well in which PWAs are run as a WWA.

Windows Web App

In Win10 a WWA (Windows Web App) is an unofficial term for a JavaScript UWP app. These are UWP apps so they have an AppxManifest.xml, they are packaged in an Appx package, they run in an App Container, they use WinRT APIs, and are installed via the Microsoft Store. Specific to WWAs though, is that the AppxManifest.xml specifies a StartPage attribute identifying some HTML content to be used as the app. When the app is activated the OS will create a WWAHost.exe process that hosts the HTML content using the EdgeHtml rendering engine.

Packaged vs Hosted Web App

Within that we have a notion of a packaged web app and an HWA (hosted web app). There's no real technical distinction for the end developer between these two. The only real difference is whether the StartPage identifies remote HTML content on the web (HWA), or packaged HTML content from the app's appx package (packaged web app). An end developer may create an app that is a mix of these as well, with HTML content in the package and HTML content from the web. These terms are more like ends on a continuum and identifying two different developer scenarios since the underlying technical aspect is pretty much identical.

Win10 PWA

Win10 PWAs are simply HWAs that specify a StartPage of a URI for a PWA on the web. These are still JavaScript UWP apps with all the same behavior and abilities as other UWP apps. We have two ways of getting PWAs into the Microsoft Store as Win10 PWAs. The first is PWA Builder which is a tool that helps PWA end developers create and submit to the Microsoft Store a Win10 PWA appx package. The second is a crawler that runs over the web looking for PWAs which we convert and submit to the Store using an automated PWA Builder-like tool to create a Win10 PWA from PWAs on the web (see Welcoming PWAs to Win10 for more info). In both cases the conversion involves examining the PWAs W3C app manifest and producing a corresponding AppxManifest.xml. Not all features supported by AppxManifest.xml are also available in the W3c app manifest. But the result of PWA Builder can be a working starting point for end developers who can then update the AppxManifest.xml as they like to support features like share targets or others not available in W3C app manifests.

PermalinkCommentsJS pwa uwp web

Tiny browser features: JSBrowser crash resistance

2018 May 13, 4:59

JSBrowser is a basic browser built as a Win10 JavaScript UWP app around the WebView HTML element. Its fun and relatively simple to implement tiny browser features in JavaScript and in this post I'm implementing crash resistance.

The normal DOM mechanisms for creating an HTML WebView create an in-process WebView, in which the WebView runs on a unique UI thread. But we can use the MSWebView constructor instead to create an out-of-process WebView in which the WebView runs in its own distinct WebView process. Unlike an in-process WebView, Web content running in an out-of-process WebView can only crash the WebView process and not the app process.

        this.replaceWebView = () => {
let webview = document.querySelector("#WebView");
// Cannot access webview.src - anything that would need to communicate with the webview process may fail
let oldSrc = browser.currentUrl;
const webviewParent = webview.parentElement;
webviewParent.removeChild(webview);
webview = new MSWebView();
Object.assign(this, {
"webview": webview
});
webview.setAttribute("id", "WebView");

// During startup our currentUrl field is blank. If the WebView has crashed
// and we were on a URI then we may obtain it from this property.
if (browser.currentUrl && browser.currentUrl != "") {
this.trigger("newWebview");
this.navigateTo(browser.currentUrl);
}
webviewParent.appendChild(webview);

I run replaceWebView during startup to replace the in-process WebView created via HTML markup with an out-of-process WebView. I could be doing more to dynamically copy styles, attributes, etc but I know what I need to set on the WebView and just do that.

When a WebView process crashes the corresponding WebView object is no longer useful and a new WebView element must be created. In fact if the old WebView object is used it may throw and will no longer have valid state. Accordingly when the WebView crashes I run replaceWebView again. Additionally, I need to store the last URI we've navigated to (browser.currentUrl in the above) since the crashed WebView object won't know what URI it is on after it crashes.

            webview.addEventListener("MSWebViewProcessExited", () => { 
if (browser.currentUrl === browser.lastCrashUrl) { ++browser.lastCrashUrlCrashCount;
}
else {
browser.lastCrashUrl = browser.currentUrl;
browser.lastCrashUrlCrashCount = 1;
}
// If we crash again and again on the same URI, maybe stop trying to load that URI.
if (browser.lastCrashUrlCrashCount >= 3) {
browser.lastCrashUrl = "";
browser.lastCrashUrlCrashCount = 0;
browser.currentUrl = browser.startPage;
}
this.replaceWebView();
});

I also keep track of the last URI that we recovered and how many times we've recovered that same URI. If the same URI crashes more than 3 times in a row then I assume that it will keep happening and I navigate to the start URI instead.

PermalinkCommentsbrowser javascript jsbrowser uwp webview win10

Win10 UWP WebView AddWebAllowedObject details

2017 Sep 4, 3:09

The x-ms-webview HTML element has the void addWebAllowedObject(string name, any value) method and the webview XAML element has the void AddWebAllowedObject(String name, Object value) method. The object parameter is projected into the webview’s top-level HTML document’s script engine as a new property on the global object with property name set to the name parameter. It is not injected into the current document but rather it is projected during initialization of the next top-level HTML document to which the webview navigates.

Lifetime

If AddWebAllowedObject is called during a NavigationStarting event handler the object will be injected into the document resulting from the navigation corresponding to that event.

If AddWebAllowedObject is called outside of the NavigationStarting event handler it will apply to the navigation corresponding to the next explicit navigate method called on the webview or the navigation corresponding to the next NavigationStarting event handler that fires, whichever comes first.

To avoid this potential race, you should use AddWebAllowedObject in one of two ways: 1. During a NavigationStarting event handler, 2. Before calling a Navigate method and without returning to the main loop.

If called both before calling a navigate method and in the NavigationStarting event handler then the result is the aggregate of all those calls.

If called multiple times for the same document with the same name the last call wins and the previous are silently ignored.

If AddWebAllowedObject is called for a navigation and that navigation fails or redirects to a different URI, the AddWebAllowedObject call is silently ignored.

After successfully adding an object to a document, the object will no longer be projected once a navigation to a new document occurs.

WinRT access

If AddWebAllowedObject is called for a document with All WinRT access then projection will succeed and the object will be added.

If AddWebAllowedObject is called for a document which has a URI which has no declared WinRT access via ApplicationContentUriRules then Allow for web only WinRT access is given to that document.

If the document has Allow for web only WinRT access then projection will succeed only if the object’s runtimeclass has the Windows.Foundation.Metadata.AllowForWeb metadata attribute.

Object requirements

The object must implement the IAgileObject interface. Because the XAML and HTML webview elements run on ASTA view threads and the webview’s content’s JavaScript thread runs on another ASTA thread a developer should not create their non-agile runtimeclass on the view thread. To encourage end developers to do this correctly we require the object implements IAgileObject.

Property name

The name parameter must be a valid JavaScript property name, otherwise the call will fail silently. If the name is already a property name on the global object, that property is overwritten if the property is configurable. Non-configurable properties on the global object are not overwritten and the AddWebAllowedObject call fails silently. On success, the projected property is writable, configurable, and enumerable.

Errors

Some errors as described above fail silently. Other issues, such as lack of IAgileObject or lack of the AllowForWeb attribute result in an error in the JavaScript developer console.

PermalinkComments

Application Content URI Rule effects

2017 Jun 30, 3:01

Previously I described Application Content URI Rules (ACUR) parsing and ACUR ordering. This post describes what you get from putting a URI in ACUR.

URIs in the ACUR gain the following which is otherwise unavailable:

  • Geoloc API usage
  • Audio and video capture API usage
  • Pointer lock API usage
  • Web notifications API usage
  • IndexedDB API usage
  • Clipboard API usage
  • window.external.notify access from within webview
  • window.close the primary window
  • Top level navigation in the primary window
  • Cross origin XHR and fetch to ms-appx(-web) scheme URIs
  • Cross origin dirtied canvas read access if dirtied by ms-appx(-web) scheme URIs
  • Cross origin text track for video element for tracks from ms-appx(-web) scheme URIs

URIs in the ACUR that also have full WinRT access additionally gain the following:

  • Cross origin XHR and fetch
  • Cross origin dirtied canvas read access
  • Cross origin text track for video element
  • Local audio and video WinRT plugins work with media elements
PermalinkCommentsapplication-content-uri-rules coding javascript programming windows-store

JavaScript Microsoft Store app StartPage

2017 Jun 22, 8:58

JavaScript Microsoft Store apps have some details related to activation that are specific to JavaScript Store apps and that are poorly documented which I’ll describe here.

StartPage syntax

The StartPage attributes in the AppxManifest.xml (Package/Applications/Application/@StartPage, Package/Applications/Extensions/Extension/@StartPage) define the HTML page entry point for that kind of activation. That is, Application/@StartPage defines the entry point for tile activation, Extension[@Category="windows.protocol"]/@StartPage defines the entry point for URI handling activation, etc. There are two kinds of supported values in StartPage attributes: relative Windows file paths and absolute URIs. If the attribute doesn’t parse as an absolute URI then it is instead interpreted as relative Windows file path.

This implies a few things that I’ll declare explicitly here. Windows file paths, unlike URIs, don’t have a query or fragment, so if you are using a relative Windows file path for your StartPage attribute you cannot include anything like ‘?param=value’ at the end. Absolute URIs use percent-encoding for reserved characters like ‘%’ and ‘#’. If you have a ‘#’ in your HTML filename then you need to percent-encode that ‘#’ for a URI and not for a relative Windows file path.

If you specify a relative Windows file path, it is turned into an ms-appx URI by changing all backslashes to forward slashes, percent-encoding reserved characters, and combining the result with a base URI of ms-appx:///. Accordingly the relative Windows file paths are relative to the root of your package. If you are using a relative Windows file path as your StartPage and need to switch to using a URI so you can include a query or fragment, you can follow the same steps above.

StartPage validity

The validity of the StartPage is not determined before activation. If the StartPage is a relative Windows file path for a file that doesn’t exist, or an absolute URI that is not in the Application Content URI Rules, or something that doesn’t parse as a Windows file path or URI, or otherwise an absolute URI that fails to resolve (404, bad hostname, etc etc) then the JavaScript app will navigate to the app’s navigation error page (perhaps more on that in a future blog post). Just to call it out explicitly because I have personally accidentally done this: StartPage URIs are not automatically included in the Application Content URI Rules and if you forget to include your StartPage in your ACUR you will always fail to navigate to that StartPage.

StartPage navigation

When your app is activated for a particular activation kind, the StartPage value from the entry in your app’s manifest that corresponds to that activation kind is used as the navigation target. If the app is not already running, the app is activated, navigated to that StartPage value and then the Windows.UI.WebUI.WebUIApplication activated event is fired (more details on the order of various events in a moment). If, however, your app is already running and an activation occurs, we navigate or don’t navigate to the corresponding StartPage depending on the current page of the app. Take the app’s current top level document’s URI and if after removing the fragment it already matches the StartPage value then we won’t navigate and will jump straight to firing the WebUIApplication activated event.

Since navigating the top-level document means destroying the current JavaScript engine instance and losing all your state, this behavior might be a problem for you. If so, you can use the MSApp.pageHandlesAllApplicationActivations(true) API to always skip navigating to the StartPage and instead always jump straight to firing the WebUIApplication activated event. This does require of course that all of your pages all handle all activation kinds about which any part of your app cares.

PermalinkComments

Application Content URI Rules rule ordering

2017 Jun 1, 1:30

Application Content URI Rules (ACUR from now on) defines the bounds on the web that make up a Microsoft Store application. The previous blog post discussed the syntax of the Rule's Match attribute and this time I'll write about the interactions between the Rules elements.

Order

A single ApplicationContentUriRules element may have up to 100 Rule child elements. When determining if a navigation URI matches any of the ACUR the last Rule in the list with a matching match wildcard URI is used. If that Rule is an include rule then the navigation URI is determined to be an application content URI and if that Rule is an exclude rule then the navigation rule is not an application content URI. For example:

Rule Type='include' Match='https://example.com/'/
Rule Type='exclude' Match='https://example.com/'/

Given the above two rules in that order, the navigation URI https://example.com/ is not an application content URI because the last matching rule is the exclude rule. Reverse the order of the rules and get the opposite result.

WindowsRuntimeAccess

In addition to determining if a navigation URI is application content or not, a Rule may also confer varying levels of WinRT access via the optional WindowsRuntimeAccess attribute which may be set to 'none', 'allowForWeb', or 'all'. If a navigation URI matches multiple different include rules only the last rule is applied even as it applies to the WindowsRuntimeAccess attribute. For example:

Rule Type='include' Match='https://example.com/' WindowsRuntimeAccess='none'/
Rule Type='include' Match='https://example.com/' WindowsRuntimeAccess='all'/

Given the above two rules in that order, the navigation URI https://example.com/ will have access to all WinRT APIs because the last matching rule wins. Reverse the rule order and the navigation URI https://example.com/ will have no access to WinRT. There is no summation or combining of multiple matching rules - only the last matching rule wins.

PermalinkCommentsapplication-content-uri-rules programming uri windows windows-store

Application Content URI Rules wildcard syntax

2017 May 31, 4:48

Application Content URI Rules (ACUR from now on) defines the bounds of the web that make up the Microsoft Store application. Package content via the ms-appx URI scheme is automatically considered part of the app. But if you have content on the web via http or https you can use ACUR to declare to Windows that those URIs are also part of your application. When your app navigates to URIs on the web those URIs will be matched against the ACUR to determine if they are part of your app or not. The documentation for how matching is done on the wildcard URIs in the ACUR Rule elements is not very helpful on MSDN so here are some notes.

Rules

You can have up to 100 Rule XML elements per ApplicationContentUriRules element. Each has a Match attribute that can be up to 2084 characters long. The content of the Match attribute is parsed with CreateUri and when matching against URIs on the web additional wildcard processing is performed. I’ll call the URI from the ACUR Rule the rule URI and the URI we compare it to found during app navigation the navigation URI.

The rule URI is matched to a navigation URI by URI component: scheme, username, password, host, port, path, query, and fragment. If a component does not exist on the rule URI then it matches any value of that component in the navigation URI. For example, a rule URI with no fragment will match a navigation URI with no fragment, with an empty string fragment, or a fragment with any value in it.

Asterisk

Each component except the port may have up to 8 asterisks. Two asterisks in a row counts as an escape and will match 1 literal asterisk. For scheme, username, password, query and fragment the asterisk matches whatever it can within the component.

Host

For the host, if the host consists of exactly one single asterisk then it matches anything. Otherwise an asterisk in a host only matches within its domain name label. For example, http://*.example.com will match http://a.example.com/ but not http://b.a.example.com/ or http://example.com/. And http://*/ will match http://example.com, http://a.example.com/, and http://b.a.example.com/. However the Store places restrictions on submitting apps that use the http://* rule or rules with an asterisk in the second effective domain name label. For example, http://*.com is also restricted for Store submission.

Path

For the path, an asterisk matches within the path segment. For example, http://example.com/a/*/c will match http://example.com/a/b/c and http://example.com/a//c but not http://example.com/a/b/b/c or http://example.com/a/c

Additionally for the path, if the path ends with a slash then it matches any path that starts with that same path. For example, http://example.com/a/ will match http://example.com/a/b and http://example.com/a/b/c/d/e/, but not http://example.com/b/.

If the path doesn’t end with a slash then there is no suffix matching performed. For example, http://example.com/a will match only http://example.com/a and no URIs with a different path.

As a part of parsing the rule URI and the navigation URI, CreateUri will perform URI normalization and so the hostname and scheme will be made lower case (casing matters in all other parts of the URI and case sensitive comparisons will be performed), IDN normalization will be performed, ‘.’ and ‘..’ path segments will be resolved and other normalizations as described in the CreateUri documentation.

PermalinkCommentsapplication-content-uri-rules programming windows windows-store

Tweet from David Risney

2016 Dec 4, 3:47
Astounding realization during Westworld finale: My wife doesn't care that I can identify all the Radiohead cover titles played on Westworld.
PermalinkComments

Tweet from David Risney

2016 Nov 3, 3:59
@FakeUnicode Spaces are technically not allowed in a URI so the only reasonable representation is percent encoded.
PermalinkComments

Parsing WinMD with .NET reflection APIs

2016 Nov 2, 6:13

Parsing WinMD files, the containers of WinRT API metadata, is relatively simple using the appropriate .NET reflection APIs. However, figuring out which reflection APIs to use is not obvious. I've got a completed C sharp class parsing WinMD files that you can check out for reference.

Use System.Reflection.Assembly.ReflectionOnlyLoad to load the WinMD file. Don't use the normal load methods because the WinMD files contain only metadata. This will load up info about APIs defined in that WinMD, but any references to types outside of that WinMD including types found in the normal OS system WinMD files must be resolved by the app code via the System.Reflection.InteropServices.WindowsRuntimeMetadata.ReflectionOnlyNamespaceResolve event.

In this event handler you must resolve the unknown namespace reference by adding an assembly to the NamespaceResolveEventArgs's ResolvedAssemblies property. If you're only interested in OS system WinMD files you can use System.Reflection.InteropServices.WindowsRuntimeMetadata.ResolveNamespace to turn a namespace into the expected OS system WinMD path and turn that path into an assembly with ReflectionOnlyLoad.

PermalinkComments.net code programming winmd winrt

Tweet from SwiftOnSecurity

2016 Oct 13, 11:02
Give flair to users with 2FA turned on. Make it a status symbol, then public shaming takes over. "U don't have 2FA what if you get hacked?"
PermalinkComments

Tweet from David Risney

2016 Sep 16, 12:10
@ericlaw "Any A.I. smart enough to pass a Turing test is smart enough to know to fail it." http://www.goodreads.com/work/quotes/2440580-river-of-gods 
PermalinkComments

Tweet from emily schechter

2016 Sep 8, 1:12
in Chrome 56, we'll mark HTTP pages with password or credit card form fields as "not secure". turn on HTTPS before! https://security.googleblog.com/2016/09/moving-towards-more-secure-web.html 
PermalinkComments

WPAD Server Fiddler Extension Source

2016 Aug 5, 3:18

I've put my WPAD Fiddler extension source and the installer on GitHub.

Six years ago I made a WPAD DHCP server Fiddler extension (described previously and previously). The extension runs a WPAD DHCP server telling any clients that connect to connect to the running Fiddler instance. I've finally got around to putting the source on GitHub. I haven't touched it in five or so years so this is either for posterity or education or something.

PermalinkCommentsdhcp fiddler network security wpad

WinRT Toast from PowerShell

2016 Jun 15, 3:54

I've made a PowerShell script to show system toast notifications with WinRT and PowerShell. Along the way I learned several interesting things.

First off calling WinRT from PowerShell involves a strange syntax. If you want to use a class you write [-Class-,-Namespace-,ContentType=WindowsRuntime] first to tell PowerShell about the type. For example here I create a ToastNotification object:

[void][Windows.UI.Notifications.ToastNotification,Windows.UI.Notifications,ContentType=WindowsRuntime];
$toast = New-Object Windows.UI.Notifications.ToastNotification -ArgumentList $xml;
And here I call the static method CreateToastNotifier on the ToastNotificationManager class:
[void][Windows.UI.Notifications.ToastNotificationManager,Windows.UI.Notifications,ContentType=WindowsRuntime];
$notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($AppUserModelId);
With this I can call WinRT methods and this is enough to show a toast but to handle the click requires a little more work.

To handle the user clicking on the toast I need to listen to the Activated event on the Toast object. However Register-ObjectEvent doesn't handle WinRT events. To work around this I created a .NET event wrapper class to turn the WinRT event into a .NET event that Register-ObjectEvent can handle. This is based on Keith Hill's blog post on calling WinRT async methods in PowerShell. With the event wrapper class I can run the following to subscribe to the event:

function WrapToastEvent {
param($target, $eventName);

Add-Type -Path (Join-Path $myPath "PoshWinRT.dll")
$wrapper = new-object "PoshWinRT.EventWrapper[Windows.UI.Notifications.ToastNotification,System.Object]";
$wrapper.Register($target, $eventName);
}

[void](Register-ObjectEvent -InputObject (WrapToastEvent $toast "Activated") -EventName FireEvent -Action {
...
});

To handle the Activated event I want to put focus back on the PowerShell window that created the toast. To do this I need to call the Win32 function SetForegroundWindow. Doing so from PowerShell is surprisingly easy. First you must tell PowerShell about the function:

Add-Type @"
using System;
using System.Runtime.InteropServices;
public class PInvoke {
[DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hwnd);
}
"@
Then to call:
[PInvoke]::SetForegroundWindow((Get-Process -id $myWindowPid).MainWindowHandle);

But figuring out the HWND to give to SetForegroundWindow isn't totally straight forward. Get-Process exposes a MainWindowHandle property but if you start a cmd.exe prompt and then run PowerShell inside of that, the PowerShell process has 0 for its MainWindowHandle property. We must follow up process parents until we find one with a MainWindowHandle:

$myWindowPid = $pid;
while ($myWindowPid -gt 0 -and (Get-Process -id $myWindowPid).MainWindowHandle -eq 0) {
$myWindowPid = (gwmi Win32_Process -filter "processid = $($myWindowPid)" | select ParentProcessId).ParentProcessId;
}
PermalinkComments.net c# powershell toast winrt

Windows Store App WebView Cross Origin XMLHttpRequest Behavior

2016 Jun 2, 6:45

TL;DR: Web content in a JavaScript Windows Store app or WebView in a Windows Store app that has full access to WinRT also gets to use XHR unrestricted by cross origin checks.

By default web content in a WebView control in a Windows Store App has the same sort of limitations as that web content in a web browser. However, if you give the URI of that web content full access to WinRT, then the web content also gains the ability to use XMLHttpRequest unrestricted by cross origin checks. This means no CORS checks and no OPTIONS requests. This only works if the web content's URI matches a Rule in the ApplicationContentUriRules of your app's manifest and that Rule declares WindowsRuntimeAccess="all". If it declares WinRT access as 'None' or 'AllowForWebOnly' then XHR acts as it normally does.

In terms of security, if you've already given a page access to all of WinRT which includes the HttpRequest class and other networking classes that don't perform cross origin checks, then allowing XHR to skip CORS doesn't make things worse.

PermalinkCommentsjavascript uwa uwp web webview windows winrt xhr
Older Entries Creative Commons License Some rights reserved.