Testing HTTPS Locally

As I’m migrating the player over to HTTPS, one challenge is partial content, leading to an incomplete padlock and strikethrough domain warning like this:

And the harsh but fair warning, upon inspection: “However, this page includes other resources which are not secure. These resources can be viewed by others while in transit, and can be modified by an attacker to change the look of the page.”

So to fix this locally, a nice setup for Ruby/Rails devs is Pow + Tunnels. Both are super-simple to setup.

Pow is a local server, so if you usually run Rails on http://localhost:3000, you can one-click install Pow and all you need is to symlink your Rails folder to ~/.pow. Then you have a local server, sans port, like http://player.dev. Then, just install Tunnels and it will simply pipe https://player.dev into http://player.dev.

Now you can open Chrome devtools’ resource tab and fish out any connections which are still https. Ideally host them locally, or at least change the links to https ones at possible loss of cache performance. Still, did you see various posts recently about ISPs injecting crapware script tags into people’s pages? OMG I know right! Seriously, https-everywhere is where the web is heading. Even public sites aren’t immune.

Login Best Practices for Mobile Web Apps

Walking home, I thought I’d venture to make a meal order via my phone…and without making a phone call. It shouldn’t be an ordeal to do so in 2011, but frankly a sense of learned helplessness means I haven’t even tried before. I know, #FirstWorldProblems, but let’s learn something from it.

Anyway, I pull up my favourite meal delivery service, Hungry House (highly recommended! At least in London.) I simultaneously launch a Market search for a Hungry House app – right or wrong, we know mobile app experience is almost always smoother. Well, no app, but the web page loads…and a bunch of antipatterns emerge.

Instead of documenting login antipatterns, I’ll make this post more useful by turning them around and proposing best practices for mobile web login. Beware it’s all speculative and subjective.

Zen Login Form

Make a simple, mobile-optimised, login form. Make sure it’s easy to click on each field to focus them (there’s only two of them!). Make sure any links (“forgot password”, “sign up”) are far enough away they won’t accidentally be licked.

This is true of all mobile web forms, not just login one. But if your app only works behind a login form, this would be the first one to optimise.

“Keep Me Logged In” should default to On

It’s a mobile phone, not an internet cafe, so yeah. Admittedly, this is trickier in the case of a tablet, but still it’s only a default, I’m not saying “hide the option altogether”. Also, form factor detection ftw.

Don’t Expire the Login Cookie

Okay, this will be controversial. But if mobile web apps are to be a viable alternative to mobile-native apps, they should provide the same login experience. Right now, a majorly overlooked distinction is login expiry. I find myself having to login to Twitter all the time, when trying to tweet from some other web app. But with the Twitter mobile app, I’m always logged in. Basically, mobile-native apps never expire the session. Most of them probably don’t even bother with a session/token, they probably just store the user’s credentials in plain text on the device (just some speculation on my part, based on the “see no evil” principle, given that this data is fairly invisible, being stuck in the app’s data storage.) At least a cookie, if found by someone else, doesn’t compromise the entire account, and can easily be expired.

Keep it Light

Needless to say, don’t load so much that the browser crashes. Repeated browser launches makes users hungry.

Mark Miller on Securing JavaScript: More Qcon Live Blogging

Google Research’s Mark Miller is presenting a talk on Caja and web security. He emphasises that this is all bleeding-edge; no current browser fully supports this yet.

There are a ton of attack vectors for browsers, as shown on the Caja wiki. There are spec vulnerabilities, implementation vulnerabilities, and an ongoing arms race emerges. Mark shows a table of numerous variables for each browser, where the variation is not just wild but more or less random. The attacker only need to find one vulnerability here.

Perhaps the ongoing cat-and-mouse game means there’s something wrong with the whole identity-centric paradigm. Instead, maybe we can look at access control – don’t worry about who’s sending the request, worry about if the request has the correct level of access.

