Skip to content

Commit

Permalink
taint pool ignore safe object type and empty objects
Browse files Browse the repository at this point in the history
  • Loading branch information
lostsnow committed Aug 4, 2022
1 parent 4f04ad8 commit b454f5b
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 252 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@
import io.dongtai.iast.core.utils.StackUtils;
import io.dongtai.iast.core.utils.TaintPoolUtils;

import java.lang.reflect.Method;
import java.util.*;
import java.util.ArrayList;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

import static io.dongtai.iast.core.utils.HashCode.isNotEmpty;

/**
* 传播节点处理逻辑暂无问题,后续优先排查其他地方的问题
*
Expand All @@ -25,8 +23,6 @@ public class PropagatorImpl {
private static final String CONDITION_OR = "|";
private static final String CONDITION_AND_RE_PATTERN = "[\\|&]";
private static final int STACK_DEPTH = 11;
private static final String VALUES_ENUMERATOR = " org.apache.tomcat.util.http.ValuesEnumerator".substring(1);
private static final String SPRING_OBJECT = " org.springframework.".substring(1);

public static void solvePropagator(MethodEvent event, AtomicInteger invokeIdSequencer) {
if (!EngineManager.TAINT_POOL.isEmpty()) {
Expand All @@ -49,23 +45,33 @@ private static void addPropagator(MethodEvent event, AtomicInteger invokeIdSeque

private static void auxiliaryPropagator(IastPropagatorModel propagator, AtomicInteger invokeIdSequencer, MethodEvent event) {
String sourceString = propagator.getSource();
boolean conditionSource = containts(sourceString);
boolean conditionSource = contains(sourceString);
if (!conditionSource) {
if (PARAMS_OBJECT.equals(sourceString) && isNotEmpty(event.object) && TaintPoolUtils.poolContains(event.object, event)) {
if (PARAMS_OBJECT.equals(sourceString)) {
if (!TaintPoolUtils.isNotEmpty(event.object)
|| !TaintPoolUtils.isAllowTaintType(event.object)
|| !TaintPoolUtils.poolContains(event.object, event)) {
return;
}

event.inValue = event.object;
setTarget(propagator, event);
addPropagator(event, invokeIdSequencer);
} else if (sourceString.startsWith(PARAMS_PARAM)) {
ArrayList<Object> inValues = new ArrayList<Object>();
int[] positions = (int[]) propagator.getSourcePosition();
for (int pos : positions) {
if (pos < event.argumentArray.length) {
Object tempObj = event.argumentArray[pos];
if (isNotEmpty(tempObj) && TaintPoolUtils.poolContains(tempObj, event)) {
inValues.add(tempObj);
}
if (pos >= event.argumentArray.length) {
continue;
}

Object tempObj = event.argumentArray[pos];
if (!TaintPoolUtils.isNotEmpty(tempObj)
|| !TaintPoolUtils.isAllowTaintType(tempObj)
|| !TaintPoolUtils.poolContains(tempObj, event)) {
continue;
}
inValues.add(tempObj);
}
if (!inValues.isEmpty()) {
event.inValue = inValues.toArray();
Expand All @@ -75,6 +81,7 @@ private static void auxiliaryPropagator(IastPropagatorModel propagator, AtomicIn
}
} else {
// o&r 解决
// @TODO: R has been tainted, so we not need to propagate it
boolean andCondition = sourceString.contains(CONDITION_AND);
String[] conditionSources = sourceString.split(CONDITION_AND_RE_PATTERN);
ArrayList<Object> inValues = new ArrayList<Object>();
Expand Down Expand Up @@ -102,7 +109,9 @@ private static void auxiliaryPropagator(IastPropagatorModel propagator, AtomicIn
if (!inValues.isEmpty()) {
int condition = 0;
for (Object obj : inValues) {
if (isNotEmpty(obj) && TaintPoolUtils.poolContains(obj, event)) {
if (TaintPoolUtils.isNotEmpty(obj)
&& TaintPoolUtils.isAllowTaintType(obj)
&& TaintPoolUtils.poolContains(obj, event)) {
condition++;
}
}
Expand Down Expand Up @@ -136,8 +145,7 @@ private static void setTarget(IastPropagatorModel propagator, MethodEvent event)
}
}
}
if (isNotEmpty(event.outValue)) {
// handlerCustomModel(event);
if (TaintPoolUtils.isNotEmpty(event.outValue)) {
EngineManager.TAINT_POOL.addTaintToPool(event.outValue, event, false);
}
}
Expand All @@ -153,7 +161,7 @@ private static void autoPropagator(AtomicInteger invokeIdSequence, MethodEvent e
// 将当前方法加入污点方法池
}
}
if (isNotEmpty(event.outValue)) {
if (TaintPoolUtils.isNotEmpty(event.outValue)) {
pools.add(event.outValue);
if (event.outValue instanceof String) {
event.addTargetHash(System.identityHashCode(event.outValue));
Expand All @@ -165,107 +173,7 @@ private static void autoPropagator(AtomicInteger invokeIdSequence, MethodEvent e
}
}

private static boolean containts(String obj) {
private static boolean contains(String obj) {
return obj.contains(CONDITION_AND) || obj.contains(CONDITION_OR);
}

/**
* todo: 处理过程和结果需要细化
*
* @param event
*/
public static void handlerCustomModel(MethodEvent event) {
Set<Object> modelValues = parseCustomModel(event.outValue);
for (Object modelValue : modelValues) {
EngineManager.TAINT_POOL.addTaintToPool(modelValue, event, false);
}
}

