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

@@ -49,4 +49,9 @@ 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.
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.