Mass assignment 漏洞

1、http://blog.mhartl.com/2008/09/21/mass-assignment-in-rails-applications/

This is a brief review of mass assignment in Rails. See the follow-up post on Finding and fixing mass assignment problems in Rails applications for some more tips on how to find and fix mass assignment problems.

简述Rails框架系统中存在大量分配漏洞

We’ll begin with a simple example. Suppose an application has a User model that looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# == Schema Information
# Table name: users
#
#  id                         :integer(11)     not null, primary key
#  email                      :string(255)    
#  name                       :string(255)    
#  password                   :string(255)
admin                      :boolean(1)      not null
class User < ActiveRecord::Base
   validates_presence_of :email , :password
   validates_uniqueness_of :email
   .
   .
   .
end

Note the presence of an admin boolean to identify administrative users. With this model, the Users controller might have this standard update code:

注意到上文中使用布尔类型的admin确定用户是否有管理员权限。使用该模型,用户控制端可能使用标准的更新代码:

1
2
3
4
5
6
7
8
9
10
11
12
def update
   @user = User.find(params[ :id ])
 
   respond_to do |format|
     if@user.update_attributes(params[:user])
       flash[ :notice ] = 'User was successfully updated.'
       format.html { redirect_to( @user ) }
     else
       format.html { render :action => "edit" }
     end
   end
end

This works fine, but note that the line

这样正常进行,但是请注意这行:

1
if @user .update_attributes(params[ :user ])

performs an update to the @user object through the params hash, assigningall the @user attributes at once—that is, as a mass assignment.

通过params哈希进行更新user对象,一次分配user的所有属性 ----这就是大量分配。

The problem with mass assignment is that some malicious [cr|h]acker might write a script to PUT something likename=New+Name&admin=1, thereby adding himself as an administrative user! This would be a Bad Thing™. The standard solution to this problem is to useattr_accessible in the model to declare explicitly the attributes that can be modified by mass assignment. To protect our User model, for example, we would write

该问题可以被黑客通过在脚本中写入name=New+Name&admin=1,可以添加自己为管理员用户!解决方法是使用attr_accessible来确定可以修改的属性来保护用户模型,例如:

1
2
3
4
5
6
7
8
9
10
class User < ActiveRecord::Base
 
   attr_accessible:email, :name,:password
 
   validates_presence_of :email , :password
   validates_uniqueness_of :email
   .
   .
   .
end

Since :admin isn’t included in the attr_accessible argument list, the User model’sadmin attribute is safe from unwanted modification.

因为admin不再attr_accessible参数列表中,用户模型的admin就不会被改变。

This seems simple enough, but the rub is that remembering to protect against mass assignment is difficult. Using mass assignment doesn’t affect the normal operations of the site, so it’s hard to notice the problem. Moreover, although you could shut off mass assignment globally, often there are many models that are used internally and never get modified directly by a web interface. Not being able to use mass assignment for these models is inconvenient, and manually making all attributesattr_accessible is cumbersome and error-prone. So, what’s a Rails developer to do?

这看起来比较简单,但是记住阻止使用大量分配是困难的。使用了大量分配也不会影响网站的正常操作,所以很难去注意这些问题。

Spurred by an email from Eric Chapweske of Slantwise Design, I recently audited the Insoshi social network for mass assignment vulnerabilities. Doing this manually was annoying, so in the process I developed a simple plugin to find likely vulnerabilities automatically, by searching through the controllers for likely mass assignment and then looking in the models to see if they didn’t define attr_accessible. The result is a list of potential trouble spots.

To use the find_mass_assignment plugin, simply install it from GitHub as follows:

$ script/plugin install git://github.com/mhartl/find_mass_assignment.git

(You’ll need Git and Rails 2.1 or later for this to work.) The plugin defines a Rake task to find mass assignment vulnerabilities; running it on the example Users controller from above would yield the following:

$ rake find_mass_assignment

/path/to/app/controllers/users_controller.rb
  5  if @user.update_attributes(params[:user])

This tells us that line 5 in the Users controller has a likely mass assignment vulnerability.

The find_mass_assignment plugin doesn’t fix mass assignment problems automatically, but by making it more convenient to find them I hope it can significantly improve the odds that they will be caught (and fixed!) quickly.

find_mass_assignment 插件不能自动修复大量分配问题,但是我认为可以有效的方便的找到这些问题。

2、http://ironshay.com/post/Mass-Assignment-Vulnerability-in-ASPNET-MVC.aspx

While reading about this vulnerability, I figured out that ASP.NET MVC worked in a very similar way… would it reproduce in an ASP.NET MVC environment? well, of course!

ASP.NET MVC 也存在这样的问题

The Problematic Feature

ASP.NET MVC has this very convenient way of getting parameters from the request named Model Binding. The very simple example of Model Binding is controller actions with parameters. For instance:

ASP.NET MVC从请求中方便的获取参数的方式称为模型绑定,模型绑定的简单的例子是使用参数的控制行为,如:

?
1
2
3
4
public ActionResult Create( string name, string email)
{
   // ... do stuff ...
}

In this sample, the Model Binding feature will automatically fill in the name and email parameters with data from the request. Very similar to doing something like that:

在这个例子中,模型绑定会自动的从请求中提取数据填充name和email两个参数,类似于下面的方式:

?
1
2
3
4
5
6
7
public ActionResult Create()
{
   string name = Request[ "name" ];
   string email = Request[ "Email" ];
 
   /// ... do stuff ...         
}

This is already very helpful and it’s getting even better – you can set the parameter to a type of your own, and ASP.NET MVC will create an instance and fill it up for you. For instance, if you have a class named Person like this one:

?
1
2
3
4
5
public class Person
{
   public string Name { get ; set ; }
   public string Email { get ; set ; }
}

You can change the Create method to:

?
1
2
3
4
public ActionResult Create(Person person)
{          
   /// ... do stuff ...
}

By doing this, the Person.Name and Person.Email properties will automatically be filled in by ASP.NET MVC Model Binding.

OK, now that we understand what the essence of model binding is, let’s move on to the problem it represents…

Reproducing the Vulnerability

  1. Create a new ASP.NET MVC Application (I tried it with ASP.NET MVC 3 and 4).
  2. Add a new model class named User, as follows:
    ?
    1
    2
    3
    4
    5
    6
    7
    public class User
    {
       public int Id { get ; set ; }
       public string Name { get ; set ; }
       public string Email { get ; set ; }
       public bool IsAdmin { get ; set ; }
    }
  3. Use the Add Controller dialog box to create a database context and a controller. Call it UsersController. Set the dialog properties as follows:
    Add Controller UsersController
  4. We don’t want the users to change the IsAdmin boolean value. It will be set somehow by the logics of the application later on. Therefore, open the Create.cshtml and Edit.cshtml views (they’re located under the Views/Users folder), and remove the IsAdmin part from them. The part to remove should look something like that:
    ?
    1
    2
    3
    4
    5
    6
    7
    <div class = "editor-label" >
         @Html.LabelFor(model => model.IsAdmin)
    </div>
    <div class = "editor-field" >
         @Html.EditorFor(model => model.IsAdmin)
         @Html.ValidationMessageFor(model => model.IsAdmin)
    </div>

 

Now to the interesting part:

  1. Run the application and browse to /Users/Create
  2. Fill up the form and send. You’ve got a new user. IsAdmin is false.
  3. Go to the Edit page for this user. The URL will be something like /Users/Edit/1.
  4. Change the URL to /Users/Edit/1?IsAdmin=true and click enter to browse to it.
  5. Now click Save
  6. IsAdmin is now saved as True to the database. Oops.

This example is very very simple, but think about real world scenarios… this might get ugly. Very ugly. The biggest site that suffered the consequences of this vulnerability(based on Rails, but it’s the same thing) is GitHub – you can read their announcement here.

How to Defend

ASP.NET MVC offers a very simple solution to that problem – the Bind(Exclude=””) Attribute.  However, most people never use this feature. So… make a new habit from today – start using it. ALL THE TIME. And when I say ALL THE TIME, I mean that from now on you use it ALL THE F***ING TIME.

For my small sample, add [Bind(Exclude = "IsAdmin")] to the top of the model class (User.cs). After this change the model class should look like that:

?
1
2
3
4
5
6
7
8
[Bind(Exclude = "IsAdmin" )]
public class User
{
   public int Id { get ; set ; }
   public string Name { get ; set ; }
   public string Email { get ; set ; }
   public bool IsAdmin { get ; set ; }
}

Rebuild and try our little hack again. It won’t work this time. Phew.

Stay safe,
Shay.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值