Blogger Information
Blog 3
fans 0
comment 0
visits 2093
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
java安全编码指南之:敏感类的拷贝
霸王防脱发
Original
425 people have browsed it

简介
一般来说class中如果包含了私有的或者敏感的数据的时候是不允许被拷贝的。

如果一个class不想被拷贝,我们是不是不提供拷贝的方法就能保证class的安全了呢?

一起来看看吧。

一个简单的SensitiveObject
假如我们有下面的一个SensitiveObject,它的作用就是存储一个password,并且提供了一个修改password的方法:

public class SensitiveObject1 {
private char[] password;

  1. SensitiveObject1(String iniValue){
  2. this.password = iniValue.toCharArray();
  3. }
  4. public final String get() {
  5. return String.valueOf(password);
  6. }
  7. public final void doPasswordChange(){
  8. for(int i = 0; i < password.length; i++) {
  9. password[i]= '*' ;}
  10. }
  11. public final void printValue(){
  12. System.out.println(String.valueOf(password));
  13. }

}
看上去没什么问题,如果我们希望密码被返回之后就不能够被修改,应该怎么做呢?

SensitiveObject的限制
为了实现上面的功能,我们可以考虑引入一个是否返回的变量,如果返回过了,就不允许进行密码修改了。

那么我们可以将上面的代码修改成这样:

public class SensitiveObject2 {
private char[] password;
private boolean returned=false;

  1. SensitiveObject2(String iniValue){
  2. this.password = iniValue.toCharArray();
  3. }
  4. public final String get()
  5. {
  6. if(!returned) {
  7. returned=true;
  8. return String.valueOf(password);
  9. }else {
  10. throw new IllegalStateException("已经返回过了,无法重复返回");
  11. }
  12. }
  13. public final void doPasswordChange(){
  14. if(!returned) {
  15. for (int i = 0; i < password.length; i++) {
  16. password[i] = '*';
  17. }
  18. }
  19. }

}
通过加入了returned标签,我们可以控doPasswordChange方法,只能在未返回之前进行密码修改。

我们看下调用代码:

  1. SensitiveObject2 sensitiveObject2= new SensitiveObject2("www.flydean.com");
  2. sensitiveObject2.doPasswordEncrypt();
  3. System.out.println(sensitiveObject2.get());

对SensitiveObject的攻击
怎么对上述代码进行攻击呢?

如果我们想在密码返回之后仍然对密码进行修改,怎么做到呢?

如果SensitiveObject2可以拷贝,我们是不是就能够保存一份char[]和boolean的副本了呢?

因为char[]属于引用拷贝,所以在拷贝的副本里面对char[]进行修改完全可以影响到原SensitiveObject2的内容。

但是,虽然clone方法是定义在Object中的,如果子类没有实现Cloneable接口的话,将会抛出CloneNotSupportedException异常。

考虑到SensitiveObject2不是一个final的类,我们可以通过继承SensitiveObject2来实现目的:

public class MaliciousSubSensitiveObject extends SensitiveObject2 implements Cloneable{
MaliciousSubSensitiveObject(String iniValue) {
super(iniValue);
}

  1. public MaliciousSubSensitiveObject clone(){
  2. MaliciousSubSensitiveObject s = null;
  3. try {
  4. s = (MaliciousSubSensitiveObject)super.clone();
  5. } catch(Exception e) {
  6. System.out.println("not cloneable");
  7. }
  8. return s;
  9. }
  10. public static void main(String[] args) {
  11. MaliciousSubSensitiveObject object1 = new MaliciousSubSensitiveObject("www.flydean.com");
  12. MaliciousSubSensitiveObject object2 = object1.clone();
  13. String password1= object1.get();
  14. System.out.println(password1);
  15. object2.doPasswordChange();
  16. object1.printValue();
  17. }

}
可以看到,虽然object1先返回了password,但是这个password被clone过的object2进行了修改,最终导致object1中的password值发生了变化。

解决办法
怎么解决呢?

一个简单的方法就是将SensitiveObject class定义为final,这样就不能继承,从而避免了上诉问题。

Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post