ModelDriven 接口是否在 struts2 中提出了安全问题?

2022-01-16 00:00:00 exploit java Hibernate struts2

背景:我用 ModelDriven 编写了一个 struts2 ActionSupport 类.这是一个 hibernate/spring web 应用程序,使用 OSIV 和视图中的附加实体 (JSP).

background: I coded a struts2 ActionSupport class with ModelDriven. It's a hibernate/spring web app, using OSIV and attached entities in the view (JSP).

我今天收到了建筑师惩罚"我放置物品的这封电子邮件通过ModelDriven 接口.他是对的还是什么?显然,这是我正在做的一件严肃的事情,但我并没有听从他的话,而且我真的不想接受他的提议并在那之后去他的办公桌前拜访他.好家伙.是时候换个职业了.

I received this email today from the architect 'punishing' me for putting an object that had a reference to an attached entity on the struts2 valuestack via the ModelDriven<E> interface. Is he correct or what? Obviously, this is a serious thing I am doing but I am not following what he is saying, and I really don't feel like taking up his offer and visiting him at his desk after this. oh boy. Time to change careers.

---来自建筑师---

--- from the architect ---

Billy,正如我们之前所讨论的,您的代码中仍然存在同样的错误一遍又一遍地.这是您第四次犯此错误,我很担心关于你的工作质量.做一次甚至两次是一回事,但是第四次之后,我想知道你是否无法理解我在说什么.下面将为您一一解读.如果您在阅读此电子邮件后没有收到它,请到我的办公桌前,我们会仔细阅读.这必须立即停止,我想要所有你的代码在一天结束之前重构,纠正了这个错误.如果有任何代码喜欢这会流血到生产中,我们将面临严重的安全问题.另请注意,我在这方面抄袭戴夫,以便发出适当的谴责.我还将向 Dave 推荐您从 III 级开发人员转到 II 级开发人员.请阅读以下内容并学习它,并按照我的指示重构您的所有代码.

Billy, as we previously discussed, you are still making the same mistakes in your code over and over again. This is the forth time you have made this error and I'm concerned about the quality of your work. It's one thing to make this once or even twice, but after the forth time, I am wondering if you are unable to comprehend what I am saying. The following will spell it out for you. If you don't get it after reading this email, then come to my desk and we'll go over it. This has to stop immediately, and I want all your code refactored before the end of the day correcting this mistake. If any code like this bleeds into production, we'll have a serious security problem on our hands. Also note that I am copying Dave on this so that a proper reprimand can be issued. I am also going to recommend to Dave that you be moved from a Level III to Level II developer. Read the following and please learn it, and refactor all your code as I've indicated.

关于绑定对象:

当一个 Struts2 动作类被标记为 ModelDriven 接口时,模型将绑定到 HTML 页面中的表单元素.例如,如果一个 HTML 表单有一个名为 userName 的字段和一个动作类定义为:

When a Struts2 action class is marked with ModelDriven interface, the model will be bound to the form elements in the HTML page. For example, if an HTML form has a field called userName and an action class is defined as:

公共类 UserAction 扩展 ActionSupport 实现 ModelDriven

public class UserAction extends ActionSupport implements ModelDriven

而UserModel是一个POJO如下:

And UserModel is a POJO as follows:

public class UserModel {
  private String userName;

  public String getUserName() {
      return userName;
  }

  public void setUserName(String userName) { 
      this.userName = userName;
  }
}

表单提交时,只要Action包含UserModel的实例,struts2将字段 userName 绑定到 UserModel.userName,自动填充值.

When the form is submitted, as long as the Action contains an instance of UserModel, struts2 will bind the field userName to UserModel.userName, automagically populating the value.

但是,这种简单性对于恶意用户来说代价高昂.如果声明了一个对象作为 ModelDriven,最终用户,即浏览用户,可以访问模型图通过模型设置器.以这个案例为例:

This simplicity has a high cost for malicious users, however. If an object is declared as ModelDriven, the end-user, the browsing user that is, has access to the models graph via the models setters. Take this case for example:

公共类 UserAction 扩展 ActionSupport 实现 ModelDriven

public class UserAction extends ActionSupport implements ModelDriven

还有……

public class UserModel {
  private String userName;
  private UserEntity userEntity;

  public String getUserName() {
      return userName;
  }

  public void setUserName(String userName) { 
      this.userName = userName;
  }

  pubic UserEntity getUserEntity() {
      return userEntity;
  }
}

还有……

@Entity
public class UserEntity {
    private String password;

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
 }

假设正在使用 OSIV 模式,并且附加了实体 UserEntity.

assuming the OSIV pattern is being used, and the entity UserEntity is attached.

有一点先见之明或手头有时间的狡猾用户可能会:

A crafty user with a bit of fore knowledge or time on his hands may:

/myform?userName=billy&userEntity.password=newpassword

假设实体在会话结束时保存,上述结果会发生变化比利的密码.

assuming the Entity is saved at the end of the session, the above results in changing billy's password.

关键是,对象图是可用的!

The point is, the object graph is available!

当使用 ModelDriven 并且使用替代方法是一种可怕的方法时,您必须定义放置在 valuestack 上的细粒度模型,然后从模型复制到在发送响应并允许事务提交之前的目标对象.

When using ModelDriven, and using the alternative is a horrible approach, you must define fine grained models that are placed on the valuestack, and then copy from the model to the target object before sending the response and allowing the transaction to commit.

推荐答案

您的架构师是对的,将有权访问敏感信息的对象放在 ValueStack 上会带来潜在的安全风险.恶意用户确实可以通过上述攻击重置密码.

Your architect is right, putting objects with access to sensitive information on the ValueStack poses a potential security risk. A malicious user could indeed reset the password with the above attack.

但是:

由于他是一名架构师,他应该设计出正确验证/限制输入参数的方法.在 Struts2 中使用 ParamsInterceptor 很容易只允许将特定参数传递给动作.因此,糟糕的不是你的工作,而是你的系统架构.开发人员应该能够专注于实现业务逻辑.基础架构必须由架构师提供.

Since he is an architect he should have designed ways for proper validation/restriction of input parameters. Using the ParamsInterceptor in Struts2 it's fairly easy to only allow specific parameters to be passed to an action. Thus, it's not your work that sucks, it's your system's architecture. Developers should be able to focus on implementing business logic. The infrastructure must be provided by the architect.

干杯,

w

相关文章