/**
* fixme: 解析自定义对象中的可疑数据,当前只解析第一层,可能导致部分变异数据无法跟踪到,不考虑性能的情况下,可疑逐级遍历
*
* @param model
* @return
*/
public static Set<Object> parseCustomModel(Object model) {
Set<Object> modelValues = new HashSet<Object>();
Class<?> sourceClass = model.getClass();
if (sourceClass.getClassLoader() == null) {
return modelValues;
}
String className = sourceClass.getName();
if (className.startsWith("cn.huoxian.iast.api.") ||
className.startsWith("io.dongtai.api.") ||
className.startsWith(" org.apache.shiro.web.servlet".substring(1)) ||
VALUES_ENUMERATOR.equals(className) ||
className.startsWith(SPRING_OBJECT)
) {
return modelValues;
}
Method[] methods = sourceClass.getMethods();
Object itemValue = null;
for (Method method : methods) {
String methodName = method.getName();
if (!methodName.startsWith("get")
|| methodName.equals("getClass")
|| methodName.equals("getParserForType")
|| methodName.equals("getDefaultInstance")
|| methodName.equals("getDefaultInstanceForType")
|| methodName.equals("getDescriptor")
|| methodName.equals("getDescriptorForType")
|| methodName.equals("getAllFields")
|| methodName.equals("getInitializationErrorString")
|| methodName.equals("getUnknownFields")
|| methodName.equals("getDetailOrBuilderList")
|| methodName.equals("getAllFieldsMutable")
|| methodName.equals("getAllFieldsRaw")
|| methodName.equals("getOneofFieldDescriptor")
|| methodName.equals("getField")
|| methodName.equals("getFieldRaw")
|| methodName.equals("getRepeatedFieldCount")
|| methodName.equals("getRepeatedField")
|| methodName.equals("getSerializedSize")
|| methodName.equals("getMethodOrDie")
|| methodName.endsWith("Bytes")
|| method.getParameterCount() != 0) {
continue;
}

Class<?> returnType = method.getReturnType();
if (returnType == Integer.class ||
returnType == Boolean.class ||
returnType == Long.class ||
returnType == Character.class ||
returnType == Double.class ||
returnType == Float.class ||
returnType == Enum.class ||
returnType == Byte.class ||
returnType == int.class ||
returnType == boolean.class ||
returnType == long.class ||
returnType == char.class ||
returnType == double.class ||
returnType == float.class ||
returnType == byte.class
) {
continue;
}

try {
itemValue = method.invoke(model);
if (!isNotEmpty(itemValue)) {
continue;
}
modelValues.add(itemValue);
if (itemValue instanceof List) {
List<?> itemValueList = (List<?>) itemValue;
for (Object listValue : itemValueList) {
modelValues.addAll(parseCustomModel(listValue));
}
}
} catch (Exception ignored) {
}
}
return modelValues;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.dongtai.iast.core.EngineManager;
import io.dongtai.iast.core.handler.hookpoint.models.MethodEvent;
import io.dongtai.iast.core.utils.StackUtils;
import io.dongtai.iast.core.utils.TaintPoolUtils;
import io.dongtai.log.DongTaiLog;

import java.lang.reflect.Method;
Expand All @@ -25,30 +26,33 @@ public class SourceImpl {
private static final String SPRING_OBJECT = " org.springframework.".substring(1);

public static void solveSource(MethodEvent event, AtomicInteger invokeIdSequencer) {
if (isNotEmpty(event.returnValue) && isAllowTaintType(event.returnValue) && allowCall(event)) {
event.source = true;
event.setCallStacks(StackUtils.createCallStack(9));

int invokeId = invokeIdSequencer.getAndIncrement();
event.setInvokeId(invokeId);
event.inValue = event.argumentArray;
event.outValue = event.returnValue;

if (isNotEmpty(event.returnValue)) {
handlerCustomModel(event);
EngineManager.TRACK_MAP.addTrackMethod(invokeId, event);
EngineManager.TAINT_POOL.addTaintToPool(event.returnValue, event, true);
}
if (!TaintPoolUtils.isNotEmpty(event.returnValue)
|| !TaintPoolUtils.isAllowTaintType(event.returnValue)
|| !allowCall(event)) {
return;
}

event.source = true;
event.setCallStacks(StackUtils.createCallStack(9));

int invokeId = invokeIdSequencer.getAndIncrement();
event.setInvokeId(invokeId);
event.inValue = event.argumentArray;
event.outValue = event.returnValue;

handlerCustomModel(event);
EngineManager.TRACK_MAP.addTrackMethod(invokeId, event);
EngineManager.TAINT_POOL.addTaintToPool(event.returnValue, event, true);
}


/**
* todo: 处理过程和结果需要细化
*
* @param event
* @param event MethodEvent
*/
public static void handlerCustomModel(MethodEvent event) {
if (!event.getMethodName().equals("getSession")){
if (!event.getMethodName().equals("getSession")) {
Set<Object> modelValues = parseCustomModel(event.returnValue);
for (Object modelValue : modelValues) {
EngineManager.TAINT_POOL.addTaintToPool(modelValue, event, true);
Expand All @@ -59,8 +63,8 @@ public static void handlerCustomModel(MethodEvent event) {
/**
* fixme: 解析自定义对象中的可疑数据,当前只解析第一层,可能导致部分变异数据无法跟踪到,不考虑性能的情况下,可疑逐级遍历
*
* @param model
* @return
* @param model Object
* @return Set<Object>
*/
public static Set<Object> parseCustomModel(Object model) {
Set<Object> modelValues = new HashSet<Object>();
Expand All @@ -80,58 +84,17 @@ public static Set<Object> parseCustomModel(Object model) {
) {
return modelValues;
}
// getter methods
Method[] methods = sourceClass.getMethods();
Object itemValue = null;
for (Method method : methods) {
String methodName = method.getName();
if (!methodName.startsWith("get")
|| methodName.equals("getClass")
|| methodName.equals("getParserForType")
|| methodName.equals("getDefaultInstance")
|| methodName.equals("getDefaultInstanceForType")
|| methodName.equals("getDescriptor")
|| methodName.equals("getDescriptorForType")
|| methodName.equals("getAllFields")
|| methodName.equals("getInitializationErrorString")
|| methodName.equals("getUnknownFields")
|| methodName.equals("getDetailOrBuilderList")
|| methodName.equals("getAllFieldsMutable")
|| methodName.equals("getAllFieldsRaw")
|| methodName.equals("getOneofFieldDescriptor")
|| methodName.equals("getField")
|| methodName.equals("getFieldRaw")
|| methodName.equals("getRepeatedFieldCount")
|| methodName.equals("getRepeatedField")
|| methodName.equals("getSerializedSize")
|| methodName.equals("getMethodOrDie")
|| methodName.endsWith("Bytes")
|| method.getParameterCount() != 0) {
continue;
}

Class<?> returnType = method.getReturnType();
if (returnType == Integer.class ||
returnType == Boolean.class ||
returnType == Long.class ||
returnType == Character.class ||
returnType == Double.class ||
returnType == Float.class ||
returnType == Enum.class ||
returnType == Byte.class ||
returnType == int.class ||
returnType == boolean.class ||
returnType == long.class ||
returnType == char.class ||
returnType == double.class ||
returnType == float.class ||
returnType == byte.class
) {
if (!TaintPoolUtils.isAllowTaintGetterMethod(method)) {
continue;
}

try {
itemValue = method.invoke(model);
if (!isNotEmpty(itemValue)) {
if (!TaintPoolUtils.isNotEmpty(itemValue)) {
continue;
}
modelValues.add(itemValue);
Expand All @@ -148,32 +111,6 @@ public static Set<Object> parseCustomModel(Object model) {
return modelValues;
}

/**
* 检查对象是否为空 - 集合类型,检查大小 - 字符串类型,检查是否为空字符串 - 其他情况,均认为非空
*
* @param obj 待检查的实例化对象
* @return true-对象不为空;false-对象为空
*/
private static boolean isNotEmpty(Object obj) {
if (obj == null) {
return false;
}
if (obj instanceof Map) {
Map<?, ?> taintValue = (Map<?, ?>) obj;
return !taintValue.isEmpty();
} else if (obj instanceof List) {
List<?> taintValue = (List<?>) obj;
return !taintValue.isEmpty();
} else if (obj instanceof Set) {
Set<?> taintValue = (Set<?>) obj;
return !taintValue.isEmpty();
} else if (obj instanceof String) {
String taintValue = (String) obj;
return !taintValue.isEmpty();
}
return true;
}

private static boolean allowCall(MethodEvent event) {
boolean allowed = true;
if (METHOD_OF_GETATTRIBUTE.equals(event.getMethodName())) {
Expand All @@ -192,11 +129,6 @@ private static boolean allowAttribute(String attribute) {
return WHITE_ATTRIBUTES.contains(attribute);
}


public static boolean isAllowTaintType(Object obj) {
return !(obj instanceof Boolean || obj instanceof Integer);
}

static {
WHITE_ATTRIBUTES.add(" org.springframework.web.servlet.HandlerMapping.bestMatchingPattern".substring(1));
WHITE_ATTRIBUTES.add(" org.springframework.web.servlet.HandlerMapping.pathWithinHandlerMapping".substring(1));
Expand Down
Loading

0 comments on commit b454f5b

Please sign in to comment.