Aaronontheweb

Hacking .NET and Startups

How to Securely Verify and Validate Image Uploads in ASP.NET and ASP.NET MVC

One of the more interesting things I had to do as part of building XAPFest was handle bulk image uploads for screenshots for applications and user / app icons. Most of the challenges here are UI-centric ones (which I resolved using jQuery File-Upload) but the one security challenge that remains outstanding is ensuring that the content uploaded to your servers is safe for your users to consume.

Fortunately this problem isn't too hard to solve and doesn't require much code in C#.

Flawed Approaches to Verifying Image Uploads

Here's what I usually see when developers try to allow only web-friendly image uploads:

  1. File extension validation (i.e. only allow images with .png, .jp[e]g, and .gif to be uploaded) and
  2. MIME type validation.

So what's wrong with these techniques? The issue is that both the file extension and MIME type can be spoofed, so there's no guarantee that a determined hacker might not take a js. file, slap an extra .png extension somewhere in the mix and spoof the MIME type.

Stronger Approach to Verifying Image Uploads: GDI+ Format Checking

Every file format has to follow a particular codec / byte order convention in order to be read and executed by software. This is as true for proprietary formats like .pptx as it is for .png and .gif.

You can use these codecs to your advantage and quickly tell if a file is really what it says it is - you quickly check the contents of the file against the supported formats' codecs to see if the content fits into any of those specifications.

Luckily GDI+ (System.Drawing.Imaging), the graphics engine which powers Windows, has some super-simple functions we can use to perform this validation. Here's a bit of source you can use to validate a file against PNG, JPEG, and GIF formats:

using System.Drawing.Imaging;
using System.IO;
using System.Drawing;

namespace XAPFest.Providers.Security
{
    /// 
    /// Utility class used to validate the contents of uploaded files
    /// 
    public static class FileUploadValidator
    {
        public static bool FileIsWebFriendlyImage(Stream stream)
        {
            try
            {
                //Read an image from the stream...
                var i = Image.FromStream(stream);

                //Move the pointer back to the beginning of the stream
                stream.Seek(0, SeekOrigin.Begin);

                if (ImageFormat.Jpeg.Equals(i.RawFormat))
                    return true;
                return ImageFormat.Png.Equals(i.RawFormat) 
|| ImageFormat.Gif.Equals(i.RawFormat);
            }
            catch
            {
                return false;
            }
        }

    }
}

All this code does is read the Stream object returned for each posted file into an Image object, and then verifies that the Image supports one of three supported codecs1.

This source code has not been tested by security experts, so use it at your own risk.

If you have any questions about how this code works or want to learn more, please drop me a line in the comments below or on Twitter.

Bonus: How Do I Make Sure Files Are below [X] Filesize?

Since I had this source code lying around anyway, I thought I would share it: 

public static bool FileIsWebFriendlyImage(Stream stream, long size)
        {
            return stream.Length <= size && FileIsWebFriendlyImage(stream);
        }
    }

Super-simple, like I said, but it gets the job done. Express the maximum allowable size as a long and compare it against the length of the stream

 


1The other important catch to note here is that I move the Stream's pointer back to the front of the stream, so it can be read again by the caller which passed the reference to this function.

If you enjoyed this post, make sure you subscribe to my RSS feed!



How I Built CaptainObvio.us

Captain Obvio.us - a place to share ideasI made a tiny splash on Hacker News a month ago when I asked for feedback on my newest side project, CaptainObvio.us – a simple portal for sharing ideas and soliciting feedback from a community of peers. The idea was popular and I’ve received a ton of feedback – I’ve implemented most of the Hacker News community’s suggestions but haven’t had the chance to do another round of customer development.

What I wanted to share in this blog post was some of the secret sauce I used for creating CaptainObvio.us – I originally created it mostly to learn MongoDB, and learned way more than that along the way.

Webstack: ASP.NET MVC3 on AppHarbor

I used ASP.NET MVC3 as my webstack of choice with AppHarbor as my hosting platform. ASP.NET MVC3 is a massive improvement over MVC2, and I took advantage of Razor syntax, the built-in support for DI (dependency injection) on controllers, and wrote a number of customized helpers to do things like create an action filter for Twitter @Anywhere.

