This is Happening Again

Less than 48 hours until my daughter is to be born, it just hit me. We're having another baby. I mean, I've known this has been coming. For some reason though, it just became real.

I've been covered up with projects at work. I've fixed up 3 rooms here at the house. I've been consumed with a construction project here too. Now it's all done and I'm here with nothing else to distract me. 9 months has withered away and we're about to have another human to keep alive.

I'm excited to meet my daughter. I'm relieved to see my wife not have to suffer through gestational diabetes. I'm nervous to see what adding another child to our family will be like. I'm scared.

Life is scary and awesome. I'm ready to stop being distracted and start focusing on the things that are important again. I have a feeling that baby Hannah will force me to slow down a bit.

Masked Input 1.3.1

A long overdue release of my Masked Input Plugin is available. This is a bugfix release that adresses some of the bigger issues out there:

  • jQuery 1.9 compatibility.
  • Fixed browser lockup when window loses focus.
  • Android issues.
  • No longer preventing event bubbling.
  • Making sure we call completed handler when pasting a value.
  • Fixed bug trying to set caret on hidden elements.
  • Fixed cursor positioning bug related to bounds check.

You can see everything in detail over at the 1.3.1 milestone on github.

I had planned to roll in more bugfixes, but jQuery 1.9 releasing forced my hand a bit. If you see any problems, please report them as a github issue. I also managed to get this published in the newly revamped jQuery plugins site. Thank you to everyone who reported issues and to those who submitted patches.

 

devLink 2012

I'm just winding down here from devLink 2012 and wanted to share my slides and take a moment to reflect. I was privileged to be given the opportunity to talk again this year on NoSQL. Unfortunately I think I reached a bit too far that late night when I pulled an abstract out of my rear for a yet to be written talk. Here, judge for yourself. This was the abstract I submitted:

Never has a technical buzzword produced such confusion as "NoSQL". Not all data stores are created equal. It's time to shine a light on the technology that claims to hold your big data, replicate it everywhere and be faster than its relational grandpa. This session will compare and contrast the popular NoSQL tools without subjecting you to fabricated benchmarks and meaingless jargon. It's time for a data store cage match!

It sounded good at the time, but it's lacking substance. What did I promise to deliver? A comparison without numbers and fancy words - okay, that's interesting I guess? The title implied there would be a winner and the tagline promised excitement, WWE style.

I feel like I delivered on comparing the technologies without numbers. I introduced some fancy words and concepts. Hopefully I explained them well enough. The video that the public will never see will tell the story there. In the end though, there was no real winner. Since I didn't show up dressed as a luchador, exciting was not a word you'd use to describe that talk.

I'm still new to this conference speaking thing and every experience, both good and bad, help me get better. I want to be great at this. I want to be able to deliver a talk that sticks in people's heads for weeks after the fact. I've learned my lesson and my next talk will be more focused - maybe a specific technology or pattern. No more of this I'm-going-to-show-you-the-meaning-of-life-in-an-hour type of thing. It's just not a good use of mine or the audience's time.

With all of that said, I'm glad to have that talk under my belt. It took me several months to compile all of that information and present it in a way that I felt was palatable in an hour format. NoSQL is a movement and there are a lot of options with more popping up every month. I felt like I had a firm grasp on the topic when I pitched the talk, but I learned so much more after having to research and build a few demos. In the end, that's knowledge I can take with me to build something awesome in the future.

My slides, notes and demos are up on github for your scrutiny. Thank you to devLink for having me. Thank you to those who attended both the talk and the preview talks - your feedback was invaluable. A big thank you to my friends and coworkers who continue to push me to be better at speaking, software, and life in general. It was great to see you all again. Now, let's all get some rest.

Codestock 2012

This past weekend I was given the opportunity to speak about CouchDB at Codestock in Knoxville, TN. This is a talk I've been able to give a few times, but this is the first time I've attempted to record it. I've pulled out a 10 minute clip where we walk through storing a fast food order in a relational database and then storing the same order in a document database. The video is rough because all I had was my pocket camcorder.

