Botre Posted June 14, 2016 Share Posted June 14, 2016 Intro Hello, today we are going to be cracking safes while learning a bit about virtual methods and how they are potentially exposing your code to exploits. Definition The wikipedia definition of "virtual method": In object-oriented programming, in languages such as C++, a virtual function or virtual method is an inheritable and overridable function or method for which dynamic dispatch is facilitated. This concept is an important part of the (runtime) polymorphism portion of object-oriented programming (OOP). Java In Java, methods are virtual by default, all methods are overridable unless any of the following criteria is met: A method is declared final. A method is declared static. The method's class is declared final (since the parent can not be sublcassed, an alternate implementation can not be provided). Annotations can be used in certain frameworks to devirtualize methods. The "Safe" class In order to point out some of the most basic vulnerabilities virtual methods can create, let's create a very simple POJO safe: This safe can be locked, unlocked with a password, and if unlocked: retrieve a treasure. public class Safe { private String password = "maldesto69"; private String treasure = "Treasure"; private boolean unlocked = false; /** * Unlocks the safe if the correct password is supplied. * @param password */ public void unlock(String password) { if(this.password.equals(password)) { unlocked = true; } else { throw new SecurityException(); } } /** * Locks the safe. */ public void lock() { unlocked = false; } /** * Checks whether the safe is unlocked. */ public boolean isUnlocked() { return unlocked; } /** * Returns the treasure if the safe is unlocked. */ public String getTreasure() { if(isUnlocked()) { return treasure; } else { throw new SecurityException(); } } } Here's how the designer intended the class to work: public static void main(String[] args) { // Create a new safe. Safe safe = new Safe(); // Print whether the safe is unlocked. System.out.println(safe.isUnlocked()); // Unlock the safe. safe.unlock("maldesto69"); // Print whether the safe is unlocked. System.out.println(safe.isUnlocked()); // Get the treasure. System.out.println(safe.getTreasure()); } false true Treasure Everything goes well and the treasure remain safe, until someone discovers the designer forgot protecting some of his methods, by anonymously sub-classing the treasure class (the class was not declared final) and overriding the isUnlocked method (which was also not declared final), the safecracker managed to entirely bypass the password system by simply making the lock getter return true unconditionally. public static void main(String[] args) { // Create a new safe, exploit the fact that isUnlocked is virtual. Safe safe = new Safe(){ @Override public boolean isUnlocked() { return true; } }; // Print whether the safe is unlocked. System.out.println(safe.isUnlocked()); // Get the treasure. System.out.println(safe.getTreasure()); } true Treasure There are plenty of solutions here: Make isUnlocked final so it can not be overriden. Make getTreasure use the variable instead of its getter. Make Safe final. Our designer opts to simply make isUnlocked final (something he will regret sooner rather than later), a new treasure is put in to the safe and everything is dandy. A couple of days later however, the programmer gets some reports about people finding odd items in their safe (panties, slimey socks, you name it (or don't)). public static void main(String[] args) { // Create a new safe, exploit the fact that getTreasure is virtual. Safe safe = new Safe(){ @Override public String getTreasure() { return "Fake treasure"; } }; // Print whether the safe is unlocked. System.out.println(safe.isUnlocked()); // Get the treasure. System.out.println(safe.getTreasure()); } false Fake treasure isUnlocked was secured, but getTreasure, a vital method of the class, remained untouched and allowed the nasty hacker to spoof fake treasure return values. The safe was sabotaged, customers panicked, the programmer's client faced multiple law suits and our designer was of course fired, never to work a programming job in his life again. The end. 8 Quote Link to comment Share on other sites More sharing options...
Harry Posted June 14, 2016 Share Posted June 14, 2016 I love this, great post. Quote Link to comment Share on other sites More sharing options...