AppHarbor has been a great experience to work with - I use Git for souce control for most of my personal projects like this one so deployments are a breeze on AppHarbor, but the other major reason I picked AppHarbor is that it shares the same Amazon AWS datacenter as MongoHQ - another [Thing]-as-a-Service that I used for hosting my MongoDB instance.

Data: MongoDB on MongoHQ

The original purpose of CaptainObvio.us was for me to learn MongoDB, a schemaless (NoSQL) document database written in C++ that is becoming all the rage in the Ruby on Rails universe. CaptainObvio.us is a good fit for Mongo given that the vast majority of its content consists of simple documents with a small amount of relational data for tying authors to ideas / comments and so forth.

I could not have gotten very far with MongoDB in C# were it not for the NoRM Project MongoDB drivers for C# - NoRM's drivers are much better than the default MongoDB drivers for C# and work similarly to LINQ-to-SQL (although not exactly.) It was a matter of hours for me to go from installing Mongo to having a functional site running with NoRM and ASP.NET MVC3.

Authentication: Originally Twitter @Anywhere; Sign-in-with-Twitter and Hammock Later

Twitter @Anywhere is a fairly new JavaScript-only framework for integrating Twitter into existing websites quickly and effortlessly - it automates all of the OAuth workflow, comes with tons of useful built-in widgets, and eliminates the need to write much (if any) plumbing needed to support Twitter integration.

This is all nice in theory but if you're building a site like CaptainObvious where your users use Twitter to sign-in and leave behind persistent data in your own data store, then this framework can really cause problems. I had to gut Twitter @Anywhere eventually because the post-authentication event hook would misfire on occasion due to issues on the client and thus I would have an "authorized" user running around adding comments and voting despite no record of them existing in the database.

In order to resolve the issue, I dumped Twitter @Anywhere and went with traditional Sign-in-with-Twitter powered by Hammock, which works fine.

Final Thoughts

I'm going to continue working on CaptainObvio.us, although I put it off largely due to all of the work I had to do engineering XAPFest's online presence on Windows Azure. If the project taught me anything, it's the value of continuous integration environments like AppHarbor and the ease with which you can get something up and running quickly with MongoDB.

I'd highly recommend checking out AppHarbor, MongoHQ, and the NoRM drivers if you're a .NET developer who's new to Mongo and wants to learn how to use it. I guarantee you that you'll appreciate traditional .NET databases like SQL Server 2008 and SQL Azure a lot better after you've worked with Mongo, as it'll help you learn the strengths and weakness of each respesctive platform.

If you enjoyed this post, make sure you subscribe to my RSS feed!



Announcing XAPFest – A Massive Windows Phone 7 Hackathon in Santa Monica, CA on June 4th 2011

xapfest_black_logoI am pleased to announce something very exciting that Microsoft is doing in my neighborhood of Santa Monica, California: we’re putting together XAPFest, a massive Windows Phone 7 hackathon aimed to bring together startups and mobile developers of all skill levels for a day of creativity and competition.

XAPFest is going down on Saturday, June 4th at the Loews Santa Monica Beach Hotel (directions) – doors open at 9:00am and will close at approximately 10:00pm. There will be opportunities for individuals and teams of developers to win prizes, eat great food, and have fun hacking down by the beach.

XAPFest is free to attend, and anyone can register for XAPFest if they wish to participate.

So here’s the full scoop behind XAPFest.

XAPFest Rules & Conditions

Your goal as a XAPFest participant is to produce a Windows Phone 7 application in a 80-90% complete state by 6:00pm on Saturday, June 4th at the Loews Santa Monica Beach Hotel (see the full schedule and driving directions.)

Here are the rules:

  1. You can get started early, and we ENCOURAGE you to get started before June 4th; install the tools and create a project on XAPFest.com and begin working on your app ASAP.
  2. You can work either as an individual or on a team of up the three people.
  3. Any apps you submit for consideration must not be in the marketplace prior to June 4th (new apps only!)
  4. In order to claim a prize, your app has to be accepted into the Windows Phone 7 marketplace shortly after XAPFest.
  5. You can submit multiple apps in XAPFest, but a team can only claim one prize in total.

 

Install the free Windows Phone 7 development tools early, create an app project, invite your friends, and write updates / post screenshots for your apps often!

If you have any questions about the event or want to know how to get involved (beyond registering and attending XAPFest,) please contact me and I’ll be in touch!

