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

com.h3xstream.findsecbugs.taintanalysis.TaintConfig Maven / Gradle / Ivy

/**
 * 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.taintanalysis;

import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
import edu.umd.cs.findbugs.ba.SignatureParser;
import edu.umd.cs.findbugs.classfile.MethodDescriptor;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.JavaClass;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;

/**
 * Map of taint summaries for all known methods and classes
 *
 * This class extends HashMap:
 * 
    *
  • The key is the method signature (ie : org/hibernate/Session.createQuery(Ljava/lang/String;)Lorg/hibernate/Query;)
  • *
  • The value is the behavior of the method * ("0" for param index 0 is tainted, * "UNKNOWN" if the method does not become tainted base on the value, * "TAINTED" if the result must be consider unsafe)
  • *
* * @author David Formanek (Y Soft Corporation, a.s.) */ public class TaintConfig extends HashMap { private static final long serialVersionUID = 1L; private final Map taintClassConfigMap = new HashMap(); private final Map taintMethodConfigWithArgumentsAndLocationMap = new HashMap(); /** * Dumps all the summaries for debugging * * @param output stream where to output the summaries */ public void dump(PrintStream output) { TreeSet keys = new TreeSet(keySet()); for (String key : keys) { output.println(key + ":" + get(key)); } } /** * Loads summaries from stream checking the format * * @param input input stream of configured summaries * @param checkRewrite whether to check duplicit summaries * @throws IOException if cannot read the stream or the format is bad * @throws IllegalArgumentException for bad method format * @throws IllegalStateException if there are duplicit configurations */ public void load(InputStream input, final boolean checkRewrite) throws IOException { new TaintConfigLoader().load(input, new TaintConfigLoader.TaintConfigReceiver() { @Override public void receiveTaintConfig(String typeSignature, String config) throws IOException { if (TaintMethodConfig.accepts(typeSignature, config)) { if (checkRewrite && containsKey(typeSignature)) { throw new IllegalStateException("Config for " + typeSignature + " already loaded"); } TaintMethodConfig taintMethodConfig = new TaintMethodConfig(true).load(config); taintMethodConfig.setTypeSignature(typeSignature); put(typeSignature, taintMethodConfig); return; } if (TaintClassConfig.accepts(typeSignature, config)) { if (checkRewrite && taintClassConfigMap.containsKey(typeSignature)) { throw new IllegalStateException("Config for " + typeSignature + " already loaded"); } TaintClassConfig taintClassConfig = new TaintClassConfig().load(config); taintClassConfigMap.put(typeSignature, taintClassConfig); return; } if (TaintMethodConfigWithArgumentsAndLocation.accepts(typeSignature, config)) { if (checkRewrite && taintMethodConfigWithArgumentsAndLocationMap.containsKey(typeSignature)) { throw new IllegalStateException("Config for " + typeSignature + " already loaded"); } TaintMethodConfigWithArgumentsAndLocation methodConfig = new TaintMethodConfigWithArgumentsAndLocation().load(config); methodConfig.setTypeSignature(typeSignature); String key = typeSignature + '@' + methodConfig.getLocation(); taintMethodConfigWithArgumentsAndLocationMap.put(key, methodConfig); return; } throw new IllegalArgumentException("Invalid full method name " + typeSignature + " configured"); } }); } public boolean isClassImmutable(String typeSignature) { if (!isClassType(typeSignature)) { return false; } TaintClassConfig classConfig = taintClassConfigMap.get(typeSignature); if (classConfig == null) { return false; } return classConfig.isImmutable(); } public boolean isClassTaintSafe(String typeSignature) { if (!isClassType(typeSignature)) { return false; } TaintClassConfig taintClassConfig = getTaintClassConfig(typeSignature); if (taintClassConfig == null) { return false; } return taintClassConfig.getTaintState().equals(Taint.State.SAFE); } public Taint.State getClassTaintState(String typeSignature, Taint.State defaultState) { if (!isClassType(typeSignature)) { return defaultState; } TaintClassConfig taintClassConfig = getTaintClassConfig(typeSignature); if (taintClassConfig == null) { return defaultState; } Taint.State taintClassConfigState = taintClassConfig.getTaintState(); if (taintClassConfigState.equals(TaintClassConfig.DEFAULT_TAINT_STATE)) { return defaultState; } return taintClassConfigState; } public TaintClassConfig getTaintClassConfig(String typeSignature) { if (!isClassType(typeSignature)) { return null; } return taintClassConfigMap.get(typeSignature); } private boolean isClassType(String typeSignature) { return typeSignature != null && typeSignature.length() > 2 && typeSignature.charAt(0) == 'L'; } public TaintMethodConfig getMethodConfig(TaintFrame frame, MethodDescriptor methodDescriptor, String className, String methodId) { TaintMethodConfig taintMethodConfig = getTaintMethodConfigWithArgumentsAndLocation(frame, methodDescriptor, className, methodId); if (taintMethodConfig == null) { taintMethodConfig = get(className.concat(methodId)); } if (taintMethodConfig == null) { taintMethodConfig = getSuperMethodConfig(className, methodId); } return taintMethodConfig; } public TaintMethodConfig getSuperMethodConfig(String className, String methodId) { try { if (className.endsWith("]")) { // not a real class return null; } JavaClass javaClass = Repository.lookupClass(className); assert javaClass != null; TaintMethodConfig methodConfig = getSuperMethodConfig(javaClass.getSuperClasses(), methodId); if (methodConfig != null) { return methodConfig; } return getSuperMethodConfig(javaClass.getAllInterfaces(), methodId); } catch (ClassNotFoundException ex) { AnalysisContext.reportMissingClass(ex); return null; } } private TaintMethodConfig getSuperMethodConfig(JavaClass[] javaClasses, String method) { assert javaClasses != null; for (JavaClass classOrInterface : javaClasses) { String fullMethodName = classOrInterface.getClassName().replace('.', '/').concat(method); TaintMethodConfig conf = get(fullMethodName); if (conf != null) { return conf; } } return null; } private TaintMethodConfig getTaintMethodConfigWithArgumentsAndLocation(TaintFrame frame, MethodDescriptor methodDescriptor, String className, String methodId) { if (taintMethodConfigWithArgumentsAndLocationMap.isEmpty()) { return null; } String signature = methodId.substring(methodId.indexOf("("), methodId.length()); int parameters = new SignatureParser(signature).getNumParameters(); StringBuffer sb = null; if (parameters > 0 && frame.getStackDepth() >= parameters) { sb = new StringBuffer(parameters); for (int i = parameters - 1; i >= 0; i--) { try { Taint taint = frame.getStackValue(i); String value = taint.getConstantValue(); if (value != null) { sb.append('"' + value + '"'); } else { sb.append(taint.getState().name()); } if (i > 0) { sb.append(','); } } catch (DataflowAnalysisException e) { assert false : e.getMessage(); } } } String arguments = sb != null ? sb.toString() : ""; String methodName = methodId.substring(1, methodId.indexOf('(')); String methodDefinition = className + "." + methodName + "(" + arguments + ")"; String key = methodDefinition + "@" + methodDescriptor.getSlashedClassName(); return taintMethodConfigWithArgumentsAndLocationMap.get(key); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy