Before we start to add new detectors in SpotBugs plugin, we first need to know some terminology and structure information.
Terminology
Bug: It is the definition of a vulnerability or sensible point in the application. A bug definition exists by its presence in the findbugs.xml and messages.xml. It can then be reported by any number of detectors.
Detector: A class that implemented the logic to find a bug type. Sometimes refer as "rules" because it is the common designation in other static analysis products.
Modules
The FindsecurityBugs project is divided into four modules:
plugin: Main project containing the FindBugs detectors.
findbugs-test-util: Utility classes that make unit test writing shorter. (Example of test case).
plugin-deps: This provided Mock version of popular Java libraries. Avoid the necessity to download all the libraries used in the FindSecurityBugs sample code.
website: This project contains scripts used to generate the static website hosted on GitHub pages.
Common tasks and key folders
Editing bug messages
Location: plugin/src/main/resources/metadata
The metadata directory contains all the FindBugs configuration files. You will find descriptions in the messages.xml.
Note: Before adding a new language, make sure you are committed to maintaining the changes before major releases. Otherwise, the description will become useless as it doesn't sync with the latest detectors.
Modification of an existing detector
Location: plugin/src/main/java/com/h3xstream/findsecbugs/
You can find the core of plugin in the com.h3xstream.findsecbugs package.
To write a detector, usually, there are five steps.
Creating vulnerable samples
First, create a simple class that illustrates the weakness you are trying to illustrate. Vulnerable sample are place in find-sec-bugs/plugin/src/test/java/testcode.
The code sample doesn't need to be a working application. Write the minimum code to trigger your rule.
For example, this class is created to illustrate Copy/paste buffer caching with CopyPasteLeakageDetector.
sample code
package com.jobair.copypasteleakage;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
public class CopyPasteLeakage extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void onClickCopy(View view) {
ClipboardManager myClipboard = new ClipboardManager();
myClipboard.setPrimaryClip(null);
Toast.makeText(null, "Text Copied",0);
}
}
Writing a test case
We can copy-paste the basic test structure from another test class. For example, here is a test that will validate that CopyPasteLeakage source will trigger the vulnerability "ANDOID_COPYPASTE" at line 25(Actual number base on the line number showed on your IDE).
CopyPasteLeakageDetectorTest
public class CopyPasteLeakageDetectorTest extends BaseDetectorTest {
@Test
public void detectCopyPasteDecoder() throws Exception {
//Locate test code
String[] files = {
getClassFilePath("testcode/android/CopyPasteLeakage")
};
//Run the analysis
EasyBugReporter reporter = spy(new SecurityReporter());
analyze(files, reporter);
verify(reporter).doReportBug(
bugDefinition()
.bugType("ANDROID_COPYPASTE")
.inClass("CopyPasteLeakage")
.inMethod("onClickCopy")
.atLine(35)
.build()
);
//The count make sure no other bug are detect
verify(reporter).doReportBug(
bugDefinition().bugType("ANDROID_COPYPASTE").build());
}
}
You can run a test and it should be failed as you have not written any detector to identify the issue.
Configuration of the new detector
findbugs.xml
<Detector class="com.h3xstream.findsecbugs.android.CopyPasteLeakageDetector" reports="ANDROID_COPYPASTE"/>
[...]
<BugPattern type="ANDROID_COPYPASTE" abbrev="CP" category="SECURITY"/>
Description
We need to create the appropriate description in the messages.xml. You can leave the DetailsXML node empty at this point and fill it later.
messages.xml
<Detector class="com.h3xstream.findsecbugs.android.CopyPasteLeakageDetector">
<Details>Identify of unintended data leakage</Details>
</Detector>
<BugPattern type="ANDROID_COPYPASTE">
<ShortDescription>Clipboard usage</ShortDescription>
<LongDescription>It is not safe to use clipboard without sanitization</LongDescription>
<Details>
<![CDATA[
<p>
Copy/paste buffer caching is one more dangerous problem in Android devices.
Users generally tend to copy and paste a lot of things due to the space limitations on the mobile screen.
If a user copies any sensitive information such as a credit card number to the clipboard, an attacker can easily read it with a small piece of code This may lead to serious damage since the attacker can access this information remotely sitting anywhere in the world using the app running on the victim’s device.
</p>
<p>
<b>Solution:</b><br/>
<pre>
Set clip borad null after each paste. For sensitive information use encryption.
</pre>
</p>
[...]
]]>
</Details>
</BugPattern>
<BugCode abbrev="CP">Clipboard usage</BugCode>
messages.xml
<Detector class="com.h3xstream.findsecbugs.android.CopyPasteLeakageDetector">
<Details>Identify of unintended data leakage</Details>
</Detector>
<BugPattern type="ANDROID_COPYPASTE">
<ShortDescription>Clipboard usage</ShortDescription>
<LongDescription>It is not safe to use clipboard without sanitization</LongDescription>
<Details>
<![CDATA[
<p>
Copy/paste buffer caching is one more dangerous problem in Android devices.
Users generally tend to copy and paste a lot of things due to the space limitations on the mobile screen.
If a user copies any sensitive information such as a credit card number to the clipboard, an attacker can easily read it with a small piece of code This may lead to serious damage since the attacker can access this information remotely sitting anywhere in the world using the app running on the victim’s device.
</p>
<p>
<b>Solution:</b><br/>
<pre>
Set clip borad null after each paste. For sensitive information use encryption.
</pre>
</p>
[...]
]]>
</Details>
</BugPattern>
<BugCode abbrev="CP">Clipboard usage</BugCode>
5. New detector class
There are many possibilities in order to implement a detector.
OpcodeStackDetector : Look for a specific method call
ConfiguredBasicInjectionDetector : To implement an injection-like detector
Detector : To analyze the complete class context
CopyPasteLeakageDetector
package com.h3xstream.findsecbugs.android;
package com.jobair.copypasteleakagedetector;
import com.sun.org.apache.bcel.internal.Constants;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.Priorities;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
public class CopyPasteLeakageDetector extends OpcodeStackDetector {
private static final String ANDROID_COPYPASTE = "ANDROID_COPYPASTE";
//private static InvokeMatcherBuilder XML_DECODER_CONSTRUCTOR = invokeInstruction().atClass("java/beans/XMLDecoder").atMethod("<init>");
private BugReporter bugReporter;
public CopyPasteLeakageDetector(BugReporter bugReporter) {
this.bugReporter = bugReporter;
}
@Override
public void sawOpcode(int seen) {
if (seen == Constants.INVOKEVIRTUAL && getClassConstantOperand().equals("android/content/ClipboardManager")&&
getNameConstantOperand().equals("setPrimaryClip")) {
bugReporter.reportBug(new BugInstance(this, ANDROID_COPYPASTE, Priorities.HIGH_PRIORITY) //
.addClass(this).addMethod(this).addSourceLine(this));
}
}
}