Mark walks us through the history of web kludges – JSON and Comet for cross-domain calls and streaming, respectively. HTML5 gets us towards a truer web of distributed objects, which all leads towards a symmetric network.

Safe Mobile Messages: Uniform XHR

Uniform as in “Uniform Resource Location”.

The proposal is for the server to ignore browser’s “helpful” extras.

Authorise based on payload. HTTPS URL or request body – info the requestor knows.

HTML5 allows servers to waive response protection using “Access-Control-Allow-Origin: *”.

Mobile Code

How do you mix coded from multiple untrusted sources into the same frame?

To solve this problem, we bring other security models to the world of JavaScript. With EcmaScript 3, Caja had to perform complex, server-side, translation with a runtime overhead.

The lessons of this effort were taken to the Ecmascript committee, and accordingly, EcmaScript 5 is one of the easiest OO languages to secure, instead of one of the hardest, as was the case previously.

Security as Extreme Modularity

This view treats security as an extreme form of modularity (ie the mutually suspicious components are seen as modules). Vulnerability is a form of dependency…so improving security also helps in other aspects, ie. makes the architecture cleaner.

So we marry up these closely related principles: * Software Engineering Principle of info hiding: Need to know. * Security Engineering Principle of least authority: Need to do.

These are the rules enforced: * Memory safety and encapsulation * Effects only by using held references * No powerful references by default

Objects as Closures

javascript
< view plain text >
  1. function makeCounter() {
  2.   var count=0;
  3.   return {
  4.     incr: function() { return ++count; }
  5.     decr: function() { return --count; }
  6.   };
  7. }

A record of closures hiding state is a fine representation of an object of methods hiding instance variables.

With “use strict”, we can enforce freezing of values. So if you have object A which depends on object B, object A can freeze properties of object “B” to make sure the reference doesn’t change. An important aspect of this is the ability to feeze a prototype.

For now, we have the “initSES.js” library. It monkey patches away bad non-standard behaviours, freezes whitelisted global variables…among other measures.

There’s a concept of membranes (wrappers) to encapsulate/secure message passing. e.g. if you don’t trust object X, you can make a read-only version of its return value. It’s also possible to wipe out what’s inside the membrane at some later stage, if desired. Even if that thing had references to external objects, only what was inside the membrane will be wiped.

TiddlyDocs User Authentication – Generic Design and Custom Features

We are working on a design that will keep TiddlyDocs as generic as possible. The core TiddlyDocs product will have a concept of “rooms”. This is the same kind of room you see in online forums or chat sites, where everyone inside the room contributes and sees content inside the room they’re in, and can’t see or do anything about rooms they’re not in.

Our design works like this. Each room is a recipe of several room-specific bags, along with a global config bag. Each room is associated with a unique user role.

Note the role is used inside the respective bags’ policy files, and they each vary somewhat. e.g. the comments bag says readable by everyone in ‘role’, appendable (“create tiddler” permission) by everyone in ‘role’, editable by “#(role)_admin”. (ie there is a second role called “role_admin”.); whereas the content bags says readable and writeable and editable by everyone in ‘role’; and the config bag says readable by everyone in ‘role’, appendable by ‘#{role}_admin”.

For now, there’s a “makeroom” script that generates the recipe, the bags and the policies. (I’d ideally like to see the recipe be “magic” in some respects, using a wildcard mechanism).

That’s the basic design. We also have some unique challenges in this particular installation – (a) users are authenticated using a custom, enterprise-specific, single-sign on solution, where the incoming header for each request identifies user’s ID and (effectively) company; (b) we have certain rooms whose composition is manually configured and are a subset of the company’s membership, and we also have a “everyone” room which is automatically composed of everyone in the company (e.g. we might have a “megacorp-everyone” room along with the manually configured “megacorp-accounting” room, and “megacorp-marketing” room); (c) to let users allocate specific TiddlyDocs to users, we need a dropdown containing real names of all users.

