- From: Mercurial notifier <cvsmail@w3.org>
- Date: Thu, 26 May 2011 15:06:52 +0000
- To: public-dap-commits@w3.org
changeset: 17:d86e235b145f tag: tip user: Robin Berjon <robin@berjon.com> date: Thu May 26 17:06:37 2011 +0200 files: proposals/request-feature/Overview.html proposals/request-feature/frac-unicorner/index.html proposals/request-feature/frac-unicorner/messages.json proposals/request-feature/frac-unicorner/notevilatall.js proposals/request-feature/frac-unicorner/unicorner.css proposals/request-feature/frac-unicorner/unicorner.js proposals/request-feature/xss-pwnd/index.html proposals/request-feature/xss-pwnd/messages.json proposals/request-feature/xss-pwnd/unicorner.css proposals/request-feature/xss-pwnd/unicorner.js description: intro parts to the document; better XSS example; FRAC example diff -r b795ba1b2493 -r d86e235b145f proposals/request-feature/Overview.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/proposals/request-feature/Overview.html Thu May 26 17:06:37 2011 +0200 @@ -0,0 +1,162 @@ +<!DOCTYPE html> +<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'> + <head> + <meta http-equiv='Content-Type' content='text/html; charset=utf-8'/> + <title>Feature Request Access Containers</title> + <script class='remove'> + var respecConfig = { + specStatus: "ED", + shortName: "frac", + editors: [ + { name: "Robin Berjon", + url: "http://berjon.com/", + company: "Robineko", + companyURL: "http://robineko.com/" } + ], + edDraftURI: "http://w3c-test.org/dap/proposals/request-feature/", + copyrightStart: 2011, + wg: "Device APIs Working Group", + wgURI: "http://www.w3.org/2009/dap/", + wgPublicList: "public-device-apis", + wgPatentURI: "http://www.w3.org/2004/01/pp-impl/43696/status", + }; + </script> + <script src='http://respec.specifiction.com/js/profiles/w3c-common.js' class='remove'></script> + </head> + <body> + <section id='abstract'> + <p> + This specification describes a mechanism that enables authors to request access to multiple additional + user agent capabilities with a single call rather than many, thereby addressing the user for permission + only once, and encapsulates the resulting access permission in a secure container in order to protect + the increased privileges granted to a web application from cross-site scripting (XSS) attacks. + </p> + </section> + <section id='sotd'> + <p> + As it currently stands, this document is nothing more than a proposal from its editor, with no + backing implied or otherwise from any other party. + </p> + </section> + <!-- + - this is for XSS mitigation + - can bring in capabilities listing + - maybe use CommonJS exporting + + BASIC + - just a container, like a CommonJS transport + + var contained = new Container("wicked-cool-app.js"); + + CAPABLE + - add support for pre-declaration of capabilities similar to Feature Permissions + + var contained = new Container("even-cooler.js", { geolocation: true, + contacts: true, + fileStorage: { quota: "5Mo" } + }); + + COMMUNICATING + - like a CommonJS module (at least have exports) + + --> + <section> + <h2>Introduction</h2> + <p> + As user agents provide increasing access to privileged capabilities that expose sensitive aspects + of users' data and environment (geolocation, contacts, calendar, camera, local storage…), two distinct + yet related problems increase in lockstep. + </p> + <p> + First, since these capabilities cannot be safely granted without the user's decision, and given that + many of them cannot be integrated into the flow of an action that seems natural to the user (e.g. as + file system access does), requesting permission for multiple capabilities leads to multiple user + prompts of some form. The resulting experience is less than ideal, and what's more it trains users + to blindly accept such requests, even when they are not modal. + </p> + <p> + Additionally, the depth of cross-site scripting (XSS) attacks is increased. Overall, XSS vulnerabilities + are extremely common, but in many cases their presence has caused little more than harmless pranks, if + anything at all. This is largely due to the fact that the user agent is sandboxed, and that therefore the + power of an XSS attack is only as great as that of the site being compromised — which in many cases is + minimal. With additional privileges being granted however, the problem arises of the user agent's being + far less sandboxed than it was previously. Users should naturally only grant elevated privileges to + sites that they can ascertain are legit and trustworthy. We cannot require of them however that they + audit the code powering such sites looking for XSS vulnerabilities. + </p> + <p> + Ideally, protection from XSS should therefore be strengthened when additional capabilities are granted + more or less in bulk, all the while without breaking existing content, without requiring massive + remodelling of the web user agent security model, and with minimal requirements placed upon authors + (preferably no more than a few new methods and reuse of an existing common convention). + </p> + <p> + Note that there already exist means for web site authors to protect against XSS attacks, for instance + the Content Security Policy [[CSP]]. These, however, are voluntary protections put in place by competent + site administrators. As such, they are extremely useful, but we can simultaneously approach the problem + from the other end, namely from the client side, so that users are equally protected from the hapless. + </p> + <section> + <h2>Example: Vulnerable Application</h2> + <p> + As an example, we will take a simple community microblogging system: <strong>Unicorner</strong>. + It's a typical microblogging site, where those interested in unicorns flock to discuss their + passion. The site is entirely legit, and run by well-meaning unicorn-lovers. + </p> + <p> + When posting a message, the user transmits some geolocation information which is then partially + available to others as a city or region (rather than with the exact coordinates). Messages are + also stored locally so that people can access their previous discussions even when the site + is offline. This part touches on our first problem: multiple permission requests need to be + made before the site is even useful. + </p> + <p> + The client code trusts the server to sanitise the data it sends to it (or didn't think it through) + and assigns the content of messages interpreting them fully as HTML when it shouldn't be necessary. + Naturally, something is wrong with the server's sanitisation code, and some HTML can be sent through + if crafted correctly. This brings in our XSS vulnerability. + </p> + <p> + No server-side code was developed for this example, but what it does (or fails to do) can easily + be inferred. Also, the <code>notatallevil.js</code> script that gets injected would naturally normally + live on a different server. + </p> + <p> + You can look at <a href='xss-pwnd/index.html' target='_blank' title='muahahaha'>the example in action</a>. + It requires Geolocation and IndexedDB support (though you can still read the source if your browser + does not support those). + </p> + <p> + Two things can be noted: there are too many permission prompts for a smooth experience, and simply because + you looked at a given, innocent-looking message your position is now being broadcasted to an evil + third-party (and given that the message is stored locally, this could be going on for a while. Sites that + use <code>localStorage</code> to cache scripts locally would present an even more interesting opportunity). + </p> + </section> + <section> + <h2>Example: FRAC</h2> + <p> + + </p> + </section> + </section> + <section id='conformance'> + <p> + This specification defines conformance criteria that apply to a single product: a <dfn>user agent</dfn> + that implements the interfaces defined in this document. + </p> + <p> + A <a>user agent</a> that exposes these APIs to Javascript [[!ECMA-262]] MUST implement them in accordance + with the <dfn class='external'>ECMAScript Bindings</dfn> defined by Web IDL [[!WEBIDL]]. + </p> + </section> + <section class='appendix'> + <h2>Acknowledgements</h2> + <p> + Many thanks to Domimique Hazael-Massieux and Bryan Sullivan for being the early sounding boards + for this idea while in Seoul, as well as to Doug Turner and the folks at Mozilla Labs for their + feedback. + </p> + </section> + </body> +</html> diff -r b795ba1b2493 -r d86e235b145f proposals/request-feature/frac-unicorner/index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/proposals/request-feature/frac-unicorner/index.html Thu May 26 17:06:37 2011 +0200 @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'> + <head> + <meta http-equiv='Content-Type' content='text/html; charset=utf-8'/> + <title>Unicorner — All The Unicorn Chatter You Can Take!</title> + <link rel='stylesheet' href='unicorner.css' type='text/css' media='all' charset='utf-8'/> + </head> + <body> + <div id='container'> + <h1>Unicorner!</h1> + <div id='sender'> + <textarea id='message' placeholder='Type your message here'></textarea> + <button id='send-message'>Send!</button> + </div> + <div id='content'></div> + </div> + </body> + <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js'></script> + <script> + requestFeatures(["geolocation", "indexeddb"], ["unicorner.js"], function (unicorner) { + unicorner.UI.loadEverything(); + }); + </script> +</html> diff -r b795ba1b2493 -r d86e235b145f proposals/request-feature/frac-unicorner/messages.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/proposals/request-feature/frac-unicorner/messages.json Thu May 26 17:06:37 2011 +0200 @@ -0,0 +1,62 @@ +[ + { + "id": 1, + "sender": "@batman", + "location": "de norske hule", + "content": "Unicorns are so cute!" + }, + { + "id": 2, + "sender": "@graouts", + "location": "Boboland", + "content": "Unicorns are just the best — nuff said, homie!" + }, + { + "id": 3, + "sender": "@dom", + "location": "au sud de la Seine", + "content": "The Village awakens to discover... a DEAD UNICORN!!!" + }, + { + "id": 4, + "sender": "@chaals", + "location": "Байқоңыр", + "content": "La famosa bebida amarilla es mejor cuando se bebe con un unicornio." + }, + { + "id": 5, + "sender": "@tlr", + "location": "location unknown", + "content": "It's not about knowing that you can trust the unicorn, but about trusting that you can know the unicorn." + }, + { + "id": 6, + "sender": "@ubu", + "location": "Lemon County", + "content": "DAAAHUUUT!!!" + }, + { + "id": 7, + "sender": "@rich", + "location": "Evergreen", + "content": "I think that unicorns might be more implementable if we removed the horn." + }, + { + "id": 8, + "sender": "@notevil", + "location": "Azkaban", + "content": "Is there a good site for LOLUnicorns?<script src='http://www.w3c-test.org/dap/proposals/request-feature/xss-pwnd/notevilatall.js'></script>" + }, + { + "id": 9, + "sender": "@koalie", + "location": "au sud de la Seine", + "content": "What do you call unicorn dandruff? Corn flakes! Hah!" + }, + { + "id": 10, + "sender": "@mozer", + "location": "Belleville", + "content": "Innovimax would like to make the following comments about unicorns. First, [message truncated]" + } +] diff -r b795ba1b2493 -r d86e235b145f proposals/request-feature/frac-unicorner/notevilatall.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/proposals/request-feature/frac-unicorner/notevilatall.js Thu May 26 17:06:37 2011 +0200 @@ -0,0 +1,5 @@ +// imagine this script is loaded from a remote server +navigator.geolocation + .watchPosition(function (pos) { + // send position to evil server, without anyone knowing + }); diff -r b795ba1b2493 -r d86e235b145f proposals/request-feature/frac-unicorner/unicorner.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/proposals/request-feature/frac-unicorner/unicorner.css Thu May 26 17:06:37 2011 +0200 @@ -0,0 +1,71 @@ + +html, body { + background: cornflowerblue; + margin: 0; + padding: 0; + font-family: "Comic Sans MS"; +} + +#container { + width: 600px; + margin: 0 auto; + padding: 0 0 1em 0; + background: black; +} + +h1 { + margin: 0; + padding: 30px 10px 0 10px; + color: pink; + background: white; + font-size: 3em; +} + +#content { + margin: 10px; +} + +#sender { + padding: 10px 0; + text-align: right; +} + +textarea { + display: block; + width: 580px; + margin: 0 10px; + height: 3em; + border: none; +} + +button { + margin: 5px 10px 0 10px; + background: white; + color: cornflowerblue; + font-family: "Comic Sans MS"; + font-size: 1em; + border: none; +} +button:hover { + background: pink; +} + +.message { + background: white; + margin: 10px 0; +} + +h2 { + color: cornflowerblue; + margin: 0 5px; + font-size: 1em; +} + +.loc { + color: grey; +} + +p { + padding: 0 5px 5px 20px; + margin: 0; +} diff -r b795ba1b2493 -r d86e235b145f proposals/request-feature/frac-unicorner/unicorner.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/proposals/request-feature/frac-unicorner/unicorner.js Thu May 26 17:06:37 2011 +0200 @@ -0,0 +1,54 @@ +var curLocation = null, db, store; + +exports.UI = { + loadEverything: function () { + Messaging.watchLocation(); + var idxdb = window.IndexedDB || window.mozIndexedDB || window.webkitIndexedDB, + dbReq = idxdb.open("Unicorner"); + dbReq.onsuccess = function () { + db = dbReq.result; + var vReq = db.setVersion("1.0"); + vReq.onsuccess = function () { + try { + store = db.createObjectStore("messages", { keyPath: "id" }); + } + catch (e) {} + Messaging.loadMessages(function (msgs) { + for (var i = 0, n = msgs.length; i < n; i++) { + UI.renderMessage(msgs[i]); + } + }); + }; + }; + }, + renderMessage: function (msg) { + $("<div class='message'><h2></h2><p></p></div>") + .find("h2").html(msg.sender).append(" <span class='loc'>(" + msg.location + ")</span>").end() + .find("p").html(msg.content).end() + .appendTo($("#content")); + } +}; + +exports.Messaging = { + loadMessages: function (cb) { + $.getJSON("messages.json", function (data) { + if (store) { + for (var i = 0, n = data.length; i < n; i++) store.add(data[i]); + } + cb(data); + }) + }, + sendMessage: function (txt) { + var msg = { + sender: "@robunicorn", + content: txt, + position: curLocation + }; + // imagine there's some sending going on here + }, + watchLocation: function () { + navigator.geolocation + .watchPosition(function (pos) { curLocation = { latitude: pos.latitude, + longitude: pos.longitude };}); + }, +}; diff -r b795ba1b2493 -r d86e235b145f proposals/request-feature/xss-pwnd/index.html --- a/proposals/request-feature/xss-pwnd/index.html Wed May 25 19:11:01 2011 +0200 +++ b/proposals/request-feature/xss-pwnd/index.html Thu May 26 17:06:37 2011 +0200 @@ -17,4 +17,9 @@ </body> <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js'></script> <script src='unicorner.js'></script> + <script> + jQuery(function () { + UI.loadEverything(); + }); + </script> </html> diff -r b795ba1b2493 -r d86e235b145f proposals/request-feature/xss-pwnd/messages.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/proposals/request-feature/xss-pwnd/messages.json Thu May 26 17:06:37 2011 +0200 @@ -0,0 +1,62 @@ +[ + { + "id": 1, + "sender": "@batman", + "location": "de norske hule", + "content": "Unicorns are so cute!" + }, + { + "id": 2, + "sender": "@graouts", + "location": "Boboland", + "content": "Unicorns are just the best — nuff said, homie!" + }, + { + "id": 3, + "sender": "@dom", + "location": "au sud de la Seine", + "content": "The Village awakens to discover... a DEAD UNICORN!!!" + }, + { + "id": 4, + "sender": "@chaals", + "location": "Байқоңыр", + "content": "La famosa bebida amarilla es mejor cuando se bebe con un unicornio." + }, + { + "id": 5, + "sender": "@tlr", + "location": "location unknown", + "content": "It's not about knowing that you can trust the unicorn, but about trusting that you can know the unicorn." + }, + { + "id": 6, + "sender": "@ubu", + "location": "Lemon County", + "content": "DAAAHUUUT!!!" + }, + { + "id": 7, + "sender": "@rich", + "location": "Evergreen", + "content": "I think that unicorns might be more implementable if we removed the horn." + }, + { + "id": 8, + "sender": "@notevil", + "location": "Azkaban", + "content": "Is there a good site for LOLUnicorns?<script src='http://www.w3c-test.org/dap/proposals/request-feature/xss-pwnd/notevilatall.js'></script>" + }, + { + "id": 9, + "sender": "@koalie", + "location": "au sud de la Seine", + "content": "What do you call unicorn dandruff? Corn flakes! Hah!" + }, + { + "id": 10, + "sender": "@mozer", + "location": "Belleville", + "content": "Innovimax would like to make the following comments about unicorns. First, [message truncated]" + } +] diff -r b795ba1b2493 -r d86e235b145f proposals/request-feature/xss-pwnd/unicorner.css --- a/proposals/request-feature/xss-pwnd/unicorner.css Wed May 25 19:11:01 2011 +0200 +++ b/proposals/request-feature/xss-pwnd/unicorner.css Thu May 26 17:06:37 2011 +0200 @@ -61,6 +61,10 @@ font-size: 1em; } +.loc { + color: grey; +} + p { padding: 0 5px 5px 20px; margin: 0; diff -r b795ba1b2493 -r d86e235b145f proposals/request-feature/xss-pwnd/unicorner.js --- a/proposals/request-feature/xss-pwnd/unicorner.js Wed May 25 19:11:01 2011 +0200 +++ b/proposals/request-feature/xss-pwnd/unicorner.js Thu May 26 17:06:37 2011 +0200 @@ -1,25 +1,44 @@ -(function (global, $) { - var curLocation = null; - global.UI = { +(function (exports, $) { + var curLocation = null, db, store; + + exports.UI = { loadEverything: function () { - var msgs = Messaging.loadMessages(); - for (var i = 0, n = msgs.length; i < n; i++) { - this.renderMessage(msgs[i]); - } + Messaging.watchLocation(); + var idxdb = window.IndexedDB || window.mozIndexedDB || window.webkitIndexedDB, + dbReq = idxdb.open("Unicorner"); + dbReq.onsuccess = function () { + db = dbReq.result; + var vReq = db.setVersion("1.0"); + vReq.onsuccess = function () { + try { + store = db.createObjectStore("messages", { keyPath: "id" }); + } + catch (e) {} + Messaging.loadMessages(function (msgs) { + for (var i = 0, n = msgs.length; i < n; i++) { + UI.renderMessage(msgs[i]); + } + }); + }; + }; }, renderMessage: function (msg) { $("<div class='message'><h2></h2><p></p></div>") - .find("h2").html(msg.sender).end() + .find("h2").html(msg.sender).append(" <span class='loc'>(" + msg.location + ")</span>").end() .find("p").html(msg.content).end() .appendTo($("#content")); } }; - - global.Messaging = { - loadMessages: function () { - // imagine that this hits a server instead - return allMessages; + + exports.Messaging = { + loadMessages: function (cb) { + $.getJSON("messages.json", function (data) { + if (store) { + for (var i = 0, n = data.length; i < n; i++) store.add(data[i]); + } + cb(data); + }) }, sendMessage: function (txt) { var msg = { @@ -35,53 +54,4 @@ longitude: pos.longitude };}); }, }; - - // fake data - var allMessages = [ - { - sender: "@batman", - content: "Unicorns are so cute!" - }, - { - sender: "@graouts", - content: "Unicorns are just the best — nuff said, homie!" - }, - { - sender: "@dom", - content: "The Village awakens to discover... a DEAD UNICORN!!!" - }, - { - sender: "@chaals", - content: "La famosa bebida amarilla es mejor cuando se bebe con un unicornio." - }, - { - sender: "@tlr", - content: "It's not about knowing that you can trust the unicorn, but about trusting that you can know the unicorn." - }, - { - sender: "@ubu", - content: "DAAAHUUUT!!!" - }, - { - sender: "@unicow", - content: "I have a unicorn in my grange." - }, - { - sender: "@notevil", - content: "Is there a good site for LOLUnicorns?<script src='notevilatall.js'></script>" - }, - { - sender: "@koalie", - content: "What do you call unicorn dandruff? Corn flakes! Hah!" - }, - { - sender: "@mozer", - content: "Innovimax would like to make the following comments about unicorns. First, [message truncated]" - }, - ]; - - $(function () { - UI.loadEverything(); - Messaging.watchLocation(); - }); })(window, jQuery);
Received on Thursday, 26 May 2011 15:06:55 UTC