10: Update plugins to make use of issue's description model
This commit is contained in:
@@ -10,6 +10,7 @@ import org.w3c.dom.NodeList;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
@@ -34,7 +35,14 @@ public class ExportedComponentsPlugin extends AndroidManifestPlugin {
|
|||||||
stream(exportedActivities)
|
stream(exportedActivities)
|
||||||
.filter(this::isExported)
|
.filter(this::isExported)
|
||||||
.filter(node -> doesNotHavePermission(node, "android:permission"))
|
.filter(node -> doesNotHavePermission(node, "android:permission"))
|
||||||
.forEach(node -> addIssue(Severity.WARNING, format(".%s.NO_PERMISSION", component.toUpperCase()), null, tagString(node)));
|
.forEach(node -> addIssue(Severity.WARNING, ".NO_PERMISSION", getModel(node), null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getModel(Node node) {
|
||||||
|
return Map.of(
|
||||||
|
"componentName", node.getAttributes().getNamedItem("android:name").getNodeValue(),
|
||||||
|
"componentType", node.getNodeName()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findExportedProviders(Document xml) {
|
private void findExportedProviders(Document xml) {
|
||||||
@@ -43,7 +51,7 @@ public class ExportedComponentsPlugin extends AndroidManifestPlugin {
|
|||||||
.filter(this::isExported)
|
.filter(this::isExported)
|
||||||
.filter(node -> doesNotHavePermission(node, "android:writePermission")
|
.filter(node -> doesNotHavePermission(node, "android:writePermission")
|
||||||
|| doesNotHavePermission(node, "android:readPermission"))
|
|| doesNotHavePermission(node, "android:readPermission"))
|
||||||
.forEach(node -> addIssue(Severity.WARNING, ".PROVIDER.NO_PERMISSION", null, tagString(node)));
|
.forEach(node -> addIssue(Severity.WARNING, ".NO_PERMISSION", getModel(node), null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doesNotHavePermission(Node node, String permissionAttribute) {
|
private boolean doesNotHavePermission(Node node, String permissionAttribute) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.w3c.dom.Node;
|
|||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class IntentFilterPlugin extends AndroidManifestPlugin {
|
public class IntentFilterPlugin extends AndroidManifestPlugin {
|
||||||
|
|
||||||
@@ -23,7 +24,14 @@ public class IntentFilterPlugin extends AndroidManifestPlugin {
|
|||||||
stream(filters)
|
stream(filters)
|
||||||
.filter(this::isNotMainActivity)
|
.filter(this::isNotMainActivity)
|
||||||
.map(Node::getParentNode)
|
.map(Node::getParentNode)
|
||||||
.forEach(n -> addIssue(Severity.INFO, null, tagString(n)));
|
.forEach(n -> addIssue(Severity.INFO, getModel(n), null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getModel(Node node) {
|
||||||
|
return Map.of(
|
||||||
|
"componentType", node.getNodeName(),
|
||||||
|
"componentName", node.getAttributes().getNamedItem("android:name").getNodeValue()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isNotMainActivity(Node filter) {
|
private boolean isNotMainActivity(Node filter) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import org.w3c.dom.NodeList;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static java.lang.Integer.parseInt;
|
import static java.lang.Integer.parseInt;
|
||||||
|
|
||||||
@@ -28,8 +29,12 @@ public class PermissionsRaceConditionPlugin extends AndroidManifestPlugin {
|
|||||||
Node minSdkVersionNode = usesSdkNode.getAttributes().getNamedItem("android:minSdkVersion");
|
Node minSdkVersionNode = usesSdkNode.getAttributes().getNamedItem("android:minSdkVersion");
|
||||||
int minSdkVersion = parseInt(minSdkVersionNode.getNodeValue());
|
int minSdkVersion = parseInt(minSdkVersionNode.getNodeValue());
|
||||||
if(minSdkVersion < 21) {
|
if(minSdkVersion < 21) {
|
||||||
addIssue(Severity.VULNERABILITY, null, minSdkVersionNode.toString());
|
addIssue(Severity.VULNERABILITY, getModel(minSdkVersion), null, minSdkVersionNode.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getModel(int minSdkVersion) {
|
||||||
|
return Map.of("minSdkVersion", Integer.toString(minSdkVersion));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.w3c.dom.Node;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class UsesSdkPlugin extends AndroidManifestPlugin {
|
public class UsesSdkPlugin extends AndroidManifestPlugin {
|
||||||
@@ -26,7 +27,7 @@ public class UsesSdkPlugin extends AndroidManifestPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Optional.ofNullable(usesSdkNode.getAttributes().getNamedItem("android:maxSdkVersion")).ifPresent(maxSdkVersion ->
|
Optional.ofNullable(usesSdkNode.getAttributes().getNamedItem("android:maxSdkVersion")).ifPresent(maxSdkVersion ->
|
||||||
addIssue(Severity.ERROR, ".USES_SDK.MAX_SDK_VERSION", null, maxSdkVersion.toString())
|
addIssue(Severity.ERROR, ".USES_SDK.MAX_SDK_VERSION", Map.of("maxSdkVersion", maxSdkVersion.getNodeValue()),null, maxSdkVersion.toString())
|
||||||
);
|
);
|
||||||
}, () -> addIssue(Severity.ERROR, ".NO_USES_SDK", null, null));
|
}, () -> addIssue(Severity.ERROR, ".NO_USES_SDK", null, null));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ This will allow accessing the backups via adb if device has USB debugging enable
|
|||||||
Consider setting it to 'false'.
|
Consider setting it to 'false'.
|
||||||
|
|
||||||
com.bartek.esa.core.plugin.PermissionsRaceConditionPlugin=Potential permissions race condition vulnerability. \n\
|
com.bartek.esa.core.plugin.PermissionsRaceConditionPlugin=Potential permissions race condition vulnerability. \n\
|
||||||
There are declared custom permissions in AndroidManifest.xml and the minimal API version is set to less than 21.\n\
|
There are declared custom permissions in AndroidManifest.xml and the minimal API version is set to ${minSdkVersion} that is less than 21.\n\
|
||||||
It means that declared permissions can be obtained by malicious application installed before and without need of having 1proper signature.\n\
|
It means that declared permissions can be obtained by malicious application installed before and without need of having 1proper signature.\n\
|
||||||
Consider setting minimal API version to 21 at least.
|
Consider setting minimal API version to 21 at least.
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ com.bartek.esa.core.plugin.UsesSdkPlugin.USES_SDK.NO_MIN_SDK_VERSION=There is no
|
|||||||
For example: <uses-sdk android:minSdkVersion="23">
|
For example: <uses-sdk android:minSdkVersion="23">
|
||||||
|
|
||||||
com.bartek.esa.core.plugin.UsesSdkPlugin.USES_SDK.MAX_SDK_VERSION=Application defines an upper limit for API version.\n\
|
com.bartek.esa.core.plugin.UsesSdkPlugin.USES_SDK.MAX_SDK_VERSION=Application defines an upper limit for API version.\n\
|
||||||
The android:maxSdkVersion is defined in AndroidManifest.xml.\n\
|
The android:maxSdkVersion is set to ${maxSdkVersion} in AndroidManifest.xml.\n\
|
||||||
There is no need to limit available platforms for application.\n\
|
There is no need to limit available platforms for application.\n\
|
||||||
Furthermore it can cause unexpected application uninstall\n\
|
Furthermore it can cause unexpected application uninstall\n\
|
||||||
on upgrading Android version (along with API which can exceed defined maximal API version).
|
on upgrading Android version (along with API which can exceed defined maximal API version).
|
||||||
@@ -88,26 +88,11 @@ com.bartek.esa.core.plugin.SuppressWarningsPlugin=@SuppressWarnings annotation w
|
|||||||
The @SuppressWarnings annotation might be hiding useful warnings.\n\
|
The @SuppressWarnings annotation might be hiding useful warnings.\n\
|
||||||
Consider removing it.
|
Consider removing it.
|
||||||
|
|
||||||
com.bartek.esa.core.plugin.ExportedComponentsPlugin.ACTIVITY.NO_PERMISSION=Exported activity.\n\
|
com.bartek.esa.core.plugin.ExportedComponentsPlugin.NO_PERMISSION=Exported activity.\n\
|
||||||
The activity is exported but not protected by any permission. \n\
|
The ${componentType} with name '${componentName}' is exported but not protected by any permission. \n\
|
||||||
It means any malicious application could make use of the component. \n\
|
It means any malicious application could make use of the component. \n\
|
||||||
Consider using 'android:permission' tag and adding custom permission to protect it.
|
Consider using 'android:permission' tag and adding custom permission to protect it.
|
||||||
|
|
||||||
com.bartek.esa.core.plugin.ExportedComponentsPlugin.SERVICE.NO_PERMISSION=Exported service.\n\
|
|
||||||
The service is exported but not protected by any permission. \n\
|
|
||||||
It means any malicious application could make use of the component. \n\
|
|
||||||
Consider using 'android:permission' tag and adding custom permission to protect it.
|
|
||||||
|
|
||||||
com.bartek.esa.core.plugin.ExportedComponentsPlugin.RECEIVER.NO_PERMISSION=Exported broadcast receiver.\n\
|
|
||||||
The broadcast receiver is exported but not protected by any permission. \n\
|
|
||||||
It means any malicious application could make use of the component. \n\
|
|
||||||
Consider using 'android:permission' tag and adding custom permission to protect it.
|
|
||||||
|
|
||||||
com.bartek.esa.core.plugin.ExportedComponentsPlugin.PROVIDER.NO_PERMISSION=Exported content provider. Potential data leakage.\n\
|
|
||||||
The content provider is exported but not protected by any permissions. \n\
|
|
||||||
It means any malicious application could make use of data provided by the component and/or insert some new data. \n\
|
|
||||||
Consider using 'android:readPermission' and 'android:writePermission' tags and adding custom permission to protect it.
|
|
||||||
|
|
||||||
com.bartek.esa.core.plugin.DangerousPermissionPlugin=Custom permission without description.\n\
|
com.bartek.esa.core.plugin.DangerousPermissionPlugin=Custom permission without description.\n\
|
||||||
Custom permission with 'dangerous' protection level was found and it doesn't have any description.\n\
|
Custom permission with 'dangerous' protection level was found and it doesn't have any description.\n\
|
||||||
As long as the permission requires user attention, he should have provided a meaningful description about\n\
|
As long as the permission requires user attention, he should have provided a meaningful description about\n\
|
||||||
@@ -119,7 +104,8 @@ com.bartek.esa.core.plugin.TextInputValidationPlugin=Input type is no selected.\
|
|||||||
For example: <EditText android:inputType="number" ...
|
For example: <EditText android:inputType="number" ...
|
||||||
|
|
||||||
com.bartek.esa.core.plugin.IntentFilterPlugin=Implemented intent filter.\n\
|
com.bartek.esa.core.plugin.IntentFilterPlugin=Implemented intent filter.\n\
|
||||||
Component with intent filter was found. It means, that the component is implicitly exposed to public.\n\
|
The ${componentType} with name '${componentName}' does have a intent filter declared. \n\
|
||||||
|
It means, that the component is implicitly exposed to public.\n\
|
||||||
Consider removing intent filter.\n\
|
Consider removing intent filter.\n\
|
||||||
Also be aware, that intent filter is not a security tool. It can be easily omitted.
|
Also be aware, that intent filter is not a security tool. It can be easily omitted.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user