edu.umd.cs.findbugs.detect.FindVulnerableSecurityCheckMethods Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spotbugs Show documentation
Show all versions of spotbugs Show documentation
SpotBugs: Because it's easy!
/*
* SpotBugs - Find bugs in Java programs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.umd.cs.findbugs.detect;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.SourceLineAnnotation;
import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
import org.apache.bcel.Const;
import org.apache.bcel.classfile.JavaClass;
import java.util.HashSet;
import java.util.Set;
/***
* This detector finds all the vulnerable methods which uses Security Manager to perform
* some security check but are declared non-final and non-private in a non-final class.
* Please see @see SEI CERT MET03-J
* @author Nazir, Muhammad Zafar Iqbal
*/
public class FindVulnerableSecurityCheckMethods extends OpcodeStackDetector {
private final BugReporter bugReporter;
private static final Set badMethodNames;
public FindVulnerableSecurityCheckMethods(BugReporter bugReporter) {
this.bugReporter = bugReporter;
}
static {
badMethodNames = new HashSet() {
{
add("checkAccept");
add("checkAccess");
add("checkAwtEventQueueAccess");
add("checkConnect");
add("checkCreateClassLoader");
add("checkDelete");
add("checkExec");
add("checkExit");
add("checkLink");
add("checkListen");
add("checkMemberAccess");
add("checkMulticast");
add("checkPackageAccess");
add("checkPackageDefinition");
add("checkPermission");
add("checkPrintJobAccess");
add("checkPropertiesAccess");
add("checkRead");
add("checkSecurityAccess");
add("checkSetFactory");
add("checkSystemClipboardAccess");
add("checkTopLevelWindow");
add("checkWrite");
//Deprecated Method Call Support
add("classDepth");
add("classLoaderDepth");
add("currentClassLoader");
add("currentLoadedClass");
add("getInCheck");
add("inClass");
add("inClassLoader");
}
};
}
/**
* Only interested in non-final classes
*/
@Override
public void visitClassContext(ClassContext classContext) {
JavaClass ctx = classContext.getJavaClass();
// Break out of analyzing this class if declared as final
if (ctx.isFinal()) {
return;
}
super.visitClassContext(classContext);
}
/**
* Returns true if the opcode is a method invocation false otherwise
*/
private boolean isMethodCall(int seen) {
return seen == Const.INVOKESTATIC ||
seen == Const.INVOKEVIRTUAL ||
seen == Const.INVOKEINTERFACE ||
seen == Const.INVOKESPECIAL;
}
@Override
public void sawOpcode(int seen) {
//I first check if there is any method invocation.
if (isMethodCall(seen)) {
//If yes then I get the method in which this invocation happened
XMethod method = getXMethod();
if (method == null) {
return;
}
//We examine only non-final and non-private methods
if (!method.isFinal() && !method.isPrivate()) {
//Then we get the method which was invoked
XMethod calledMethod = this.getXMethodOperand();
if (calledMethod == null) {
return;
}
//I used the documentation of SecurityManager class and compiled the "badMethodNames"
// list of method names which can really perform security check.
//If security check is really performed, I report the bug.
if ("java.lang.SecurityManager".equals(calledMethod.getClassName())
&& badMethodNames.contains(calledMethod.getName())) {
bugReporter.reportBug(new BugInstance(this, "VSC_VULNERABLE_SECURITY_CHECK_METHODS", NORMAL_PRIORITY)
.addClass(this.getClassContext().getJavaClass())
.addMethod(method)
.addMethod(calledMethod)
.addSourceLine(SourceLineAnnotation.fromVisitedInstruction(this, getPC())));
}
}
}
}
}