程式設計師面試系列之Java單例模式的攻擊與防禦
我寫的程式設計師面試系列
Java面試系列-webapp資料夾和WebContent資料夾的區別?
程式設計師面試系列:Spring MVC能響應HTTP請求的原因?
Java程式設計師面試系列-什麼是Java Marker Interface(標記介面)
JavaScript面試系列:JavaScript設計模式之橋接模式和懶載入
使用JavaScript ES6的新特性計算Fibonacci(非波拉契數列)
單例模式在很多Java程式設計師的眼中,應該是設計模式裡最簡單的一種了。那麼單例模式可能會被攻擊,您聽說過麼?
說到“單例模式被攻擊”這個話題,大家最容易想到的可能就是通過序列化/反序列化來攻擊單例模式,因為一個物件例項序列化再反序列化後,得到的新的物件雖然各欄位內容和原欄位一致,然而物件地址和原始物件地址相比已經發生了變化,因此它們是兩個不同的物件。
上面的結論完全正確,然而除了序列化/反序列化,單例模式還可能遭受另一種方式的攻擊,即反射攻擊(Reflection attack)。
看一個具體例子:
public class JerrySingleton { private String name; private JerrySingleton(){ name = "Jerry"; }private static class SingletonHolder{ private static final JerrySingleton INSTANCE = new JerrySingleton(); }public static JerrySingleton getInstance() { return SingletonHolder.INSTANCE; } }
上面是一個餓漢式單例。
然而我只需要將這個單例類JerrySingleton的建構函式通過反射設定成可以訪問Accessible,然後就能通過反射呼叫該建構函式,進而生成新的物件例項。這樣就破壞了單例模式。
Class<?> classType = JerrySingleton.class; Constructor<?> c = classType.getDeclaredConstructor(null); c.setAccessible(true); JerrySingleton e1 = (JerrySingleton)c.newInstance(); JerrySingleton e2 = JerrySingleton.getInstance(); System.out.println(e1 == e2);
第6行程式碼會列印false。
針對這種攻擊,一種可行的防禦措施是在單例類的建構函式內定義一個布林變數,初始化為false。當建構函式執行後,該變數被置為true。如果接下來建構函式再次被執行,則人為丟擲異常,避免建構函式重複執行。
public class JerrySingletonImproved { private static boolean flag = false; private JerrySingletonImproved(){ synchronized(JerrySingletonImproved.class) { if(flag == false) { flag = !flag; } else { throw new RuntimeException("Singleton violated"); } } } }
這種防禦措施無法從根本上杜絕Singleton被攻擊,因為攻擊者仍舊可以通過反射來修改布林變數flag的值,從而繞過這個檢查。
最理想的不會受到攻擊的單例模式實現是藉助Java裡列舉類Enumeration的特性:
這種實現型別的單例模式的消費程式碼:
System.out.println("Name:" + JerrySingletonAnotherApproach.INSTANCE.getName());
如果攻擊者通過前面介紹的反射程式碼對這種實現方式的單例進行攻擊,JDK會丟擲NoSuchMethodException異常:
Exception in thread "main" java.lang.NoSuchMethodException: singleton.JerrySingletonAnotherApproach.<init>() at java.lang.Class.getConstructor0(Class.java:3082) at java.lang.Class.getDeclaredConstructor(Class.java:2178) at singleton.SingletonAttack.test3(SingletonAttack.java:31) at singleton.SingletonAttack.main(SingletonAttack.java:43)
究其原因,是因為現在我們是通過Java列舉方式實現的單例,列舉類沒有傳統意義上的建構函式,因此對這種反射攻擊免疫。
要獲取更多Jerry的原創技術文章,請關注公眾號"汪子熙"或者掃描下面二維碼:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2214340/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java設計模式系列之單例設計模式Java設計模式單例
- CSRF 攻擊與防禦
- WEB攻擊與防禦Web
- CSRF攻擊與防禦
- WMI 的攻擊,防禦與取證分析技術之防禦篇
- CSS keylogger:攻擊與防禦CSS
- WMI 的攻擊,防禦與取證分析技術之攻擊篇
- Java設計模式之單例模式Java設計模式單例
- Kotlin 設計模式系列之單例模式Kotlin設計模式單例
- 淺談DDos攻擊與防禦
- DDoS攻擊、CC攻擊的攻擊方式和防禦方法
- 折騰Java設計模式之單例模式Java設計模式單例
- 《我是面試官》設計模式-單例模式面試設計模式單例
- 【Java面試指北】單例模式Java面試單例模式
- 伺服器防禦流量攻擊的簡單方法!伺服器
- 生成樹欺騙攻擊與防禦策略
- Android面試之Java設計模式Android面試Java設計模式
- 設計模式之單例設計模式設計模式單例
- Java設計模式【單例模式】Java設計模式單例
- Java設計模式 | 單例模式Java設計模式單例
- Java設計模式——單例模式Java設計模式單例
- Java設計模式–單例模式Java設計模式單例
- Java設計模式-單例模式Java設計模式單例
- Java設計模式--單例模式Java設計模式單例
- 如何有效防禦DDoS攻擊和CC攻擊?
- 好程式設計師:Java程式設計師面試秘籍程式設計師Java面試
- 面對境外網路的攻擊,該如何有效防禦?
- 設計模式之單例模式設計模式單例
- 設計模式之☞單例模式設計模式單例
- 設計模式之---單例模式設計模式單例
- Java HTTP Host 頭攻擊原理以及如何防禦JavaHTTP
- java單例設計模式Java單例設計模式
- JAVA設計模式 1 設計模式介紹、單例模式的理解與使用Java設計模式單例
- 高防伺服器主要防禦的攻擊伺服器
- 在面對攻擊時,怎麼樣有效防禦?
- 設計模式之單例設計模式單例
- DDoS 攻擊與防禦:從原理到實踐
- 面試之---手寫單例模式面試單例模式