BTW I’m simplifying some of the finer details here to make the discussion more pertinent to the general topic of TiddlyWeb/TiddlyDocs, rather than our specific problem. All of the following will be developed as proprietary plugins for our own installation. It’s a somewhat complicated set of requirements because it’s a real-world enterprise problem, where we have specialised requirements, combined with integration issues where we can control some things, but can’t control others. (e.g. We can’t change the underlying user store, where we would ideally store which rooms a user is in, instead of holding secondary user records inside TiddlyDocs.)

We will be building a TiddlyWeb plugin that sets the “extractor” filter. This is one of the several filters the request is subject to, on the way into TiddlyWeb. It is usually paired with the challenger filter – where challenger might present a username/password form and set a cookie, and extractor will read the cookie and set usersign (aka user ID) and any other info like users’ roles. In this case, though, we already have the header set, so we don’t need a challenger at all. We simply need an extractor that sets the usersign from the incoming header, and also notes the user’s company. Verification will then check that (a) if the user is attempting to access the “everyone” company room, they are a member of the company; (b) if the user is attempting to access a “manual” company room, they are a member of the company and they have the role associated with the company. We use a naming convention to determine which company a manual room belongs to.

On (c), we need a tiddler in the room “config” bag containing a list of user names. So in addition to the custom extractor, we will also need a periodic script to poll the user store associated with the SSO system. This will give us all the info about users in each company, so we can build up a mapping from company to list of users, where each user record has an ID and name. company->list[{user ID, user name]}. The script will then (a) rewrite the list of user names for the “everyone room” based on the company list, by effectively “copying” the results for that company (b) rewrite the list of user names for each manual room, by walking through each user, checking their roles, and accumulating their user name into the room list for each room they’re in (c) do some cleanup – removing TiddlyWeb records for any users not in the list.

There’s nothing very elegant about these custom implementations, and I’ve primarily written these details for the benefit of myself and colleagues who are implementing these custom features. The more interesting, general, point here is about open-source and plugins. TiddlyWeb’s architecture allows us deliver a generic solution for TiddlyDocs rooms, which is applicable to any organisation, and we can then superimpose a custom feature using the plugin mechanism. Furthermore, the plugin mechanism is a great way to decouple concerns – plugins are moduels on steroids. The core TiddlyDocs developer can concentrate on building an open-source, functional, multi-room TiddlyDocs edition, using the default authentication mechanism. Meanwhile, other developers can work in parallel on custom plugins.

(This post is a refinement of this post; we have been doing further thinking as we get closer to the final product and we learn more about our external environment.)

Explaining the “Don’t Click” Clickjacking Tweetbomb

I just noticed some of my Twitter friends posting the following mysterious message:

“Don’t Click: http://tinyurl.com/amgzs6″

It turns out this is a Tweetbomb. If you go to that link and click on the button below, you end up tweeting the same thing:

… thus all your friends see it and some of them click on it and re-post it, and so on, thus propagating the message across the entire Twittersphere.

TinyURL shut down the redirect quickly and Twitter has responded, but the same attack could arise unless measures are taken. Of which, more later.

So how does this hack work?

The hack is an example of clickjacking. (I’ve heard the term a lot, but only understood its meaning after the investigation of this tweetbomb described here.)

Firstly, it’s using an iframe to embed Twitter.com on the page. The iframe is essentially invisible, due to the CSS structure…more on that in a moment. But first, looking at the source of the iframe, we spot our mysterious message:

<iframe src="http://twitter.com/home?status=Don't Click: http://tinyurl.com/amgzs6" scrolling="no"></iframe>

Well, I didn’t know about this before, but it turns out you can set an initial value for the status field by passing in a “status” parameter on the URL. So here, it’s setting the status to out mysterious message. You can try it yourself by visiting http://twitter.com/home?status=Don’t Click: http://tinyurl.com/amgzs6. (It’s safe to do so – nothing will get submitted, honest!) For the lazy and untrusting ;), what you’ll see at that URL is something like this, assuming you’re logged in to Twitter:

However, their job is not done yet, because they also have to trick you into clicking the “update” button. This is where more cunning comes into play. Check out the CSS for the iframe – containing your Twitter.com page – and the fake button contained on this trickster website:

  1. iframe {
  2.             position: absolute;
  3.             width: 550px;
  4.             height: 228px;
  5.             top: -170px;
  6.             left: -400px;
  7.             z-index: 2;
  8.             opacity: 0;
  9.             filter: alpha(opacity=0);
  10.         }
  11.         button {
  12.             position: absolute;
  13.             top: 10px;
  14.             left: 10px;
  15.             z-index: 1;
  16.             width: 120px;
  17.         }

And the elements:

<iframe src="http://twitter.com/home?status=Don't Click: http://tinyurl.com/amgzs6" scrolling="no"></iframe>

<button>Don't Click</button>

We can see from the CSS z-indexes, the iframe is on top of the button. And we can see from the iframe’s opacity that it is completely invisible. Hmmm…so it’s on top, but completely invisible. If there was a button there, you wouldn’t be able to see it, but you would still be able to click on it. This is where the layout comes in (position, width, height, top, left). The iframe is positioned just right so the the (invisible) update button appears in the top-right of the web page at (10,10), right where the fake button is. So the Update button is directly above the fake button but invisible. The website shows a fake button and tempts you to click on it, but clicking on it causes the real Twitter button – inside the iframe – to fire. Thanks to the URL status hack, you have just submitted their planted message. And of course, you couldn’t see the message, because the iframe is hidden and because that part of the iframe is not present anyway due to the negative left and top settings. There is also some filler text on the trickster page, below the fake button – I guess this is in case some browsers expand the iframe height if nothing else is on the page.

The main way Twitter can prevent this kind of attack is to use the old “bust the iframe” idiom. As I explained in Cross-Domain Communication with IFrames, it’s possible for an iframe to access the URL of its container, and actually re-set that value. Thus the common pattern:

javascript
< view plain text >
  1. if (top.location.href != self.location.href)
  2.      top.location.href = self.location.href;

If Twitter had that code on its web page, whenever it was loaded inside an iframe, the user would see the entire page clear and refresh to become the Twitter URL that was in the iframe. I actually think it’s a shame they would have to resort to something like that, because there are valid uses for iframes, as WebWait demonstrates. Any site that uses this pattern cannot bathe in the warm glow of WebWait :). But I can see why sites need to take this measure. (Update: Twitter has updated their code to bust out of the cache, just after I posted this!)

Frame-Busting Gadgets

In the questions after my @media ajax talk, Simon Willison asked about frame busting. If gadgets sit inside iframes, what’s to stop them from busting the frame, i.e. replacing the container with another website. I notice he made a similar comment when OpenSocial came out. If a gadget can cause iGoogle to go away in place of another website, it could for example launch a phishing attack by presenting a mock iGoogle login page (“iGoogle has timed out. Please re-enter your username and password.”).

At a technical level, there is actually nothing to prevent this. There’s no magic in the container. IFrames are about as good as it gets in modern browser for taming the gadgets, but there are still problems with that model, and one of those is the ability for iframes to bust out. I decided to create a demo of this. The gadget is here. You can drop it into iGoogle and see for yourself. Video below:

[kml_flashembed movie="http://picupper.com/video/framebust.swf" height="700" width="400" /]

(Parenthetically, the video is vertical. Why are videos always horizontal on the internets? It’s a computer, not a TV! It should be just as easy to embed an dodecahedron video if that’s what I fancy at the time.)

