-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
01a074c
commit fd66f47
Showing
2 changed files
with
101 additions
and
0 deletions.
There are no files selected for viewing
27 changes: 27 additions & 0 deletions
27
java/ql/src/experimental/Security/CWE/CWE-470/LoadClassNoSignatureCheck.qhelp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd"> | ||
<qhelp> | ||
|
||
<overview> | ||
<p> | ||
If a vulnerable app obtains the ClassLoader of any app based solely on the package name without checking the package signature | ||
allow attacker to create application with the targeted package name for "package namespace squatting". | ||
If the victim install such malicious app in the same device as the vulnerable app, the vulnerable app would load | ||
classes or code from the malicious app, potentially leading to arbitrary code execution. | ||
</p> | ||
</overview> | ||
|
||
<recommendation> | ||
<p> | ||
Verify that the signature of an app in addition to the package name before loading the classes or code. | ||
</p> | ||
</recommendation> | ||
|
||
<references> | ||
<li> | ||
<a href="https://blog.oversecured.com/Android-arbitrary-code-execution-via-third-party-package-contexts/"> | ||
Oversecured (Android: arbitrary code execution via third-party package contexts) | ||
</a> | ||
</li> | ||
</references> | ||
|
||
</qhelp> |
74 changes: 74 additions & 0 deletions
74
java/ql/src/experimental/Security/CWE/CWE-470/LoadClassNoSignatureCheck.ql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/** | ||
* @name Load 3rd party classes or code ('unsafe reflection') without signature check | ||
* @description Load classes or code from 3rd party package without checking the | ||
* package signature but only rely on package name. | ||
* This makes it susceptible to package namespace squatting | ||
* potentially leading to arbitrary code execution. | ||
* @kind path-problem | ||
* @problem.severity error | ||
* @precision high | ||
* @id java/unsafe-reflection | ||
* @tags security | ||
* experimental | ||
* external/cwe/cwe-470 | ||
*/ | ||
|
||
import java | ||
import semmle.code.java.dataflow.DataFlow | ||
import semmle.code.java.dataflow.TaintTracking | ||
|
||
predicate doesPackageContextLeadToInvokeMethod( | ||
DataFlow::Node sinkPackageContext, MethodAccess maInvoke | ||
|
||
) | ||
{ | ||
exists( | ||
MethodAccess maGetClassLoader, | ||
MethodAccess maLoadClass, | ||
MethodAccess maGetMethod | | ||
maGetClassLoader.getCallee().getName() = "getClassLoader" and | ||
maGetClassLoader.getQualifier() = sinkPackageContext.asExpr() and | ||
maLoadClass.getCallee().getName() = "loadClass" and | ||
maLoadClass.getQualifier() = maGetClassLoader and | ||
// check for arbitray code execution | ||
maGetMethod.getCallee().getName() = "getMethod" and | ||
maGetMethod.getQualifier() = maLoadClass and | ||
maInvoke.getCallee().getName() = "invoke" and | ||
maInvoke.getQualifier() = maGetMethod | ||
) | ||
} | ||
|
||
predicate isSignaturesChecked(MethodAccess maCreatePackageContext) | ||
{ | ||
exists( | ||
MethodAccess maCheckSignatures | | ||
maCheckSignatures.getCallee().getDeclaringType().getQualifiedName() = "android.content.pm.PackageManager" and | ||
maCheckSignatures.getCallee().getName() = "checkSignatures" and | ||
//maCheckSignatures.getArgument(0).toString() = maCreatePackageContext.getArgument(0).toString() | ||
TaintTracking::localTaint( | ||
DataFlow::exprNode(maCheckSignatures.getArgument(0)), | ||
DataFlow::exprNode(maCreatePackageContext.getArgument(0))) | ||
) | ||
} | ||
|
||
from | ||
MethodAccess maCreatePackageContext, | ||
LocalVariableDeclExpr lvdePackageContext, | ||
DataFlow::Node sinkPackageContext, | ||
MethodAccess maInvoke | ||
where | ||
maCreatePackageContext.getCallee().getDeclaringType().getQualifiedName() = "android.content.ContextWrapper" and | ||
maCreatePackageContext.getCallee().getName() = "createPackageContext" and | ||
|
||
not isSignaturesChecked(maCreatePackageContext) and | ||
|
||
lvdePackageContext.getEnclosingStmt() = maCreatePackageContext.getEnclosingStmt() and | ||
TaintTracking::localTaint(DataFlow::exprNode(lvdePackageContext.getAnAccess()), sinkPackageContext) and | ||
|
||
doesPackageContextLeadToInvokeMethod(sinkPackageContext, maInvoke) | ||
select | ||
lvdePackageContext, | ||
sinkPackageContext, | ||
maInvoke, | ||
maCreatePackageContext.getArgument(0) | ||
|