Otherwise, see you on June 4th!

P.S. Take a look at the apps I've created for XAPFest:

If you enjoyed this post, make sure you subscribe to my RSS feed!



Geolocation Services and Bing Maps in Windows Phone 7

Tonight I gave a brief talk to WinMo LA about using Geolocation Services and Bing Maps on Windows Phone 7. I mostly covered the APIs and controls that developers can use in the current Windows Phone SDK, the steps developers need to take in order to protect a user's data, and some of the future things that are changing in Mango for Windows Phone 7 developers.

Source Code for Demos:

  1. Bing Maps WP7 Demo [Github]
  2. Geolocation WP7 Demo [Github]

Other Important Links

  1. Bing Maps Portal - Get API Keys for Bing Maps
  2. MIX11 Sessions - Get all of the updates on Mango and WP7.
  3. WinMo LA - Subscribe for the next event!
  4. Windows Phone Dev Podcast - Unofficial Podcast for Windows Phone 7

If you enjoyed this post, make sure you subscribe to my RSS feed!



Having Network Connectivity Issues with the Windows Phone 7 Emulator?

April 7, 2011 18:07 by Aaronontheweb in Windows Phone 7 // Tags: , // Comments (0)

I spent about three hours banging my head against the wall trying to figure out why my browser could connect to the Internet but the Windows Phone 7 emulator couldn’t, and if you find yourself in the same boat as me I thought I would spare you the trouble.

Are you seeing something like this when you try to pull up a web page in IE on the emulator?

image

If that’s the case, then you’re having network connectivity issues specific to the Windows Phone 7 emulator. There’s a guide to troubleshooting Windows Phone 7 emulator issues on MSDN, and it speaks to the root of the issue: your HTTP proxy settings.

If you’re like me, you like using Fiddler for testing network I/O when you’re trying to connect to RESTful services – Fiddler acts as a proxy and disrupts all network I/O from the emulator; leave it turned off while you’re working with the Windows Phone 7 emulator.

Thought I’d spare any other Fiddler / Windows Phone 7 using developers the trouble Smile with tongue out

If you enjoyed this post, make sure you subscribe to my RSS feed!



How to Create a Twitter @Anywhere ActionFilter in ASP.NET MVC

My newest project, Captain Obvious, got a fair amount of attention this week when it landed on the front page of Hacker News – one of the key features that makes the first version of Captain Obvious tick is Twitter @Anywhere integration.

Twitter @Anywhere is brand new and there isn’t much developer documentation for it – the way to think about Twitter @Anywhere is as a Javascript platform that allows you to outsource user authentication and registration to Twitter’s servers, and in exchange you get less hassle but also less intimate access to your user’s accounts.

One of the key features to integrating Twitter @Anywhere users with your ASP.NET MVC site is reading the cookie that Twitter sets after users have authenticated – this cookie contains two parts:

  1. The Twitter user’s unique ID, an integer representing their unique account (because remember – Twitter users can change their handles!)
  2. A SHA1 hash of the Twitter user’s unique ID + your application’s consumer secret – you use this to verify that the cookie was set by Twitter, since they’re the only ones who know your consumer secret other than you.

Naturally, if you are going to use this cookie as your authentication mechanism, then you are going to need to write your own Authorize attribute that allows you to validate the content’s of the Twitter @Anywhere cookie. Here’s the source code I use for doing that:

 

ValidTwitterAnywhereAttribute

/// <summary>
    /// Controller Action Filter Attribute which requires that
    /// </summary>
    public class ValidTwitterAnywhereAttribute : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var twitterCookieValue = httpContext.Request.Cookies["twitter_anywhere_identity"];
            var consumerSecret = ConfigurationManager.AppSettings["TwitterConsumerSecret"];

            return TwitterAuthHelper.ValidateTwitterCookie(twitterCookieValue, consumerSecret);
        }
    }

 

Here’s the relevant source code from the TwitterAuthHelper that I use to actually validate the hash in the cookie:

TwitterAuthHelper

 

 public static bool VerifyTwitterUser(string twitterCookieValue, string ConsumerSecret)
        {
            var results = twitterCookieValue.Split(':');
            var sha1 = new SHA1CryptoServiceProvider();
            var hash = BitConverter.ToString(sha1.ComputeHash(Encoding.UTF8.GetBytes(results[0] + ConsumerSecret)))
                        .ToLower().Replace("-", "");
            if (hash.Equals(results[1]))
                return true;


            return false;
        }

