BUILDING A SOCIAL NETWORKING
WEBSITE WITH RUBY ON RAILS

RailsSpace blog code security flaw

Posted over 2 years ago by Michael Hartl

I’d like to thank Fulvio Cusumano for pointing out a significant security problem in the RailsSpace blog code. He writes:

I’ve created an account on http://www.railsspace.com/ and my Username is “fulvio”. I am User ID 589. The following will not work, because I am not user 2. This is correct functionality because it tells me that it isn’t my blog. http://www.railsspace.com/blogs/2/posts/1;edit The actual security flaw I’ve found is that I don’t have a Post of ID #1 however if I access the following URL I can edit/update that post when I shouldn’t be able too! http://www.railsspace.com/blogs/589/posts/1;edit (589 is obviously me, but I don’t have a post of 1, however it DOES exist within your railsspace database).

This has now been fixed on the site, and in the RailsSpace zip files. The errata and code listings have also been updated to reflect the fix.

Here are the changes to make. First update the Posts fixture so that blog_id of the second post doesn’t match the blog of the test user:

test/fixtures/posts.yml
one:
  id: 1
  blog_id: 1
  title: MyString
  body: MyText
  created_at: 2007-01-16 15:34:32
  updated_at: 2007-01-16 15:34:32

two:
  id: 2
  blog_id: 2
  title: MyString
  body: MyText
  created_at: 2007-01-16 15:34:32
  updated_at: 2007-01-16 15:34:32

Then test the behavior we want:

test/functional/posts_controller_test.rb
class PostsControllerTest < Test::Unit::TestCase
  fixtures :posts, :blogs, :users
  .
  .
  .
  def test_post_blog_mismatch
    wrong_post = posts(:two)  # Post exists, but belongs to wrong blog.
    get :edit, :id => wrong_post, :blog_id => @post.blog
    assert_response :redirect
    assert_redirected_to hub_url
    assert_equal "That isn't your blog post!", flash[:notice]
  end
end

Finally, get the test to pass by putting in a new before_filter to make sure that post.blog and @blog agree:

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  helper :profile, :avatar
  before_filter :protect, :protect_blog
  before_filter :protect_post, :only => [:show, :edit, :update, :destroy]
  .
  .
  .
  private

  # Ensure that user is blog owner, and create @blog.
  def protect_blog
    @blog = Blog.find(params[:blog_id])
    user = User.find(session[:user_id])
    unless @blog.user == user
      flash[:notice] = "That isn't your blog!"
      redirect_to hub_url
      return false
    end
  end

  def protect_post
    post = Post.find(params[:id])    
    unless post.blog == @blog
      flash[:notice] = "That isn't your blog post!"
      redirect_to hub_url
      return false
    end
  end
end

Comments

There are 0 comments on this post.