I’m trying to understand how exactly can someone that doesn’t already have access to the source code exploit a non-final class that has a constructor which invokes overridable functions (functions not marked final).
This question comes from the fact that after scanning my source code with a Source Code Analyzer (Fortify), it showed a few findings about “Code Correctness: Constructor Invokes Overridable Function”.
Some of the references for the issue, or bad practice, are:
- Guideline 4-5 / EXTEND-5: Limit the extensibility of classes and methods (link)
- Guideline 7-4 / OBJECT-4: Prevent constructors from calling methods that can be overridden (link)
I understand why the code is being flagged and I also understand how I can mitigate/remove the finding. But I’d like to understand how someone could actually exploit this unless they have access to the source code. Since in that case, they could really just wreak havoc and wouldn’t care much about this triviality. Surely I am missing something!
Advertisement
Answer
You do not need source code to extend a class and overwrite some methods – you only need the corresponding .class
file for that.
Suppose you would do something dumb like
public class PayFlowjoe { public PayFlowjoe() { sendMoneyTo(getRecipient()); } protected String getRecipient() { return "flowjoe"; } private void sendMoneyTo(String recipient) { System.out.println("Sending money to " + recipient); } }
then I could create a class
public class PayMe extends PayFlowjoe { protected String getRecipient() { return "me"; } }
and creating an instance of PayMe
would send money to me instead of you. To compile PayMe
, you only need the PayFlowjoe.class
file. To create an instance of PayMe
and trigger the bad code, you simply need to put PayFlowjoe.class
in the classpath of the application that uses PayMe
.
By the way – it is actually fairly easy to use a decompiler to get the PayFlowjoe
source code from the PayFlowjoe.class
file.