What are the consequences of Java strings that are not immutable?

Background

In Java 101, we are taught:

A String is immutable.

Yes. Good. Thanks.

Then we go to Java 102 (or, possibly, to Java 201), and find:

A String is not really immutable: you can change it with reflection.

Oh. Good. Either pretty cute or immeasurably perverse, depending on your perspective.

These things have so far been discussed endlessly about stack overflows and elsewhere. I take this for granted in formulating this question.

I am interested to ask:

Question

Once we find that String not really immutable, what are the implications for how we should write our code?

Let me make this more specific in two ways.

JVM Sandbox

Is it possible for a malicious class to use this trick to violate the security of the JVM and get up to tricks that it should not do? Are there any places in the JDK, for example, where a String returned from a method and is safe only if it cannot be changed?

Here's a promising start:

  String prop = "java.version"; // retrieve a System property as a String String s = System.getProperty(prop); System.out.println(s); // now mess with it Field field = String.class.getDeclaredField("value"); field.setAccessible(true); char[] value = (char[])field.get(s); value[0] = 'x'; //turns out we've changed not just the String we were //given but the underlying property too! System.out.println(System.getProperty(prop)); 

This is done to retrieve the system property from the JVM returned as String , and then change the String ; the consequence is that the underlying property also changes. Could this be used to cause chaos?

I'm not sure. It is worth noting that you must have the correct permissions to reflect. Is a security game already on this? This allows me to do without the right to change security properties, but can this be expected or is this a problem?

Are there any ways to extend this to make something much worse?

Defensive cloning

We are always told that it is recommended to clone arrays and other objects before passing them to methods that can modify them if we do not want them to be changed. This is just good coding practice. This is your own stupid mistake if you give someone the only copy of your array and it gets back in a mess.

But it looks like the same argument should apply to String ! I have never heard anyone say that we must clone a String before passing it to a method written by another. But how could it be otherwise if String is as volatile as an array?

Argument for Clone Protective Strings

If defensive cloning is due to the fact that he does not know what the method can do with the things we transmit, and if what we transfer is volatile, then we should clone it. If the code may be malicious, it may modify String ; therefore, when it is important that the String remains unchanged, we need to make sure that we are sending a copy, not the real thing.

This is not to say that untrusted code should run under a security manager if we do not trust it to not do bad things in String . If this were true for String , this would be true for an array; but no one ever says that cloning arrays and other objects should only be done when you also block the code with the security manager.

Argument Against Clone Protective Strings

An array can only be modified using sloppy encoding; in other words, it may be changed unintentionally. But nobody changes String unintentionally: this can only be done with the help of vile tricks, which means that the programmer tried to break immutability.

This makes two cases different. We really do not have to pass an array, not even a clone of it, to encode that we do not trust at any level. You are not loading the library from somewhere dodgy, and then you think that everything is in order, because you cloned your array. You clone defensively because you think that a programmer may make mistakes or make different assumptions from you about what is valid with the data that you send. If you are concerned that the code might change String behind your back, you really shouldn't run the code at all. All you achieve by cloning a String is overhead.

Answer?

How should we think about this? Is it possible to break the JVM sandbox using these tricks? And should we code defensively in the light of the variability of a String , or is it all a red herring?

+6
source share
2 answers

There is a security setting that you can enable for your Java program. According to Javadocs for setAccessible ,

First, if there is a security manager, its checkPermission method is called with the permission ReflectPermission ("suppressAccessChecks").

In this case, the security flag occurs if the flag is true, but the accessibility of this object cannot be changed (for example, if this element object is a Constructor object for the Class class).

A security exception is thrown if this object is a Constructor object for the java.lang.Class class and the flag is true.

So, with a SecurityManager that does not allow this check, you can prevent any code from successfully calling setAccessible , keeping String s unchanged.

+4
source

Java has mechanisms to prevent this. In particular, for example, to undermine a String, you had to call field.setAccessible(true); which works for you, but if you look at the documentation, calling setAccessible(true) may throw a SecurityException .

Java allows you to install or modify Security Managers that can block these reflection APIs. For example, consider Ideone, which allows you to run limited Java applications. To a large extent, they do this by limiting system security permissions.

You must read the SecuityManager as well as the Trail document

You should also read

+3
source

Source: https://habr.com/ru/post/976388/


All Articles