Pelargir

Musings on software and life from Matthew Bass.

November 26th, 2006

Using protected attributes in your Rails models

Let’s say we’ve created a simple profile page to allow our users to update their e-mail address, locale, time zone, and various other settings. This profile page exposes only those model attributes that we want the user to be able to update. Other attributes on the model should not be updateable by the user.

We opt to surface the updateable attributes on the profile page and assume that the user won’t be able to update the remaining attributes since they won’t even appear on the page. But does that really provide enough protection?

Our model and database schema are defined as follows:

class User < ActiveRecord::Base
end
 
create_table :user |t|
  t.column :username, :string  t.column :password, :string
  t.column :fname, :string
  t.column :lname, :string
  t.column :email, :string
  t.column :permission, :string
end

Our model can store a username, password, first and last name, e-mail address, and permission level. The permission level is used to determine what the user is allowed to do on the site. A permission level might be “Moderator” or “Admin.”

Our profile form surfaces the attributes that we want to be updateable:

<%= start_form_tag %>
  <%= text_field :user, :fname %> First Name<br/>
  <%= text_field :user, :lname %> Last Name<br/>
  <%= text_field :user, :email %> E-mail Address<br/>
  <%= submit_tag %>
<%= end_form_tag %>

It’s obvious that we only want the user to update his first and last name and e-mail address. Now let’s examine the action being called when we submit the profile form:

def update
  @user = User.find(params[:id])
  if @user.update_attributes(params[:user])
    redirect_to :action => "success"
  end
end

Our action looks up a user, updates its attributes with the new values passed on the request, and redirects to a new action if the update was successful. Simple enough, yet the code above could allow a malicious user to update the permission level of his account… something we certainly don’t want him doing! Assuming the action is not protected against GET requests, we could simply visit the following URL in our browser to give the user a different permission level:

http://localhost:3000/user/update/1?user[permission]=Admin

Protecting the action against GET requests would prevent the attack from occuring via a URL, but the attacker could easily generate a POST request through other means. Rails provides a way to protect against such attacks: the #attr_protected class method:

class User < ActiveRecord::Base
  attr_protected :permission
end

Now if we attempt our attack again, the permission level simply doesn’t get updated. The other attributes sent on the request are assigned correctly, but the permission level isn’t. Why not?

It turns out that #attr_protected makes it impossible to update the permission attribute through the #update_attributes method (or any other mass assignment method for that matter). The only way we can update the permission level now is by using single-assignment techniques such as:

@user.update_attribute(:permission, "Admin")

It’s generally a good idea to protect attributes that could cause a security breach in your system. These might include usernames, passwords, software keys, and even product prices. While by no means a silver bullet, #attr_protected is still a good tool to use as you begin locking down sensitive parts of your application.

#attr_protected accepts multiple attributes so we could rewrite our model again as:

class User < ActiveRecord::Base
  attr_protected :username, :password, :permission
end

#attr_protected also has a more conservative cousin, #attr_accessible. It renders all attributes on the model unavailable for mass assignment unless they are specifically named. This differs from #attr_protected which lets you start in an “all-open” state and only restrict attributes as necessary. Both methods are handy to have in your toolbox.

November 25th, 2006

I’ve made the switch (to an iMac)

I’ve been a PC user my whole life. That all changed two weeks ago when I purchased my first Mac. Most of my friends who are software developers had already switched so I figured I’d better go forward with the grand experiment now rather than later. I haven’t looked back since.

The model I purchased was an iMac 20″ with the Intel Core Duo processor, 2 GB of RAM, and the 256 MB Radeon video card. It’s zippy. The UI is quite responsive. I can have dozens of apps open at the same time without an appreciable slowdown, and the video editing capabilities of this little beauty have been quite impressive. The main reason I switched was because my friends were reporting a marked increase in their effeciency while using a Mac. I’m happy to report that they were 100% correct. Here are some of the reasons why I like my Mac:

Everything can be automated. Tasks that used to take several steps in Windows can now be performed with a single click. Apps like Quicksilver make it dead simple to launch an app, perform a numeric calculation, or switch to the next song in my iTunes playlist… all with a couple of keystrokes.

The UNIX command line rocks. The Windows command line is best described as “castrated.” There is just no comparison between it and a standard UNIX command line. Even something as simple as being able to directly execute Ruby scripts without manually calling the interpreter becomes a benefit when it’s repeated dozens of times per day.

Tests run FAST. A typical stack of Rails tests takes about a minute to finish on my Windows box. Under OS X, the same tests take 15 seconds or so, and most of this is startup time.

Editing videos and burning them to DVD actually works. I experimented with several different software packages on my PC and two different DVD burners, none of which gave me the results I wanted. Capturing from my VCR left minor glitches in the video when a background process was running. On my Mac, the screen saver is automatically disabled when capturing video and the Core Duo processor removes the negative effects of background processes.

The Apple Remote. A very clever addition to the iMac is the Apple Remote, which lets me control the system at a distance. I don’t need to head downstairs to use the TV and DVD player anymore. I can just scoot my chair back and bring up a movie in Front Row.

Nice touches. As you’ve undoubtedly heard from other Mac owners, it’s the nice little touches that count. The magnetic holder for the Apple Remote. The blinking white sleep light on the front of the bezel. The built-in mini-DVI port. The simplicity of the System Preferences pane. It all combines to make for a computing experience so much more pleasant than it used to be.

All is not peachy keen, though. I’ve had the iMovie editing software crash on me a couple of times. I’m not sure why this happened, but the good news is it didn’t take down the rest of the system like it might have on Windows. Also, software for the Mac is quite pricey, as is hardware. You’ll definitely pay a premium for an Apple system, but if you stick with craigslist and eBay you might get away with paying much less than retail.

In summary, I feel much more effecient on this Mac and so I think the purchase was well worth the price. This little beauty makes computing FUN again! I really suffered while I was on Thanksgiving vacation since I didn’t have my Mac around. If you’ve been thinking of making the switch to a Mac yourself, I encourage you to give it a try. You can always sell the system if it doesn’t work out for you. My bet is you won’t.

November 19th, 2006

Installing Mongrel on a shared host

Can this be true? Could it really work? I think I’ll find out.

November 19th, 2006

Fitting words

From the biography of John Henry Jowett:

“We leave our places of worship, and no deep and inexpressible wonder sits upon our faces. We can sing these lilting melodies, and when we go out into the street our faces are one with the faces of those who have left the theater and the music halls. There is nothing about us to suggest that we have been looking at anything stupendous and overwhelming. Far back in my boyhood I remember an old saint telling me that after some services he liked to make his way home alone, by quiet by-ways, so that the hush of the Almighty might remain on his awed and prostrate soul. That is the element we are losing, and its loss is one of the measure of our poverty, and the primary secret of inefficient life and service.”