Skip to content

Commit

Permalink
Added LoadClassNoSignatureCheck.ql
Browse files Browse the repository at this point in the history
  • Loading branch information
masterofnow committed Nov 12, 2023
1 parent 01a074c commit fd66f47
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
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>
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)

0 comments on commit fd66f47

Please sign in to comment.