All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.h3xstream.findsecbugs.password.HashUnsafeEqualsDetector Maven / Gradle / Ivy

Go to download

Core module of the project. It include all the FindBugs detectors. The resulting jar is the published plugin.

There is a newer version: 1.13.0
Show newest version
/**
 * Find Security Bugs
 * Copyright (c) Philippe Arteau, All rights reserved.
 *
 * 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 3.0 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.
 */
package com.h3xstream.findsecbugs.password;

import com.h3xstream.findsecbugs.common.StackUtils;
import com.h3xstream.findsecbugs.common.matcher.InvokeMatcherBuilder;
import com.h3xstream.findsecbugs.injection.BasicInjectionDetector;
import com.h3xstream.findsecbugs.injection.InjectionPoint;
import com.h3xstream.findsecbugs.taintanalysis.Taint;
import com.h3xstream.findsecbugs.taintanalysis.TaintFrame;
import com.h3xstream.findsecbugs.taintanalysis.TaintFrameAdditionalVisitor;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.Priorities;
import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
import org.apache.bcel.generic.*;

import java.util.ArrayList;
import java.util.List;

import static com.h3xstream.findsecbugs.common.matcher.InstructionDSL.invokeInstruction;

/**
 * 

* Detect: *

* *
 * if(hashInput.equals(actualHash)) {
 *     ....
 * }
 * 
*/ public class HashUnsafeEqualsDetector extends BasicInjectionDetector implements TaintFrameAdditionalVisitor { private static final String UNSAFE_HASH_EQUALS_TYPE = "UNSAFE_HASH_EQUALS"; private static final InvokeMatcherBuilder STRING_EQUALS_METHOD = invokeInstruction() // .atClass("java/lang/String").atMethod("equals").withArgs("(Ljava/lang/Object;)Z"); private static final InvokeMatcherBuilder ARRAYS_EQUALS_METHOD = invokeInstruction() // .atClass("java/util/Arrays").atMethod("equals").withArgs("([B[B)Z"); private static final boolean DEBUG = false; public static List HASH_WORDS = new ArrayList(); static { HASH_WORDS.add("hash"); HASH_WORDS.add("md5"); HASH_WORDS.add("sha"); HASH_WORDS.add("digest"); } public HashUnsafeEqualsDetector(BugReporter bugReporter) { super(bugReporter); registerVisitor(this); } @Override protected int getPriorityFromTaintFrame(TaintFrame fact, int offset) throws DataflowAnalysisException { Taint rightValue = fact.getStackValue(offset); Taint leftValue = fact.getStackValue(offset == 0 ? 1 : 0); boolean passwordVariableLeft = leftValue.isUnknown() && leftValue.hasTag(Taint.Tag.HASH_VARIABLE); boolean passwordVariableRight = rightValue.isUnknown() && rightValue.hasTag(Taint.Tag.HASH_VARIABLE); //Is a constant value that was tag because the value was place in a variable name "password" at some point. if (passwordVariableLeft || passwordVariableRight) { return Priorities.NORMAL_PRIORITY; } else { return Priorities.IGNORE_PRIORITY; } } @Override protected InjectionPoint getInjectionPoint(InvokeInstruction invoke, ConstantPoolGen cpg, InstructionHandle handle) { if(STRING_EQUALS_METHOD.matches(invoke,cpg) || ARRAYS_EQUALS_METHOD.matches(invoke,cpg)) { return new InjectionPoint(new int[]{0,1}, UNSAFE_HASH_EQUALS_TYPE); } return InjectionPoint.NONE; } @Override public void visitInvoke(InvokeInstruction invoke, MethodGen methodGen, TaintFrame frameType, List parameters, ConstantPoolGen cpg) { } @Override public void visitReturn(MethodGen methodGen, Taint returnValue, ConstantPoolGen cpg) throws Exception { } @Override public void visitLoad(LoadInstruction instruction, MethodGen methodGen, TaintFrame frameType, int numProduced, ConstantPoolGen cpg) { //Extract the name of the variable int index = instruction.getIndex(); LocalVariableGen var = StackUtils.getLocalVariable(methodGen, index); if(var == null) { if(DEBUG) System.out.println("Unable to get field name for index "+ index + " in "+methodGen); return; } String fieldName = var.getName(); boolean isHashVariable = false; String fieldNameLower = fieldName.toLowerCase(); for (String password : HASH_WORDS) { if (fieldNameLower.contains(password)) { isHashVariable = true; } } if(!isHashVariable) {return;} //Mark local variable Taint passwordValue = frameType.getValue(index); passwordValue.addTag(Taint.Tag.HASH_VARIABLE); if(numProduced <= 0) {return;} //Mark the stack value try { for(int indexStack=0;indexStack




© 2015 - 2025 Weber Informatics LLC | Privacy Policy