2013-03-07 3 views
14

私はJavaに慣れていないし、学習するときにStringが不変であるという事実を知りました。その背後にある理由を読んでいたとき、値を変更することができず、複数のスレッドで共有できるなど、いくつかの理由がありました。私が理解するこれらの理由。
しかし、私はそれがセキュリティにどのように関係しているかは分かりません。 StringはどのようにJavaセキュリティの不変のヘルプですか?Java文字列が不変であればセキュリティは向上しますか?

ご理解をお願いします。前もって感謝します。

+2

セキュリティ上の理由はどこですか? – ivant

+0

[Java継承の重複可能性、どのようにクラスを拡張すると実際のクラスに影響しますか?](http://stackoverflow.com/questions/15165619/java-inheritance-how-does-a-extending-a-class-effect-実際のクラス) – jtahlborn

答えて

15

書き込みクラスライブラリでは非常に一般的な方法は次のように、コンストラクタで、たとえば、あなたのAPIに渡されたパラメータを格納している:

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; 
    } 
} 

Stringであり、これは微妙な悪用につながります。攻撃者は良いURLを渡し、数マイクロ秒待って攻撃サイトを指すようにURLを設定します。

文字列が最も一般的に使用されるデータ型の中にあるため、文字列を変更可能なままにすると、重大なセキュリティ上問題が発生していない多くのAPIが開かれます。文字列を不変にすると、まだ書かれていないAPIを含むすべてのAPIのセキュリティホールが閉じられます。

+1

( "部分的な")可変性の良い例は 'File'です。基本的には 'String'をラップします。しかし、セキュリティチェックのために使用されたケースが数多くあります。悪意のあるサブクラスは、チェックと使用(TOCTOU/TOC2TOUの脆弱性)を変更する可能性があります。 –

+1

微妙なエクスプロイトがどのように行われているのかわかりませんが、このメソッドが別のスレッドを介して何らかの形で傍受されると仮定しています。基本的に、MyApiコンストラクタがurlString "ABC"で呼び出された場合、Stringは不変なので、コンストラクタの外側から内容を変更することはできません。不変でない場合は、単にurlString = "someMaliciousUrl"を呼び出すことによって、他のスレッドで変更することができます。 checkApprovedUrl呼び出しの後にその理解は正しいのでしょうか? – Mercury

+0

@水銀はい、これは上記の攻撃の正しい理解です。 – dasblinkenlight

0

文字列が不変であるということは、オブジェクト自体を変更することはできませんが、もちろん参照を変更することができます。例えばa = "ty"を呼び出すと、実際にはaの参照をStringリテラル "ty"によって作成された新しいオブジェクトに変更しています。オブジェクトを変更すると、例えば、そのフィールドの1つを変更し、そのメソッドを使用することを意味します

Foo x = new Foo("the field"); 
x.setField("a new field"); 
System.out.println(x.getField()); // prints "a new field" 

(finalとして宣言された)不変クラスでは、例えば、文字列のために、あなたは現在の文字列を変更することはできませんが、返すことができながら、新しいString、すなわち:

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" 
+4

"final"はそれが不変であることを意味しません。クラスの場合、それを継承することはできません。 – ivant

+0

が不変であるとすると、サブクラスが不変性を破らないようにfinalでなければなりません – topcat3

+0

しかし、それは不変にするためにfinal宣言するだけでは不十分です。 – ivant

3

不変の文字列は、SecurityManagerコンセプトが機能するために必要です。 dasbklinkenlightはすでに正しい答えを示していますが、変更可能な文字列はサンドボックスの概念を完全に破るでしょう。あなたは、ファイルを読むためにnew FileInputStream("foo");を行う際に、APIの実装では、内部で他の人の間で行います。例えば

、:

  • は、引数として「FOO」でセキュリティマネージャのcheckReadメソッドを呼び出している場合は例外をスローチェックが
  • 使用のオペレーティングシステムは、セキュリティチェックは呼び出しは、これら2つのステップの間に文字列を変更することが可能である場合は、セキュリティチェックが1のために成功するかもしれ

を渡された場合、実際にファイルを開くために呼び出して失敗しました実際には別のファイルが開かれます。

+0

私が正しく理解していれば、Javaが渡すので疑いがあります。値のセキュリティチェックはfooに対してのみ起こりましたfooのみが開きます –