I’m using this code in production and it works great – all you have to do to use it is decorate your controller methods with the [ValidTwitterAnywhere] attribute and it will behave just like Forms authentication if you have that enabled in your ASP.NET MVC app.

If you enjoyed this post, make sure you subscribe to my RSS feed!



8 Lessons Learned from Startup Weekend

I imagewanted to post this the morning after Startup Weekend Los Angeles concluded in late February, but due to the fact that I along with half my team (Minboxed) came down with the flu the following morning, I postponed this for long than I would have liked.

Startup Weekend Los Angeles stands out among other Startup Weekends in that each one of these events have produced real companies like Vol.ly, Foodme, Ming.ly, and Zaarly – who took first place in this very Startup Weekend and recently closed a $1m dollar round of funding and soft-launched at SXSW (great job, guys!)

The quality bar for talent is high and the judges are terrific – this year we were even treated to a surprise visit from Ashton Kutcher and Demi Moore, who judged my presentation along with 9 others.

This marked my third startup weekend, my second as a participant, and my first as a team lead.

I learn something new at each Startup Weekend; the ultimate value in these events isn’t really producing a product or a company – it’s learning how to work alongside a team of strangers to build something that didn’t exist 56 hours prior.

In that vein, I thought I would share what I learned.

1. You don’t need a functional product demo to win Startup Weekend

If I can point to one thing that I personally did wrong in this event, it was over-emphasis on building a functional prototype at the detriment of everything else. I can’t help it – I’m an engineer and a passionate geek.

I spent all of Saturday hammering out a prototype, figuring out how to connect to Gmail, how to use IMAP, how to write SQL queries to score achievements, how to batch everything from an ASP.NET MVC app on AppHarbor without worker roles, and so forth…

Minboxed didn’t place in the top three at the end of the judging, despite solid engineering and design efforts from our team – another startup, Eventify.me won 2nd place however.

In the course of Eventify.me’s demo of their live product, their entire thing came down and the team leader was forced to scramble onstage for the duration of her presentation. It’s the sort of nightmare scenario that every presenter worries about. In the end, it didn’t matter though – the judges were able to appreciate the quality of the idea and the future of the business without having to see it fully in action.

2. Sell the judges on the business, not the product

We were very focused on making Minboxed an awesome product – competitive social gaming built on top of email in order to make it more fun to be productive with your email. We had some innovative monetization strategies (in my opinion) and a good general strategy for acquiring customers; in other words, I think we made a good case for building a healthy business.

However, in our pitch to the judges those aspects of our work received a fraction of the attention that our product demo and our value proposition did. In hindsight, we made a great product pitch at the cost of a great business pitch.

3. Relate your business model to a proven one

In past Startup Weekends I’ve attended, the winners have always been companies who’ve modified a successful business model to either address a new problem or a new market; Zaarly took the Craigslist model and flipped it on its head, making it demand-driven instead of supply-driven. Hinty, the winner from the previous Startup Weekend LA, took a consumer-facing twist on TellMe’s business model.

I don’t want to make it sound like Startup Weekend judges punish innovative business models – it’s just easier to sell them on something that builds on the success of something else. I still can’t think of anybody who’s built a business doing something close to what Minboxed does; maybe that means it’s a bad fit for Startup Weekend or perhaps it means that we simply needed to go further to prove that there was a viable business behind it.

4. Talk to customers early

We did not talk to customers, a huge mistake. We talked to users, people who would be playing the Minboxed game, but not people who would be paying for it.

Had we talked to customers earlier we would have discovered just how far we needed to go in terms of privacy (one of the judges told me later that this was a big part of the reason why we didn’t make it.) In addition to discovering potential issues early and helping teams pivot on their business models and products, early customer commitments and testimonials are one of the best ways to sell judges on the future of your business.

We were focused on users of products, not customers of our business – a big mistake.

5. Do your pitch presentation with someone who isn’t on your team

Small lesson here – there were a number of things we did to make a good case for Minboxed, but we didn’t touch on them with either enough clarity or enough detail to convince the judges. Had we given our presentation to someone who wasn’t on our team before we ever showed it to the judges, we could have heard their “I don’t understand why…” questions and modified it earlier.

