软件框架有时允许开发人员自动将HTTP请求参数绑定到程序变量或对象中,以使开发人员更容易使用该框架开发。这有时会造成伤害。攻击者有时可以使用这种方法来创建,修改,更新开发人员或者业务本身从未打算设计到的参数,而这些新参数反过来又会影响程序代码中不需要的新变量或对象。
本人比较熟悉Java,因此就拿Spring MVC中的自动绑定作为举例,假设有一个用户提交基本信息的功能:
首先看前端html:
<form action=“addUserInfo” method="post">
<input name=username type=text><br>
<input name=phone type=text><br>
<input name=email text=text><br>
<input type=submit>
</form>
很简单,一个form表单,通过post提交username,phone,email到addUserInfo。
我们看一下用户的实体类:
public class User {
private String userid;
private String username;
private String phone;
private String email;
private boolean isAdmin;
//Getters & Setters
}
可以看到User的实体类存在除了username,phone,email还有比较重要的userid和isAdmin参数。
我们接下来看一下controller层如果利用了自动绑定可以写出的处理方式:
@RequestMapping(value = "/addUserInfo", method = RequestMethod.POST)
public String submit(User user) {
userService.add(user);
return "successPage";
}
ok,到这里大家也许应该可以看明白了。
结合上面的demo,我们可以看到,controller层使用的自动绑定对象的方式,也就是使用了post请求的参数直接绑定到了User,虽然前端form表单中仅出现了username,phone,email,但是如果使用burp等工具向addUserInfo发送了
POST /addUserInfo
username=daheike&password=bypass&[email protected]&isAdmin=true
或者
POST /addUserInfo
username=daheike&password=bypass&[email protected]&userid=adminid
那么如果后续使用了被污染的对象的被污染的属性,那么就会产生一定的安全问题。
[1].2012年,GitHub被黑客利用了自动绑定漏洞。用户能够将其公钥上传到任何组织,从而在其存储库中进行更改:https://github.com/blog/1068-public-key-security-vulnerability-and-mitigation
[2].某P2P系统对象自动绑定漏洞可任意充值:https://threathunter.org/topic/593ff6bc9c58e020408a79d4#595485920084b15859bc7219
在案例2中,我猜测可能是编写程序的人员处理不当,导致用户设置地址时自动绑定到了用户对象中,并且orm中并未严格区分业务,将整个用户对象更新,插入到了用户表中,导致了漏洞的触发;那么问题可能就不仅仅是文中的一处看,可能多处都会有该问题存在。
自动绑定漏洞并非仅在Spring MVC中可能出现,只要有自动绑定功能的框架都可能出现这样的逻辑问题。
但是可能对于大部分安全人员来说,可能面对的是一个黑盒的环境,很难发现controller层或者orm是否存在这样的问题,那么可能就需要多个表单的交叉对比,猜测活着推测出可能出现问题的点了。
通用修复方法是:避免将输入直接绑定到域对象,只有用户可以编辑的字段才包含在DTO中。以上文中的deom为例:
public class UserRegistrationFormDTO {
private String username;
private String password;
private String email;
//Getters & Setters
}
或者可以修改controller层,仅接收用户可以修改的参数:
@RequestMapping(value = "/addUserInfo", method = RequestMethod.POST)
public String submit(String username,String phone,String email) {
userService.add(username,phone,email);
return "successPage";
}
也可以设置白名单:
@Controller
public class UserController
{
@InitBinder
public void initBinder(WebDataBinder binder, WebRequest request)
{
binder.setDisallowedFields(["isAdmin"]);
}
...
}
白名单
var UserSchema = new mongoose.Schema({
userid : String,
username : String,
password : String,
email : String,
isAdmin : Boolean,
});
UserSchema.statics = {
User.userCreateSafeFields: ['username', 'password', 'email']
};
var User = mongoose.model('User', UserSchema);
_ = require('underscore');
var user = new User(_.pick(req.body, User.userCreateSafeFields));
黑名单
var massAssign = require('mongoose-mass-assign');
var UserSchema = new mongoose.Schema({
userid : String,
username : String,
password : String,
email : String,
isAdmin : { type: Boolean, protect: true, default: false }
});
UserSchema.plugin(massAssign);
var User = mongoose.model('User', UserSchema);
/** Static method, useful for creation **/
var user = User.massAssign(req.body);
/** Instance method, useful for updating **/
var user = new User;
user.massAssign(req.body);
/** Static massUpdate method **/
var input = { username: 'bhelx', isAdmin: 'true' };
User.update({ '_id': someId }, { $set: User.massUpdate(input) }, console.log);
http://guides.rubyonrails.org/v3.2.9/security.html#mass-assignment
https://coffeeonthekeyboard.com/mass-assignment-security-part-10-855/
白名单:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
private $userid;
private $username;
private $password;
private $email;
private $isAdmin;
protected $fillable = array('username','password','email');
}
黑名单:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
private $userid;
private $username;
private $password;
private $email;
private $isAdmin;
protected $guarded = array('userid','isAdmin');
}
http://spring.io/blog/2012/03/28/secure-data-binding-with-grails/
https://www.playframework.com/documentation/1.4.x/controllers#nobinding
http://www.baeldung.com/jackson-field-serializable-deserializable-or-not
http://lifelongprogrammer.blogspot.com/2015/09/using-jackson-view-to-protect-mass-assignment.html
http://stackoverflow.com/a/27986860
http://json-lib.sourceforge.net/advanced.html
http://flexjson.sourceforge.net/#Serialization
Mass Assignment Cheat Sheet:https://www.owasp.org/index.php/Mass_Assignment_Cheat_Sheet#Solutions