I am new to Java and when learning, I came across the fact that a String
is immutable. When I was reading the reason behind it, a few reasons came up, for example performance increasements, since its value cannot be modified, and it can be shared by multiple threads. These reasons I do understand.
But I don't get how it is related to security. How does a String
being immutable help in Java security?
Please help me in understanding. Thanks in advance.
A very common practice in writing class libraries is storing the parameters passed into your API, say, in a constructor, like this:
public class MyApi {
final String myUrl;
public MyApi(String urlString) {
// Verify that urlString points to an approved server
if (!checkApprovedUrl(urlString)) throw new IllegalArgumentException();
myUrl = urlString;
}
}
Were String
mutable, this would lead to a subtle exploit: an attacker would pass a good URL, wait for a few microseconds, and then set the URL to point to an attack site.
Since storing without copying is a reasonably common practice, and because strings are among the most commonly used data types, leaving strings mutable would open up many APIs that are not written yet open to a serious security problem. Making strings immutable closes this particular security hole for all APIs, including the ones that are not written yet.
Immutable strings are required for the SecurityManager concept to work. dasbklinkenlight is already on the right track with his answer, but mutable strings would break the sandbox concept entirely.
For example, when you do a new FileInputStream("foo");
to read a file, the API implementation will internally do among others:
- invoke the security manager's checkRead method with "foo" as an argument and throw an exception if the check fails
- use operating system calls to actually open the file if the security check passed
If the invoker is able to modify the string between these two steps, the security check may succeed for one file, while actually a different file will be opened.
String is immutable means that you cannot change the object itself, but you can change the reference of course. When you call(for example) a = "ty", you are actually changing the reference of a to a new object created by the String literal "ty". Changing an object means to use its methods to change one of its fields, for example:
Foo x = new Foo("the field");
x.setField("a new field");
System.out.println(x.getField()); // prints "a new field"
while in an immutable class (declared as final), for example String, you cannot change the current String but you can return a new String, i.e:
String s = "some text";
s.substring(0,4);
System.out.println(s); // still printing "some text"
String a = s.substring(0,4);
System.out.println(a); // prints "some"