At the end of the day, your idea will be judged by how you communicate it as it will be on its own merits, if not more. Your team will take a myopic view of the business if you don’t include feedback from outsiders, thus why this lesson is important.

6. Cap the number of team members and pick people with specific skills

This is one thing that we did really, really well. We had a team of six, which is still a little large, but we made sure that we had the right people on it. Two engineers, one designer, and three marketing / business development folks.

I had to turn away a few people, and I’m glad that I did – when you get too many people, you spend too much time trying to make sure that everyone is included and trying to roll everybody’s work into the final product / presentation. You’re better off being mean on Friday night and saying “no thanks, we’re good” and paring down your team to the bare essentials.

7. Keep the engineering workflow tight

One problem I have yet to find a good solution to is how to manage the engineering workflow for product development at Startup Weekend.

Following my experience from this past Startup Weekend, it’s my new belief that if you have an appropriately tractable idea for Startup Weekend you should have two engineers: a back-end developer who owns 100% of the database + stack and a front-end developer who implements the JavaScript, CSS, and user-experience implementation. The two engineers and the designer (if there is one) need to hammer out on-paper designs for every page with a user interaction, and the back-end developer needs to create a set of dummy controllers for the front-end developer to build against.

I say this because my teammates and I have spent a lot of time trying to merge divergent bottom-up designs on Sunday on two different Startup Weekends, instead continuing to work on the product, and it’s a major productivity-killer.

If you have better ideas on how to do this and what’s worked for you historically, please leave a comment. I don’t have a perfect system for this.

8. As a team lead, your job is to evangelize

The team lead for any Startup Weekend project is usually going to be the person who pitched the idea before it was selected; as a team lead, your first job is to evangelize a vision to your team from the first second to the last.

If your teammates have a clear vision that they can buy into, it makes it easy for them to self-manage and work with minimal interruption.

Next are your potential customers –evangelize them on the idea and get early commitments and testimonials.

Last are your judges – your job is to evangelize them on the total vision for your team, business, vision, and product and earn their votes.

Stepping away to work on the product and talk to potential customers is still time well-spent, but ultimately your first priority is evangelism.

Thoughts for next time

I’m going to participate in the next Startup Weekend LA, and I’ll pitch a new idea, and even if I don’t win I’ll learn something new. Looking forward to it!

If you enjoyed this post, make sure you subscribe to my RSS feed!



ASP.NET MVC3 / Razor: How to Get Just the Uri for an Action Method

March 15, 2011 17:43 by Aaronontheweb in ASP.NET // Tags: , , // Comments (0)

I normally wouldn’t post something this small to my blog, but this issue bothered me so much when I was working on some Twitter @Anywhere + jQuery integration in ASP.NET MVC3 that I couldn’t help but share it.

Issue: You’re using ASP.NET MVC3 and want to be able to place a relative Uri for one of your ASP.NET MVC controller’s action methods in a block of JavaScript or anywhere else, and you want to be able to do it without having to parse it out of an Html.ActionLink output or anything else. What built-in helper method do you use?

Solution: The answer is that you use the Url.Action method, which yields a relative Uri, as you’d expect.

Observe the code below:

T("#login").connectButton({
	authComplete: function (user) {
		// triggered when auth completed successfully
		$.post('@Url.Action("AnywhereTest", "Auth")');
		location.reload();
	   
	}
});

And here’s the output to go along with it:

T("#login").connectButton({
	authComplete: function (user) {
		// triggered when auth completed successfully
		$.post('/auth/anywheretest');
		location.reload();
	   
	}
});

If you enjoyed this post, make sure you subscribe to my RSS feed!



Quick and Dirty Feed Parser 1.0 Released!

January 19, 2011 19:42 by Aaronontheweb in QDFeedParser // Tags: , , // Comments (4)

Without further adieu, it’s my pleasure to announce that the full 1.0 release of Quick and Dirty Feed Parser is now available to download on Codeplex.

