23 December 2011

Book Review: The Tangled Web

Browsers are not secure. They won’t ever be invincible to malicious attacks. Browser A does not serve the same set of security mechanisms as Browser B. These points are highlighted in Michal Zalewski’s book “The Tangled Web: A Guide to Securing Modern Web Applications”, but Zalewski, an expert in browser security and author of Google’s Browser Security Handbook, discusses in detail common and known vulnerabilities, providing hints and tips to keep web applications as secure as possible along the way.

The book starts with a relatively exhaustive dissection of the “Anatomy of the Web”, highlighting the history of the web, from HTTP up to Plug-ins such as Flash and Silverlight all while noting some of the varying browser implementations of many common web functionalities. For example when discussing the Content-Disposition Header, Zalewski notes that these headers “are truncated at NUL by Internet Explorer, Firefox, and Chrome but not by Opera or Safari”,

In parts Two and Three of the book, the meat of browser security features are discussed in depth. Highlights include a detailed look at the Same Origin Policy for all aspects of the modern web, including Scripts, XHR, Cookies, and Plugins. Another intriguing look into browser inner workings was the sections on special psuedo urls such as about:, javascript:, and data: and how these can lead to interesting handlings of the origination of the requests across browser implementations. For example about:blank can be navigated to from an Existing non-same-origin page and have its origin inherited from the caller in Firefox, Webkit, and Opera while gaining a unique origin in Internet Explorer.

Perhaps one the most valuable parts of “The Tangled Web” is how Zalewski adds a handy “Security Engineering Cheat Sheet” to the end of each chapter. Having these quick tips at ones fingertips is a remarkable asset and great addition to the book. I could continue to outline the great parts of this book, and tout the security expertise that jumps from the pages, but the most important parts in the book are what each reader takes away. Whether its a small attack vector that a reader picks up on to close a vulnerability in their own web application, or an interesting fact about browser inconsistencies, each reader should gain something from this book. For me, the take away is that as a developer there is no magic bullet and we will always uncover new security holes in our web applications, either from poor programming, or new features of a browser’s implementation. And that our expectations should not be that we have a perfectly impenetrable web, or are capable of producing one. Zalewski puts it like this, “As the complexity of our online interactions approaches that of real life, the odds of designing perfectly secure software are rapidly diminishing”

19 December 2011

Canvas, History, Local Storage and More

A few months ago I entered the August Mozilla Dev Derby, which focused on the History API. I have seen some of the amazing things that the new changes to this interface have been able to make from folks like Facebook and GitHub but I wanted to try something a little different. I had been hacking on a simple drawing canvas and decided that I could leverage the History API to create a more application like experience. Since winning the Derby, I’ve seen my code improved and extended in a later Dev Derby Entry, and I turned it into a sample application for Mozilla’s new App experience. Here’s a peek into the process of creating a drawing demo like the one I created.

Basic Setup

Firstly, we’re going to need to create a canvas. This is pretty straightforward for those who have done this sort of thing before, but for a reminder that can look like the following
    <!DOCTYPE html>
    <html>
    <body>
     <div id="content">
        <canvas id="canvas" height="500" width="500"></canvas>
     </div>
    </body>
    </html>
Now that we have our canvas we can start to initialize it and get ready to roll with the fun features we’d like to demonstrate.
var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    img, //more about this later
    blankCanvas = true; //this too
