soot.jimple.infoflow.problems.rules.WrapperPropagationRule Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of soot-infoflow Show documentation
Show all versions of soot-infoflow Show documentation
Soot extending data flow tracking components for Java
package soot.jimple.infoflow.problems.rules;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import soot.RefType;
import soot.SootMethod;
import soot.jimple.DefinitionStmt;
import soot.jimple.InstanceInvokeExpr;
import soot.jimple.Stmt;
import soot.jimple.infoflow.InfoflowConfiguration.StaticFieldTrackingMode;
import soot.jimple.infoflow.InfoflowManager;
import soot.jimple.infoflow.aliasing.Aliasing;
import soot.jimple.infoflow.data.Abstraction;
import soot.jimple.infoflow.data.AccessPath;
import soot.jimple.infoflow.problems.TaintPropagationResults;
import soot.jimple.infoflow.sourcesSinks.manager.SourceInfo;
import soot.jimple.infoflow.util.ByReferenceBoolean;
import soot.jimple.infoflow.util.TypeUtils;
/**
* Rule for using external taint wrappers
*
* @author Steven Arzt
*
*/
public class WrapperPropagationRule extends AbstractTaintPropagationRule {
public WrapperPropagationRule(InfoflowManager manager, Abstraction zeroValue, TaintPropagationResults results) {
super(manager, zeroValue, results);
}
@Override
public Collection propagateNormalFlow(Abstraction d1, Abstraction source, Stmt stmt, Stmt destStmt,
ByReferenceBoolean killSource, ByReferenceBoolean killAll) {
return null;
}
/**
* Computes the taints produced by a taint wrapper object
*
* @param d1 The context (abstraction at the method's start node)
* @param iStmt The call statement the taint wrapper shall check for well-
* known methods that introduce black-box taint propagation
* @param source The taint source
* @return The taints computed by the wrapper
*/
private Set computeWrapperTaints(Abstraction d1, final Stmt iStmt, Abstraction source) {
// Do not process zero abstractions
if (source == getZeroValue())
return null;
// If we don't have a taint wrapper, there's nothing we can do here
if (getManager().getTaintWrapper() == null)
return null;
// Do not check taints that are not mentioned anywhere in the call
if (!source.getAccessPath().isStaticFieldRef() && !source.getAccessPath().isEmpty()) {
boolean found = false;
// The base object must be tainted
if (iStmt.getInvokeExpr() instanceof InstanceInvokeExpr) {
InstanceInvokeExpr iiExpr = (InstanceInvokeExpr) iStmt.getInvokeExpr();
found = getAliasing().mayAlias(iiExpr.getBase(), source.getAccessPath().getPlainValue());
}
// or one of the parameters must be tainted
if (!found)
for (int paramIdx = 0; paramIdx < iStmt.getInvokeExpr().getArgCount(); paramIdx++)
if (getAliasing().mayAlias(source.getAccessPath().getPlainValue(),
iStmt.getInvokeExpr().getArg(paramIdx))) {
found = true;
break;
}
// If nothing is tainted, we don't have any taints to propagate
if (!found)
return null;
}
// Do not apply the taint wrapper to statements that are sources on their own
if (!getManager().getConfig().getInspectSources()) {
// Check whether this can be a source at all
final SourceInfo sourceInfo = getManager().getSourceSinkManager() != null
? getManager().getSourceSinkManager().getSourceInfo(iStmt, getManager())
: null;
if (sourceInfo != null)
return null;
}
Set res = getManager().getTaintWrapper().getTaintsForMethod(iStmt, d1, source);
if (res != null) {
Set resWithAliases = new HashSet<>(res);
for (Abstraction abs : res) {
// The new abstraction gets activated where it was generated
if (!abs.equals(source))
checkAndPropagateAlias(d1, iStmt, resWithAliases, abs);
}
res = resWithAliases;
}
return res;
}
/**
* Starts alias tracking for the results of a taint wrapper if necessary
*
* @param d1 The context in which the wrapped method was called
* @param iStmt The call site
* @param resWithAliases The resulting taint abstractions generated by the
* wrapper
* @param abs The original incoming taint abstraction
*/
protected void checkAndPropagateAlias(Abstraction d1, final Stmt iStmt, Set resWithAliases,
Abstraction abs) {
// If the taint wrapper creates a new taint, this must be propagated
// backwards as there might be aliases for the base object
// Note that we don't only need to check for heap writes such as a.x = y,
// but also for base object taints ("a" in this case).
final AccessPath val = abs.getAccessPath();
boolean isBasicString = TypeUtils.isStringType(val.getBaseType()) && !val.getCanHaveImmutableAliases()
&& !getAliasing().isStringConstructorCall(iStmt);
boolean taintsObjectValue = val.getBaseType() instanceof RefType
&& abs.getAccessPath().getBaseType() instanceof RefType && !isBasicString;
boolean taintsStaticField = getManager().getConfig()
.getStaticFieldTrackingMode() != StaticFieldTrackingMode.None && abs.getAccessPath().isStaticFieldRef();
// If the tainted value gets overwritten, it cannot have aliases afterwards
boolean taintedValueOverwritten = (iStmt instanceof DefinitionStmt)
? Aliasing.baseMatches(((DefinitionStmt) iStmt).getLeftOp(), abs)
: false;
if (!taintedValueOverwritten) {
if (taintsStaticField || (taintsObjectValue && abs.getAccessPath().getTaintSubFields())
|| manager.getAliasing().canHaveAliases(iStmt, val.getPlainValue(), abs))
getAliasing().computeAliases(d1, iStmt, val.getPlainValue(), resWithAliases,
getManager().getICFG().getMethodOf(iStmt), abs);
}
}
@Override
public Collection propagateCallToReturnFlow(Abstraction d1, Abstraction source, Stmt stmt,
ByReferenceBoolean killSource, ByReferenceBoolean killAll) {
// Compute the taint wrapper taints
Collection wrapperTaints = computeWrapperTaints(d1, stmt, source);
if (wrapperTaints != null) {
// If the taint wrapper generated an abstraction for
// the incoming access path, we assume it to be handled
// and do not pass on the incoming abstraction on our own
for (Abstraction wrapperAbs : wrapperTaints)
if (wrapperAbs.getAccessPath().equals(source.getAccessPath())) {
if (wrapperAbs != source)
killSource.value = true;
break;
}
}
return wrapperTaints;
}
@Override
public Collection propagateReturnFlow(Collection callerD1s, Abstraction source, Stmt stmt,
Stmt retSite, Stmt callSite, ByReferenceBoolean killAll) {
return null;
}
@Override
public Collection propagateCallFlow(Abstraction d1, Abstraction source, Stmt stmt, SootMethod dest,
ByReferenceBoolean killAll) {
// If we have an exclusive taint wrapper for the target
// method, we do not perform an own taint propagation.
if (getManager().getTaintWrapper() != null && getManager().getTaintWrapper().isExclusive(stmt, source)) {
// taint is propagated in CallToReturnFunction, so we do not need any taint
// here:
killAll.value = true;
}
return null;
}
}