奇安信代码安全卫士扫描出来的 API误用:不安全的框架绑定 漏洞需要怎么解决?救助!
漏洞·描述为:
目前大部分WEB框架支持将HTTP请求参数与类的属性相匹配的而生成一个对象。因此,攻击者能够将值放入HTTP请求参数中从而绑定系统对象。
例如:在以下代码片段中, Spring MVC可以将 HTTP请求参数绑定到User所有属性。
@RequestMapping("/login" )
public String login(User user) {
...
}
其中,User 类定义为:
public class User {
private String username;
private String address;
private boolean admin;
private int age;
...
}
修复建议:
当程序将非将HTTP请求参数直接绑定给对象时,应该要控制绑定到对象的属性,防止暴露所有属性。
在Spring MVC中,可以配置绑定器使用setAllowedFields
和setDisallowedFields
方法控制属性绑定过程以控制应绑定的属性。
例1:在以下代码片段中,在 Spring MVC(3.0版本至最新)通过setDisallowedFields
方法禁止绑定敏感属性。
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields(new String[]{"admin"});
}
@RequestMapping("/login" )
public String login(User user) {
...
}
例2:在 Spring MVC(2.X版本)通过setDisallowedFields
方法禁止绑定敏感属性。
@Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
binder.setDisallowedFields(new String[]{"admin"});
}
而在使用 @RequestBody
注释参数的 Spring MVC应用程序中,绑定过程由HttpMessageConverter进行处理,这些实例使用Jackson和JAXB等库将 HTTP请求参数转换为Java对象。这些库提供了注释来控制应允许或禁止的字段。例如对于Jackson,可以使用@JsonIgnore
注释禁止将某个字段绑定到请求。
例3:在以下代码片段中,Jackson禁止绑定敏感属性。
@RequestMapping(value="/add/user", method=RequestMethod.POST, consumes="text/html")
public void addEmployee(@RequestBody User user){
...
}
public class User {
private String username;
private String address;
@JsonIgnore
private boolean admin;
private int age;
...
}
同理,Jackson还可以使用@JsonIgnoreProperties、@JsonIgnoreType和 @JsonInclude
等注解告诉框架忽略这些属性,使用JAXB使用@XmlAccessorType、@XmlAttribute、@XmlElement和 @XmlTransient
等注解告诉框架忽略这些属性,然后使用@XmlAttribute和@XmlElement
等注解选择应绑定的字段。
例4:在以下代码片段中,Jackson使用@XmlAttribute
选择要绑定的字段。
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class User {
private String username;
private String address;
@JsonIgnore
private boolean admin;
private int age;
@XmlAttribute
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@XmlAttribute
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
private boolean isAdmin() {
return admin;
}
private void setAdmin(boolean admin) {
this.admin = admin;
}
...
}
在Struts 1和 2 中,如果某个属性不应绑定到请求,则应将其 setter
方法设置为私有即可。
例5:在以下代码片段中,在Struts可以将某个属性的setter
方法设置为私有从而禁止绑定敏感属性。
private boolean admin;
private void setAdmin(boolean admin) {
this.admin = admin;
}
代码中Controller入参为为@RequestBody entity.尝试过在Controller层加@InitBinder,entity里加@JsonIgnoreProperties(ignoreUnknown = true),依旧能扫描出来。救助!