0 Comments By Damon on Dec 19 in Rubyonrails, Releases, and Security.

As I mentioned in a previous blog, Rails recently introduced RequestForgeryProtection. I wanted to take full advantage of this functionality to help protect against CSRF-based attacks. I realize it's not a perfect method, but every layer helps. One of the observations I made when reviewing some of my code is that I had a number of actions within my controllers that did not validate the type of HTTP method supplied. Therefore, actions like deleting a blog or media file would work regardless of the HTTP method provided by the user as long as the user was logged in. Not a huge problem, right? Well, not quite.

Glancing through the source code for the verified_request? method, you'll notice that GET requests are automatically exempt from forgery protection. Therefore, even though I had enabled forgery protection, it was not being applied to certain actions, which allowed for potentially bad things. What I needed to do was to make sure my actions that should be "forgery protected" only accept POST requests. As well, I needed to adjust a few of my links to make sure they are sending POST requests.

Hello to the Rails verify method. Using this method, I was able to specify actions that should only accept POST requests. Here's what the code looked like in my controllers. 

verify :method => :post, :only => [:create, :update, :delete], :render => { :text => '405 HTTP POST required', :status => 405 }, :add_headers => { 'Allow' => 'POST' }

What the chunk o' code above does is verifies that the create, update, and delete actions only accept POST methods. If it's anything else, then it renders an error indicating that only POST requests are accepted and even sets the appropriate header. This was primarily inspired by infused.org's blog on Returning supported HTTP methods with 'verify'.

Sample Functional Test

No updates would be complete with out tests, so I wrote the appropriate functional test for each controller.

def test_invalid_update_methods
  do_login
  [:get, :put, :delete].each do |http_method|
    actions_requiring_post = [:create, :update, :delete]
    actions_requiring_post.each do |x|
      send http_method, x
      assert_response 405
      assert_equal 'POST', @response.headers['Allow']
      assert_equal '405 HTTP POST required', @response.body
    end
  end
end

This test simply loops through to ensure that GET, PUT, and DELETE methods return the correct error when submitted to actions that only accept POST. Alright, nuff for now.

Happy Holidays! 

Current Rating: 4.0 rating from 1 vote

  • Current rating is 4
  •  
  •  
  •  
  •  
  •  

No Responses to "Getting Strict with HTTP methods"

Comments are Closed

Name: (Required)
Website:
Comment:
Remember my info