10: Create ImplicitIntentsPlugin

This commit is contained in:
Bartłomiej Pluta
2019-04-05 17:01:05 +02:00
parent b3a88821f5
commit 6a238a497c
5 changed files with 124 additions and 1 deletions

View File

@@ -2,6 +2,7 @@ package com.bartek.esa.core.di;
import com.bartek.esa.core.desc.provider.DescriptionProvider;
import com.bartek.esa.core.executor.PluginExecutor;
import com.bartek.esa.core.java.JavaSyntaxRegexProvider;
import com.bartek.esa.core.xml.XmlHelper;
import dagger.Module;
import dagger.Provides;
@@ -19,6 +20,11 @@ public class CoreModule {
return new DescriptionProvider();
}
@Provides
public JavaSyntaxRegexProvider javaSyntaxRegexProvider() {
return new JavaSyntaxRegexProvider();
}
@Provides
public XmlHelper xmlHelper() {
return new XmlHelper();

View File

@@ -1,6 +1,7 @@
package com.bartek.esa.core.di;
import com.bartek.esa.core.archetype.Plugin;
import com.bartek.esa.core.java.JavaSyntaxRegexProvider;
import com.bartek.esa.core.plugin.*;
import com.bartek.esa.core.xml.XmlHelper;
import com.bartek.esa.file.matcher.GlobMatcher;
@@ -50,4 +51,10 @@ public class PluginModule {
public Plugin secureRandomPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) {
return new SecureRandomPlugin(globMatcher, xmlHelper);
}
@Provides
@IntoSet
public Plugin implicitIntentsPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper, JavaSyntaxRegexProvider javaSyntaxRegexProvider) {
return new ImplicitIntentsPlugin(globMatcher, xmlHelper, javaSyntaxRegexProvider);
}
}

View File

@@ -0,0 +1,31 @@
package com.bartek.esa.core.java;
import com.github.javaparser.ast.expr.Expression;
import javax.inject.Inject;
import java.util.regex.Pattern;
public class JavaSyntaxRegexProvider {
@Inject
public JavaSyntaxRegexProvider() {
}
public Pattern constant() {
return Pattern.compile("^[A-Z0-9_$]*$");
}
public boolean isConstant(Expression expression) {
String value = expression.toString();
if(expression.isNameExpr() && constant().matcher(value).matches()) {
return true;
}
if(expression.isFieldAccessExpr()) {
return constant().matcher(expression.asFieldAccessExpr().getName().getIdentifier()).matches();
}
return false;
}
}

View File

@@ -0,0 +1,74 @@
package com.bartek.esa.core.plugin;
import com.bartek.esa.core.archetype.JavaPlugin;
import com.bartek.esa.core.java.JavaSyntaxRegexProvider;
import com.bartek.esa.core.model.enumeration.Severity;
import com.bartek.esa.core.xml.XmlHelper;
import com.bartek.esa.file.matcher.GlobMatcher;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.expr.*;
import javax.inject.Inject;
import java.util.List;
import java.util.stream.Collectors;
public class ImplicitIntentsPlugin extends JavaPlugin {
private final JavaSyntaxRegexProvider java;
@Inject
public ImplicitIntentsPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper, JavaSyntaxRegexProvider javaSyntaxRegexProvider) {
super(globMatcher, xmlHelper);
this.java = javaSyntaxRegexProvider;
}
@Override
public void run(CompilationUnit compilationUnit) {
List<String> intentVariables = getIntentVariables(compilationUnit);
findAllSetActionMethodInvocations(compilationUnit, intentVariables);
compilationUnit.findAll(ObjectCreationExpr.class).stream()
.filter(expr -> expr.getType().getName().getIdentifier().equals("Intent"))
.filter(this::checkConstructor)
.forEach(objectCreation -> addIssue(Severity.INFO, getLineNumberFromExpression(objectCreation), objectCreation.toString()));
}
private boolean checkConstructor(ObjectCreationExpr objectCreation) {
NodeList<Expression> arguments = objectCreation.getArguments();
boolean isImplicit = false;
if (arguments.size() == 1) {
Expression argument = arguments.get(0);
isImplicit = java.isConstant(argument);
}
if(arguments.size() == 2) {
Expression argument = arguments.get(0);
isImplicit = !argument.isThisExpr();
}
return isImplicit;
}
private void findAllSetActionMethodInvocations(CompilationUnit compilationUnit, List<String> intentVariables) {
compilationUnit.findAll(MethodCallExpr.class).forEach(methodCall -> {
boolean isCalledOnIntentObject = methodCall.getScope()
.map(Expression::toString)
.filter(intentVariables::contains)
.isPresent();
if(isCalledOnIntentObject && methodCall.getName().getIdentifier().equals("setAction")) {
addIssue(Severity.INFO, getLineNumberFromExpression(methodCall), methodCall.toString());
}
});
}
private List<String> getIntentVariables(CompilationUnit compilationUnit) {
return compilationUnit.findAll(VariableDeclarationExpr.class).stream()
.filter(expr -> expr.getElementType().toString().equals("Intent"))
.map(VariableDeclarationExpr::getVariables)
.flatMap(NodeList::stream)
.map(VariableDeclarator::getName)
.map(SimpleName::getIdentifier)
.collect(Collectors.toList());
}
}

View File

@@ -50,3 +50,8 @@ com.bartek.esa.core.plugin.PermissionsRaceConditionPlugin=Potential permissions
com.bartek.esa.core.plugin.SecureRandomPlugin=Initializing SecureRandom object with custom seed. \n\
Specifying custom seed for SecureRandom can produce predictable sequence of numbers. \n\
Please create SecureRandom object without any arguments instead.
com.bartek.esa.core.plugin.ImplicitIntentsPlugin=Creating implicit intent. Potential data leakage. \n\
Implicit intents can be abused in man-in-the-middle attack. Malicious application can hijack intent and start its\n\
activity/send service etc. to steal sent data. \n\
Also make sure that no sensitive information is passing to this intent.