天天看點

《Java編碼指南:編寫安全可靠程式的75條建議》—— 指南10:不要使用clone()方法來複制不可信的方法參數

本節書摘來異步社群《java編碼指南:編寫安全可靠程式的75條建議》一書中的第1章,第1.10節,作者:【美】fred long(弗雷德•朗), dhruv mohindra(德魯•莫欣達), robert c.seacord(羅伯特 c.西科德), dean f.sutherland(迪恩 f.薩瑟蘭), david svoboda(大衛•斯沃博達),更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

建立可變方法參數的防禦性副本,可以減輕來自各種安全漏洞的威脅,更多資訊請參考《the cert® oracle® secure coding standard for java™》[long 2012]的“obj06-j. defensively copy mutable inputs and mutable internal components”。然而,對clone()方法不當地使用,可以使攻擊者利用這一漏洞,提供看上去正常的參數,但随後傳回意想不到的結果。這樣的對象可能是以繞過驗證和安全檢查。當這樣一個類可能會作為一個參數傳遞給一個方法時,應當把這個參數視為不可信任的,同時不要使用該類提供的clone()方法。另外,不要使用未經final修飾的類的clone()方法來建立防禦性副本。

該指南是指南15的一個特定執行個體。

下面的違規代碼示例定義了一個validatevalue()方法來驗證時間值。

class maliciousdate extends java.util.date {

 @override

 public maliciousdate clone() {

  // malicious code goes here

 }

}<code>`</code>

然而,如果攻擊者隻能提供惡意的日期參數,但是沒有足夠特權,他還是可以繞過驗證,進而混淆程式的其餘部分。試想一下這個例子:

private void storedateindb(java.util.date date)

  throws sqlexception {

 final java.util.date copy = new java.util.date(date.gettime());

 if (validatevalue(copy.gettime())) {

  connection con =

   drivermanager.getconnection(

    "jdbc:microsoft:sqlserver://:1433",

    "", ""

   );

  preparedstatement pstmt =

   con.preparestatement("update accessdb set time = ?");

  pstmt.setlong(1, copy.gettime());

  // ...

下面的違規代碼示例展示了一個java核心類atomicreferencearray的構造函數,它來自于java 1.7.0版本的第2次更新。

public atomicreferencearray(e[] array) {

 // visibility guaranteed by final field guarantees

 this.array = arrays.copyof(

  array, array.length, object[].class);

使用clone()方法複制不可信的參數會給攻擊者執行任意代碼的機會。