At this stage, there’s no technical way around this. One possibility would be for the container to do something in the rarely-used onexit() method, which runs just before the new page is loaded. However, as I learned with WebWait, which is also vulnerable to frame-busting, there’s nothing you can really do at that stage, and you can’t determine if the exit is happening because of a frame-busting event as opposed to the user just typing in a new URL. I suppose onexit() could still be used to log info to the server – if you knew all the times the container exits and which gadgets were present at that time, you might find certain (malicious) gadgets were present more times than you’d expect if they were present randomly. Although, I’m not sure about how reliable it is to make an Ajax call in the onexit(). (In this case, though, it would only need to work some of the time.)

In the future, the technical solution is Caja, if it proves to be production-ready. Caja ensures a safe subset of Javascript, so a container like iGoogle would only ever serve a gadget if it was verified to be safe.

Until then, we have to rely on “social” mechanisms. i.e. user comments in the catalogue and manual checking by container staff. A while ago, iGoogle made it harder to add a gadget directly by URL – you basically have to use the catalogue unless you’re a developer. So the catalogue is effectively acting as a whitelist – once found to be malicious, a gadget could be removed. This isn’t simple though – gadgets are dynamic and the catalogue is effectively just a list of URLs. A malicious author could have their gadget added to the catalogue and then change it, so the gadgets need constant review – a highly ineffective process.

I also mentioned in the presentation that “html” type gadgets are more recommended than “url” gadgets. This is partly because with html gadgets, the container at least has some idea of what’s happening inside the gadget – though not entirely, since the code can still reference external scripts and services. With “url” gadgets, what happens is entirely controlled by an external server.

OAuth-OpenID: You’re Barking Up the Wrong Tree if you Think They’re the Same Thing

OAuth, OpenID…they sound like the same thing and they kind of do vaguely similar things But I’m here to tell you, OAuth is not Open ID. They have a different purpose. I’ve been playing around with OAuth a bit in the past couple weeks and have a grip on what it’s aiming to do and what it’s not aiming to do.

To start with, here’s what OAuth does have in common with Open ID:

  • They both live in the general domain of security, identity, and authorisation
  • They are open web standards. Created and evolved by people with an itch to scratch and evolved pragmatically by a loose, fluid, alliance. Think REST, not SOAP. Think Bar Camp, not The 25th Monosemiannual International Convention for the Society of Professionals who Devise Acronyms Quite a Bit.
  • They both celebrate decentralisation. There is no central Open ID or OAuth server that holds all the security information in the universe (cf Passport). Anyone can set up as a server or a client.
  • They both involve browser redirects from the website you’re trying to use – the “consumer” website – to a distinct “provider” website, and back again. Meanwhile, those websites talk to each other behind the scenes to verify what just happened.
  • The user can actively manage the provider website, exerting control over which websites can talk to it and for how long.

With that much in common, the casual observer could be forgiven for confusing them. But they’re different. Not different as in “vying to be the no. 1 standard”, but different as in “they let you do different things”. How so?

Open ID gives you one login for multiple sites. Each time you need to log into Zooomr – a site using Open ID – you will be redirected to your Open ID site where you login, and then back to Zooomr. OAuth lets you authorise one website – the consumer – to access your data from another website – the provider. For instance, you want to authorise a printing provider – call it Moo – to grab your photos from a photo repository – call it Flickr. Moo will redirect you to Flickr which will ask you, for instance, “Moo wants to download your Flickr photos. Is that cool?”, and then back to Moo to print your photos.

With OAuth, you still need to log into the provider. e.g. When Moo sends you to Flickr, you still have to log into Flickr (or be logged in already). How Flickr decides you’re logged in is completely orthogonal to OAuth. It could be a standard username-password login, it could be via a physical password device, or it could well be via Open ID.

With Open ID, there is no suggestion of two web apps sharing your data. Except in the very limited sense that the Open ID provider may hold some general information about you, e.g. some photos, addresses, phone numbers, etc., and with your consent, send it back to the consumer so you don’t have to re-enter all the boring profile details again. However, this is data of a generic, non-application-specific, nature. (And even this limited form of sharing is an extension to the core Open ID spec.) With OAuth, any information you hold on any website can be shared with another website. You could share your GMail with a clever consumer that automatically tags items by inspecting the content, if GMail was an OpenAuth consumer.