CouchDB Bucket Demo, Codestock 2012 from digitalbush on Vimeo.

Also, here are the slides for the whole talk.

The sample code for the note taking app and map/reduce are in this repository. The wikipedia demo can be found in this repository. I'm still trying to get my legs with this whole speaking thing, so your feedback is much appreciated. Codestock was a blast and I hope to go back next year!

Mass Assignment Vulnerability in ASP.NET MVC

By now you may have seen what happened to github last night. In case you didn't, let me bring you up to speed.

In a Ruby on Rails application, you can make a call to update your model directly from request parameters. Once you've loaded an ActiveRecord model into memory, you can poke its values by calling update_attributes and passing in the request parameters. This is bad because sometimes your model might have properties which you don't want to be updated by just anyone. In a rails application, you can protect this by adding attr_accessible to your model and explicitly stating which properties can be updated via mass assignment.

I'm not going to pretend to be a Ruby dev and try to explain this with a Rails example. Github already linked to this fantastic post on the subject regarding Rails here. What I'm here to tell you is that this situation exists in ASP.NET MVC also. If you aren't careful, you too could end up with a visit from Bender in the future.

So, let's see this vulnerability in action on an ASP.NET MVC project.

First, let's set up a model:

public class User {
    public int Id { get; set; }
    public string UserName { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsAdmin { get; set; }
}

Then let's scaffold out a controller to edit this user:

public class UserController : Controller {
    IUserRepository _userRepository;
    public UserController(IUserRepository userRepository) {
        _userRepository = userRepository;
    }

    public ActionResult Edit(int id) {
        var user = _userRepository.GetUserById(id);
        return View(user);
    }

    [HttpPost]
    public ActionResult Edit(int id, FormCollection collection) {
        try {
            var user = _userRepository.GetUserById(id);
            UpdateModel(user);
            _userRepository.SaveUser(user);
            return RedirectToAction("Index");
        } catch {
            return View();
        }
    }
}

Do you see that UpdateModel call in the POST to '/User/Edit'. Pay attention to that. It looks innocent enough, but we'll see in a minute why that is bad.

Next, we scaffold up a view and remove the checkbox that allows us to update the user's Admin status. Once we're done, it looks like this:

That works. We can ship it, right? Nope. Look what happens when we doctor up the URL by adding a query parameter:

I bet you guess what's about to happen now. Here, I'll break execution right at the problematic line so you can watch the carnage:

Okay, you can see the current values to the right. We've loaded user #42 from the database and we're about to update all of his values based on the incoming request. Step to the next line and we see this:

UH OH. That's not good at all. User #42 is now an administrator. All it takes is an industrious user guessing the names of properties on your entities for you to get burned here.

So, what can we do to prevent it? One way would be to change the way we call UpdateModel. You can use the overload which allows you to pass in an array of properties you want to include. That looks like this:

UpdateModel(user,new[]{"FirstName","LastName","Email"});

We've just created a whitelist of properties we will allow to be updated. That works, but it's ugly and would become unmanageable for a large entity. Aesthetics aside, using this method isn't secure by default. The developer has to actively do something here to be safe. It should be the other way around, it should be hard to fail and easy to succeed. The Pit of Success is what we want.

So, what can we really do to prevent it? The approach I typically take is to model bind to an object with only the properties I'm willing to accept. After I've validated that the input is well formed, I use AutoMapper to apply that to my entities. There are other ways to achieve what we want too, but I don't have time to enumerate all of the scenarios.

Wrapping up
The point of all of this is that you need to understand exactly what your framework is doing for you. Just because there is a gun available, it doesn't mean you have to shoot it. Remember folks, frameworks don't kill people; developers with frameworks kill people. Stay safe out there friends, it's a crazy world.

Cross posted from Fresh Brewed Code. If you haven't taken a look over there, please take a moment to see what we've been up to.

Next Page »

gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.