java secure coding guide: Mutability variability

catalogue

brief introduction

mutable (variable) and immutable (immutable) objects are often used in the process of java programming.

Variable type object means that after the object is created, its internal data may be modified. So its security is not guaranteed.

The immutable type object means that once the object is created, its internal data cannot be modified. We can fully trust this object.

Although the security of mutable object is not enough, because it can be modified, it will effectively reduce the copy of the object.

The immutable object cannot be changed, so any attempt to modify the object will lead to a copy of the object and generate a new object.

The most commonly used String is an immutable object.

So what is the best practice of variability in java security coding? Let's have a look.

Mutable and immutable objects

After knowing the difference between variable object and immutable object, how can we judge whether this object is variable object or immutable object?

First of all, the simplest point is that immutable objects cannot be modified after they are created, so there are basically no setXXX methods in immutable objects, while variable objects provide setXXX methods that can modify the state of internal variables.

Look at an example Java util. Date is a mutable object, while Java time. Localtime is an immutable object.

What's the difference between their method definitions?

The first is Date. We can see that many setXXX methods are defined in it.

In LocalTime, we can hardly see the setXXX method.

At the same time, the fields of immutable objects are basically final to prevent secondary modification.

Second, immutable objects are generally non inheritable. In java, they are limited by the final keyword:

public class Date
public final class LocalTime

Third, immutable objects generally hide constructors, but use methods similar to factory mode to create objects, which provides more flexibility for instance creation.

Create a copy of the mutable object

So what if we want to use mutable objects without being modified by others?

The simple way is to copy an object to be used:

public class CopyOutput {
            private final java.util.Date date;
            ...
            public java.util.Date getDate() {
                return (java.util.Date)date.clone();
            }
        }

Here we should also pay attention to the problem of deep copy and shallow copy.

Create a copy method for the mutable class

Since you want to create a copy of the mutable object, the corresponding mutable class also needs to provide a copy method to assist in copying.

Here we need to consider the problem of deep copy and shallow copy.

Don't trust equals

Do we know how to find a key in HashMap? Find the value of. Key first, and then go to. hash Whether the equals method is equal, consider the following:

private final Map<Window,Extra> extras = new HashMap<>();

        public void op(Window window) {
            Extra extra = extras.get(window);
        }

The op method receives a Window object and takes it as a key to get the corresponding value from the HashMap.

If, at this time, we have A class A inheriting Window, and the hash value and equals are the same as those of another Window object B, then we can use the key A to obtain the data stored by the key B!

How to solve this problem?

There is a special HashMap in Java: IdentityHashMap. The key and value of this Map are compared with = = instead of equals, so the above problems can be effectively avoided.

private final Map<Window,Extra> extras = new IdentityHashMap<>();

        public void op(Window window) {
            Extra extra = extras.get(window);
        }

If no such Map is available, you can use the immutable object as the key or use the private variable of Window, so that the malicious attacker cannot obtain this variable.

public class Window {
            /* pp */ 
            class PrivateKey {
                Window getWindow() {
                    return Window.this;
                }
            }
            final PrivateKey privateKey = new PrivateKey();

            private final Map<Window.PrivateKey,Extra> extras =
                 new WeakHashMap<>();
            ...
        }

        public class WindowOps {
            public void op(Window window) {
                // Window.equals may be overridden,
                // but safe as we don't use it.
                Extra extra = extras.get(window.privateKey);
                ...
            }
        }

Do not directly expose modifiable properties

If a property in a mutable class really needs to be exposed for external use, be sure to define the property as private and wrap it with the wrapper method.

If it is directly exposed, there is basically no permission control. Any program can modify the properties as long as it can get your object. Considering the following application methods, we add a parameter verification and permission control to the method of modifying state.

public final class WrappedState {
            // private immutable object
            private String state;

            // wrapper method
            public String getState() {
                return state;
            }

            // wrapper method
            public void setState(final String newState) {
                this.state = requireValidation(newState);
            }

            private static String requireValidation(final String state) {
                if (...) {
                    throw new IllegalArgumentException("...");
                }
                return state;
            }
        }

public static fields should be set to final

Similarly, if you are a class variable and of course you don't want this variable to be modified by anyone, you need to set it to final.

public class Files {
            public static final String separator = "/";
            public static final String pathSeparator = ":";
        }

public static final field should be immutable

If the class variable is public static final, the variable must be immutable.

Some people will ask, are all defined as final, is it immutable?

In fact, it is not. For example, we define a final list. Although the list cannot be changed, the values in the list can be changed. We need to change the variable variable variable to the immutable variable, as shown below:

import static java.util.Arrays.asList;
        import static java.util.Collections.unmodifiableList;
        ...
        public static final List<String> names = unmodifiableList(asList(
            "Fred", "Jim", "Sheila"
        ));

If you use the of() or ofEntries() methods introduced in JDK9, you can directly create immutable Collections:

public static final List
<String> names =
 List.of("Fred", "Jim", "Sheila");

This article has been included in http://www.flydean.com/java-security-code-line-mutability/

The most popular interpretation, the most profound dry goods, the most concise tutorial, and many tips you don't know are waiting for you to find!

Welcome to my official account: "procedures and things". I understand technology and you better!

Tags: Java

Posted by faizanno1 on Thu, 19 May 2022 23:09:08 +0300