Or you could copy your GMail address book into Facebook, by allowing Facebook to read your GMail account. Right now, the only way to do that is to give Facebook your GMail username and password. Clearly a dumb thing to do, and that’s exactly the kind of thing OAuth is set up to prevent. OAuth prevents it by explicitly asking you if you want to let Facebook grab your details from the provider. That’s not a problem Open ID solves. Even if Facebook and GMail used Open ID and you had accounts with both against the same Open ID, you still couldn’t get Facebook to read your GMail account. The Open ID provider wouldn’t let Facebook log in to GMail as if it was you. Even if an Open ID extension came along to allow it, you wouldn’t want it. It’s too coarse-grained and would allow the consumer to do too much potential damage. OAuth is more fine-grained – consumers can do some things with your provider data, not everything.

Ajax Functionality and Usability Patterns – Podcast 4 of 4: Functionality Patterns

This is the fourth and final podcast in the series on Ajax functionality and usability patterns (Book: Part 4, pp 327-530). This 54-minute podcast covers seven patterns of Ajax Architecture (Book: Chapter 17, pp 473-530):

Dedicated to the Nitobians, whose last podcast inspired me to crank another one out again. Recent events suggest it may cost me $5000 to appear on their podcast again, and as Andre points out in this podcast, the same applies for them appearing on my podcast. Thus, my simple proposal would be:

  1. Each of us appear on the others’ podcast, at $5000 each. Actually, let’s make that $50k each.
  2. Cancel the debt
  3. Now each of us can claim our podcast attracts guests who pay $50k to appear. Enough to cover headsets ($20), bandwidth ($10/month with Libsyn), and assorted beverages (name your price).
  4. Profit!!!

Soon I’ll be publishing the final podcast in the overall series, which has already been recorded, and then I’ll be taking it in a more general direction akin to the topics on this blog – talking about agile, programming (Java/Rails/etc), usability, Web2.0, as well as Ajax and the coming revolution of real-time webapps. If you have a skype account and you’d like to join me sometime, drop us an email ([email protected]). Also feel free to suggest any topics that would be good to cover.

Wikipedia as a Honeypot

How long until wikipedia becomes a honeypot?

“Who wants to be a millionaire” contestant is struggling to answer the question, “What year did the Fonz jump the shark?”, and calls out to Lifeline Buddy. Back in 2005, Lifeline Buddy would have googled for the answer. But this is 2007, and “wiki” is now a household name (the media refers to “wiki” and “wikipedia” interchangeably). Lifeline Buddy bangs out “fonz jump shark” into wikipedia’s search field and quickly finds the right page, reporting confidently the year was 1975. Only, it’s wrong; Fonzarelli, of course, jumped the shark in 1977. The producers had entered the fraudulent details at precisely the moment the lifeline was consulted. Contestant takes his $1000 consellation and exits, muttering something about the Britannica under his breath.

Producers wouldn’t stoop so low? If the BBC can do it, draw your own conclusion. The Register, in any event, would have a field day with their latest whipping boy.

Instead of restorting to restricting edits, wikipedia first needs to try out a “heat map” view to help people decide how stable the information is. Not as gaudy as the Ajax Patterns authoring heatmap (using a more subtle theme now), but some way for people to know what’s new and what’s old. Again, this comes back to the idea of separating out wiki content from presentation, ideally using some kind of web service. A wiki needs more than one view, even without any Maps/Flickr/Delicious mashup. For example, you could have three standard views:

  • Pure wiki reading, just like wikipedia today.
  • Stability view. e.g. Most content in white as now, but with a few shades of grey to distinguish how old each phrase is (darker grey = past minute, medium grey = past hour, light grey = past day; so a phrase “graduates” from grey to white as it matures).
  • Inspection mode. Full-on data mining interface, using Ajax (of course) to explore history, drill down to author info, etc.