Here are the main reasons why you should care about Quick and Dirty Feed Parser 1.01:

  1. Works on Windows Phone 7 and Silverlight 4;
  2. All IFeed objects now consume substantially less memory on average;
  3. All IFeed objects are now serializable;
  4. All IFeedFactory objects now support DI for injecting your own feed parsers; and
  5. Added an IsolatedStorageFeedFactory for working with RSS / Atom feeds in IS for all Silverlight and Windows Phone 7 developers.

Making QD Feed Parser run on Windows Phone 7 took some work – I had to rewrite the entire parsing library using LINQ-to-XML instead of XPath, but it was well worth it. The LINQ parser is now used by default in all IFeedFactory instances, but you can inject your own if you have a better way of parsing RSS or Atom.

I’ve had the pleasure of using Quick and Dirty Feed Parser 1.0 in Geeky Reads and in my new budding project, JSONify, and QD Feed Parser has performed excellently in its response time in both of those services thus far.

I’m also building a line of Windows Phone 7 applications on top of Quick and Dirty Feed Parser 1.0, and it’s made life rather easy for me in the scheme of things.

You can read the full release notes for Quick and Dirty Feed Parser 1.01 on CodePlex, and by all means please feel free to leave me feedback here if you’ve had a chance to try the project yourself.

Contributors Wanted!

We’re actively looking for contributors who want to help make Quick and Dirty Feed Parser even better. If you’re interested, feel free to ping me via CodePlex or leave a comment below!

Update: Quick and Dirty Feed Parser Added to NuGet

Quick and Dirty Feed Parser is now available on NuGet! http://nuget.codeplex.com/

If you enjoyed this post, make sure you subscribe to my RSS feed!



What Drives a Startup Founder?

January 18, 2011 13:21 by Aaronontheweb in Startup // Tags: // Comments (6)

I’ve been working on numerous projects since the year began, and on Sunday night I finally got around to watching The Social Network. My expectation was that the movie was going to be a breathless attempt by Hollywood to insert themselves in something cool and relevant, a tin-eared paean to their own importance. “Hey, we can be part of the social media revolution too – check out this awesome movie we made!”

But I was wrong – the movie was excellent. I assume that aside from some specific numbers regarding equity and valuation that the movie is a pretty accurate depiction of the early years of Facebook. I don’t know Mark, but from the movie I gathered that he was a socially challenged person who was very, very focused on getting one thing done.

What Drives Me

The image that gripped me most from The Social Network was the scene where Mark and the early Facebook engineering team were living together in a small house in Palo Alto, hammering out code and taking ziplines into the swimming pool. I thought “that’s what an adventure looks like – this is what being in a startup should be all about.”

The biggest thing that attracts me to startups is the desire to be a part of a great team and the sense of shared accomplishment and camaraderie that comes along with it. I tried going it fully alone in my last startup because I simply couldn’t wait to find the right teammates any longer, and I just wanted to give it a try. It didn’t work – lesson learned.

I’ve had countless ideas, some of which I’ve tried to implement, but up until I joined Microsoft I was never on a team where everyone really gave a shit and pulled their own weight. My friends in high school and in college talked a lot of game, but no one ever stepped up with me to try to actually accomplish something. So that’s why that particular scene reached me – everyone gave a shit and did the requisite work to prove it.

Not-giving-a-shit is a disease; it corrupts morale and ruins companies. I’ve been in situations where I came into something full of ideas, energy, and effort to match, but was quickly ruined by the malcontent spirits known as don’t-give-a-shitters. If you find yourself surrounded by these types – get out before they spread the infection to you and waste your life.

I’m motivated by working with an effective team of people who want to achieve a common end. I don’t know what truly motivates Mark Zuckerberg, but my best guess is that he’s motivated by the experience of realizing a specific vision for Facebook: to map the college social experience online.

I found the whole experience of watching The Social Network to be deeply motivating - realizing an idea and doing it with the right people is better than all of the wealth in the world, and it's a hell of a lot better than making millions in the stock market. The movie made me want to be a better programmer; take more risks; find more potential teammates; and do it sooner rather than later.

If you enjoyed this post, make sure you subscribe to my RSS feed!



Search

About

My name is Aaron, I'm an entrepreneur and a .NET developer who develops web, cloud, and mobile applications.

I left Microsoft recently to start my own company, MarkedUp - we provide analytics for desktop developers, focusing initially on Windows 8 developers.

You can find me on Twitter or on Github!

Recent Comments

Comment RSS

Sign in