We now need to set it up to allow for drawing. This is done by adding a event listeners to the mouse events we’d like to watch.
window.addEventListener("mousedown", setupDraw, false);
window.addEventListener("mousemove", setupDraw, false);
window.addEventListener("mouseup", setupDraw, false);
You’ll notice the setupDraw function is called on all of these events. This function will grab the coordinates of our pointer (less the offset of our lovely #content div and send those to our draw object.
function setupDraw(event) {
    var cnt = document.getElementById("content"),
        coordinates = {
            x: event.pageX - cnt.offsetLeft,
            y: event.pageY - cnt.offsetTop
          };
    draw[event.type](coordinates);
};
Now time for the drawing I’ll go ahead and let you peek at the source so you can follow along.
var draw = {
    isDrawing: false,
    mousedown: function(coordinates) {
        ctx.beginPath();
        ctx.moveTo(coordinates.x, coordinates.y);
        this.isDrawing = true;
    },
    mousemove: function(coordinates) {
        if (this.isDrawing) {
            ctx.lineTo(coordinates.x, coordinates.y);
            ctx.stroke();
        }
    },
    mouseup: function(coordinates) {
        this.isDrawing = false;
        ctx.lineTo(coordinates.x, coordinates.y);
        ctx.stroke();
        ctx.closePath();
      }
};
You’ll see this object directs to an event type specific function and handles the coordinates parameters which are passed into the object. Following some basic canvas drawing steps for ctx.beginPath() -> ctx.moveTo(x,y) -> ctx.lineTo(x,y) -> ctx.stroke() -> ctx.closePath() we now have the ability to draw with our mouse. The “isDrawing” property is there to let us know to continue our strokes on mousemove. Now that we have an example that allows us to draw, we’ll move forward to make it more interesting by utilizing the History API and LocalStorage.

About the History API

One of the new features in HTML5 (an subject of the Dev Derby) is the additional features of the History API. These are history.pushState(data,title [,url]) and history.replaceState(data, title [,url] ) which are utilized to directly push (or replace) data in the session history. For the purposes of this demo we’ll be using pushState to add data, specifically the image data from the canvas, to the current URL. Now this alone is not enough we will also need to know when the current state changes, which is made accessible to us via the window.onpopstate event. This event fires when the browser gets a new history event. We can inspect the event to see if it contains a state and then load the data (hopefully our image) into the canvas. So to get things wired up correctly, its time to add a function to store the history.
var storeHistory = function () {
    img = canvas.toDataURL("image/png");
    history.pushState({ imageData: img }, "", window.location.href);
};
This grabs the data from the canvas in the form of a “data:image/png…” url. Then we create a new history state by pushing an imageData attribute for later retrieval. Now, before we add the calls to storeHistory to our drawing application, we need to do a bit of preventative maintenance. If we store this data and navigate backward without a reinitialization of the canvas, we will just draw the stored imageData onto the existing image. To us this will look like it isn’t working so we need to add an initialization function to reset our canvas.
var initializeCvs = function () {
    ctx.lineCap = "round";
    ctx.save();
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.restore();
}
Now we can go about the business of storing our history states. The code that follows will store history in two places. The first place it stores is if the canvas is blank it stores that before drawing anything. The second is on the mouseup event after the line is completed. Now our draw object looks like this:
var draw = {
    isDrawing: false,
    mousedown: function(coordinates) {
        if (blankCanvas) { storeHistory(); blankCanvas = false; }
        ctx.beginPath();
        ctx.moveTo(coordinates.x, coordinates.y);
        this.isDrawing = true;
    },
    mousemove: function(coordinates) {
        if (this.isDrawing) {
            ctx.lineTo(coordinates.x, coordinates.y);
            ctx.stroke();
        }
    },
    mouseup: function(coordinates) {
        this.isDrawing = false;
        ctx.lineTo(coordinates.x, coordinates.y);
        ctx.stroke();
        ctx.closePath();
        storeHistory();
    }
};
Awesome, now we have started storing history on the page with each completed line. Now we need to be able to see the results of this work when the history state changes. As I mentioned earlier this is done via the window.onpopstate event. We will examine the imageData of the state (if it exists) and place that image on the canvas as follows:
 window.onpopstate = function (event) {
        if (event.state !== null) {
            img = new Image();
            img.onload =function () {
                ctx.drawImage(img, 0, 0);
            };
            img.src = event.state.imageData;
        }
    };
Splendid, we now have a drawing tool that stores history so we can undo and redo drawings. But wait! What happens if I’m in the middle of a canvas masterpiece and my browser crashes? Lets handle that with localStorage. With localStorage we can store a named item locally independent of our session, so in the event of leaving the page, we can retrieve data from our previous encounter. In this demo I did a simple test of the window.localStorage object to see if we can store data, and then I store the latest image so upon return you’ll at least be able to recover that data. Here are the initializeCanvas and storeHistory functions with this additional feature added:
var initializeCvs = function () {
    ctx.lineCap = "round";
    ctx.save();
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.restore();

    if (window.localStorage) {
        img = new Image();
        img.onload = function () {
            ctx.drawImage(img, 0, 0);
        };
        if (localStorage.curImg) {
            img.src = localStorage.curImg;
            blankCanvas = false;
        }
    }
}

var storeHistory = function () {
    img = canvas.toDataURL("image/png");
    history.pushState({ imageData: img }, "", window.location.href);

    if (window.localStorage) { localStorage.curImg = img; }
};
You can see the full working demo in this jsFiddle.

11 November 2011

Moving to Octopress

I started blogging here a while back, mostly about the cloud and what I could do with my cool new chromebook the cr-48.  I've hacked around a bit in the cloud using Chrome OS, but I find myself enjoying Ubuntu on my cr-48 more than Chrome OS.  In my playing around with different sites, IDEs, tools, and engines I came across Octopress and thought it would be fun to try it out.  So I did and I liked it.  From there I decided to move my blog over there for future posts.  I went through the work to convert these blogger posts from here -> go-cloud-go.blogspot.com (now blog.cgack.com)  to their new home at cgack.com/blog but they likely aren't all picture perfect so if there are broken links or anything I apologize.  So there you have it. this blog is moving to its new home at cgack.com/blog

24 October 2011

Firefox Add-on Automated Updates

Since Firefox moved to a rapid release cycle, there has been concern by some (including myself) as to whether add-ons would stay compatible with each of the new versions, and how one would go about testing to find any breaking changes.  In news that makes a geek happy - Mozilla has taken care of that for me as I received notice from Mozilla that stated:
Dear add-on author,

Good news! Our automated tests did not detect any compatibility issues with your add-on Google Music Hotkeys and Firefox 9.*. We've updated your add-on's compatibility to work with Firefox 9.* so that our Aurora users can begin using it.
This compatibility bump is server-side and we did not modify your add-on package in any way. If you wish or need to revert this change, just go to your add-on edit page on addons.mozilla.org, select the Status & Versions page, then the version, and change its maxVersion compatibility back to its previous value.

For more information on our new compatibility process with rapid Firefox releases, please read this post: http://blog.mozilla.com/addons/2011/04/19/add-on-compatibility-rapid-releases/

22 October 2011

Snakes in the Cloud


I used to think that building web applications in Python for Google's app engine was reserved for a desktop development environment.  I had hacked a bit on an app or two and used the command line tools to test and publish to the app engine.  Then I discovered CoderBuddy.   CoderBuddy is a one stop shop for building python apps for the app engine.  Once signed in you can create a blank project, or get a head start with one of six template apps.  One template is of course a "hello world" app, but there are a  few other samples including 3 that come with some Django (arguably the go to MVC framework for python web applications).   I tested a couple of the template apps and found them to be quite useful.  The "Adrian Remembers Me" template creates an app that allows users to become members and sign in.   Here is a look at the editor with the main.py file opened for this project:


Each of these templates could be either a good launching point or reference for a new developer looking to quickly create a Python app.  Deploying to the App Engine is just a few clicks away with CoderBuddy.  So I "created" my Adrian Remembers Me app in one click and about two minutes later had my site running on the app engine at http://cgack2-coderbuddy.appspot.com/.  The ease of deploy along with the ability to upload files and download the project as a .zip I will definitely look to CoderBuddy for part if not all of my next project.