mirror of
https://github.com/github/codeql.git
synced 2026-05-30 19:11:23 +02:00
add Automodel specific version of the queries using ai-generated sink models
This commit is contained in:
87
java/ql/lib/semmle/code/java/AutomodelSinkTriageUtils.qll
Normal file
87
java/ql/lib/semmle/code/java/AutomodelSinkTriageUtils.qll
Normal file
@@ -0,0 +1,87 @@
|
||||
private import java
|
||||
private import semmle.code.java.dataflow.ExternalFlow as ExternalFlow
|
||||
private import semmle.code.java.dataflow.TaintTracking::TaintTracking
|
||||
|
||||
/** Gets the models-as-data description for the method argument with the index `index`. */
|
||||
bindingset[index]
|
||||
private string getArgumentForIndex(int index) {
|
||||
index = -1 and result = "Argument[this]"
|
||||
or
|
||||
index >= 0 and result = "Argument[" + index + "]"
|
||||
}
|
||||
|
||||
private boolean considerSubtypes(Callable callable) {
|
||||
if
|
||||
callable.isStatic() or
|
||||
callable.getDeclaringType().isStatic() or
|
||||
callable.isFinal() or
|
||||
callable.getDeclaringType().isFinal()
|
||||
then result = false
|
||||
else result = true
|
||||
}
|
||||
|
||||
private class SinkModelExpr extends Expr {
|
||||
predicate hasSignature(
|
||||
string package, string type, boolean subtypes, string name, string signature, string input
|
||||
) {
|
||||
exists(Call call, Callable callable, int argIdx |
|
||||
call.getCallee() = callable and
|
||||
(
|
||||
this = call.getArgument(argIdx)
|
||||
or
|
||||
this = call.getQualifier() and argIdx = -1
|
||||
) and
|
||||
input = getArgumentForIndex(argIdx) and
|
||||
package = callable.getDeclaringType().getPackage().getName() and
|
||||
type = callable.getDeclaringType().getErasure().(RefType).nestedName() and
|
||||
subtypes = considerSubtypes(callable) and
|
||||
name = callable.getName() and
|
||||
signature = ExternalFlow::paramsString(callable)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private string pyBool(boolean b) {
|
||||
b = true and result = "True"
|
||||
or
|
||||
b = false and result = "False"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string representation of the existing sink model at the expression `e`, in the format in
|
||||
* which it would appear in a Models-as-Data file.
|
||||
*/
|
||||
string getSinkModelRepr(SinkModelExpr e) {
|
||||
exists(
|
||||
string package, string type, boolean subtypes, string name, string signature, string input,
|
||||
string ext, string kind, string provenance
|
||||
|
|
||||
e.hasSignature(package, type, subtypes, name, signature, input) and
|
||||
ExternalFlow::sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) and
|
||||
provenance = "ai-generated" and
|
||||
result =
|
||||
"\"" + package + "\", \"" + type + "\", " + pyBool(subtypes) + ", \"" + name + "\", \"" +
|
||||
signature + "\", \"" + ext + "\", \"" + input + "\", \"" + kind + "\", \"" + provenance +
|
||||
"\""
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string representation of a sink model in a format suitable for appending to an alert
|
||||
* message.
|
||||
*/
|
||||
string getSinkModelQueryRepr(SinkModelExpr e) { result = "\nsinkModel: " + getSinkModelRepr(e) }
|
||||
// TODO: make this logic more generic
|
||||
// private predicate relevantSinkModel(int c, string s) {
|
||||
// exists(RequestForgeryFlow::PathNode source, RequestForgeryFlow::PathNode sink |
|
||||
// RequestForgeryFlow::flowPath(source, sink) and
|
||||
// s = getSinkModelRepr(sink.getNode().asExpr())
|
||||
// ) and
|
||||
// c =
|
||||
// count(RequestForgeryFlow::PathNode sink |
|
||||
// exists(RequestForgeryFlow::PathNode source |
|
||||
// RequestForgeryFlow::flowPath(source, sink) and
|
||||
// s = getSinkModelRepr(sink.getNode().asExpr())
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
41
java/ql/src/Security/CWE/CWE-022/TaintedPathAutomodel.ql
Normal file
41
java/ql/src/Security/CWE/CWE-022/TaintedPathAutomodel.ql
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @name Uncontrolled data used in path expression
|
||||
* @description Accessing paths influenced by users can allow an attacker to access unexpected resources.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @id java/path-injection-automodel
|
||||
* @tags security
|
||||
* external/cwe/cwe-022
|
||||
* external/cwe/cwe-023
|
||||
* external/cwe/cwe-036
|
||||
* external/cwe/cwe-073
|
||||
* ai-generated
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.PathCreation
|
||||
import semmle.code.java.security.TaintedPathQuery
|
||||
import TaintedPathFlow::PathGraph
|
||||
private import semmle.code.java.AutomodelSinkTriageUtils
|
||||
|
||||
/**
|
||||
* Gets the data-flow node at which to report a path ending at `sink`.
|
||||
*
|
||||
* Previously this query flagged alerts exclusively at `PathCreation` sites,
|
||||
* so to avoid perturbing existing alerts, where a `PathCreation` exists we
|
||||
* continue to report there; otherwise we report directly at `sink`.
|
||||
*/
|
||||
DataFlow::Node getReportingNode(DataFlow::Node sink) {
|
||||
TaintedPathFlow::flowTo(sink) and
|
||||
if exists(PathCreation pc | pc.getAnInput() = sink.asExpr())
|
||||
then result.asExpr() = any(PathCreation pc | pc.getAnInput() = sink.asExpr())
|
||||
else result = sink
|
||||
}
|
||||
|
||||
from TaintedPathFlow::PathNode source, TaintedPathFlow::PathNode sink
|
||||
where TaintedPathFlow::flowPath(source, sink)
|
||||
select getReportingNode(sink.getNode()), source, sink,
|
||||
"This path depends on a $@." + getSinkModelQueryRepr(sink.getNode().asExpr()), source.getNode(),
|
||||
"user-provided value"
|
||||
27
java/ql/src/Security/CWE/CWE-078/ExecTaintedAutomodel.ql
Normal file
27
java/ql/src/Security/CWE/CWE-078/ExecTaintedAutomodel.ql
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @name Uncontrolled command line
|
||||
* @description Using externally controlled strings in a command line is vulnerable to malicious
|
||||
* changes in the strings.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id java/command-line-injection-automodel
|
||||
* @tags security
|
||||
* external/cwe/cwe-078
|
||||
* external/cwe/cwe-088
|
||||
* ai-generated
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.CommandLineQuery
|
||||
import RemoteUserInputToArgumentToExecFlow::PathGraph
|
||||
private import semmle.code.java.AutomodelSinkTriageUtils
|
||||
|
||||
from
|
||||
RemoteUserInputToArgumentToExecFlow::PathNode source,
|
||||
RemoteUserInputToArgumentToExecFlow::PathNode sink, Expr execArg
|
||||
where execIsTainted(source, sink, execArg)
|
||||
select execArg, source, sink,
|
||||
"This command line depends on a $@." + getSinkModelQueryRepr(sink.getNode().asExpr()),
|
||||
source.getNode(), "user-provided value"
|
||||
35
java/ql/src/Security/CWE/CWE-089/SqlConcatenatedAutomodel.ql
Normal file
35
java/ql/src/Security/CWE/CWE-089/SqlConcatenatedAutomodel.ql
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @name Query built by concatenation with a possibly-untrusted string
|
||||
* @description Building a SQL or Java Persistence query by concatenating a possibly-untrusted string
|
||||
* is vulnerable to insertion of malicious code.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 8.8
|
||||
* @precision medium
|
||||
* @id java/concatenated-sql-query-automodel
|
||||
* @tags security
|
||||
* external/cwe/cwe-089
|
||||
* external/cwe/cwe-564
|
||||
* ai-generated
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.SqlConcatenatedLib
|
||||
import semmle.code.java.security.SqlInjectionQuery
|
||||
import semmle.code.java.security.SqlConcatenatedQuery
|
||||
private import semmle.code.java.AutomodelSinkTriageUtils
|
||||
|
||||
from QueryInjectionSink query, Expr uncontrolled
|
||||
where
|
||||
(
|
||||
builtFromUncontrolledConcat(query.asExpr(), uncontrolled)
|
||||
or
|
||||
exists(StringBuilderVar sbv |
|
||||
uncontrolledStringBuilderQuery(sbv, uncontrolled) and
|
||||
UncontrolledStringBuilderSourceFlow::flow(DataFlow::exprNode(sbv.getToStringCall()), query)
|
||||
)
|
||||
) and
|
||||
not queryIsTaintedBy(query, _, _)
|
||||
select query,
|
||||
"Query built by concatenation with $@, which may be untrusted." +
|
||||
getSinkModelQueryRepr(query.asExpr()), uncontrolled, "this expression"
|
||||
27
java/ql/src/Security/CWE/CWE-089/SqlTaintedAutomodel.ql
Normal file
27
java/ql/src/Security/CWE/CWE-089/SqlTaintedAutomodel.ql
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @name Query built from user-controlled sources
|
||||
* @description Building a SQL or Java Persistence query from user-controlled sources is vulnerable to insertion of
|
||||
* malicious code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 8.8
|
||||
* @precision high
|
||||
* @id java/sql-injection-automodel
|
||||
* @tags security
|
||||
* external/cwe/cwe-089
|
||||
* external/cwe/cwe-564
|
||||
* ai-generated
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.SqlInjectionQuery
|
||||
import QueryInjectionFlow::PathGraph
|
||||
private import semmle.code.java.AutomodelSinkTriageUtils
|
||||
|
||||
from
|
||||
QueryInjectionSink query, QueryInjectionFlow::PathNode source, QueryInjectionFlow::PathNode sink
|
||||
where queryIsTaintedBy(query, source, sink)
|
||||
select query, source, sink,
|
||||
"This query depends on a $@." + getSinkModelQueryRepr(sink.getNode().asExpr()), source.getNode(),
|
||||
"user-provided value"
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @name Android missing certificate pinning
|
||||
* @description Network connections that do not use certificate pinning may allow attackers to eavesdrop on communications.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/android/missing-certificate-pinning-automodel
|
||||
* @tags security
|
||||
* external/cwe/cwe-295
|
||||
* ai-generated
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.AndroidCertificatePinningQuery
|
||||
private import semmle.code.java.AutomodelSinkTriageUtils
|
||||
|
||||
from DataFlow::Node node, string domain, string msg
|
||||
where
|
||||
missingPinning(node, domain) and
|
||||
if domain = ""
|
||||
then msg = "(no explicitly trusted domains)"
|
||||
else msg = "(" + domain + " is not trusted by a pin)"
|
||||
select node,
|
||||
"This network call does not implement certificate pinning. " + msg +
|
||||
getSinkModelQueryRepr(node.asExpr())
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @name Insertion of sensitive information into log files
|
||||
* @description Writing sensitive information to log files can allow that
|
||||
* information to be leaked to an attacker more easily.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id java/sensitive-log-automodel
|
||||
* @tags security
|
||||
* external/cwe/cwe-532
|
||||
* ai-generated
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.SensitiveLoggingQuery
|
||||
import SensitiveLoggerFlow::PathGraph
|
||||
private import semmle.code.java.AutomodelSinkTriageUtils
|
||||
|
||||
from SensitiveLoggerFlow::PathNode source, SensitiveLoggerFlow::PathNode sink
|
||||
where SensitiveLoggerFlow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink,
|
||||
"This $@ is written to a log file." + getSinkModelQueryRepr(sink.getNode().asExpr()),
|
||||
source.getNode(), "potentially sensitive information"
|
||||
24
java/ql/src/Security/CWE/CWE-601/UrlRedirectAutomodel.ql
Normal file
24
java/ql/src/Security/CWE/CWE-601/UrlRedirectAutomodel.ql
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @name URL redirection from remote source
|
||||
* @description URL redirection based on unvalidated user-input
|
||||
* may cause redirection to malicious web sites.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.1
|
||||
* @precision high
|
||||
* @id java/unvalidated-url-redirection-automodel
|
||||
* @tags security
|
||||
* external/cwe/cwe-601
|
||||
* ai-generated
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.UrlRedirectQuery
|
||||
import UrlRedirectFlow::PathGraph
|
||||
private import semmle.code.java.AutomodelSinkTriageUtils
|
||||
|
||||
from UrlRedirectFlow::PathNode source, UrlRedirectFlow::PathNode sink
|
||||
where UrlRedirectFlow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink,
|
||||
"Untrusted URL redirection depends on a $@." + getSinkModelQueryRepr(sink.getNode().asExpr()),
|
||||
source.getNode(), "user-provided value"
|
||||
24
java/ql/src/Security/CWE/CWE-918/RequestForgeryAutomodel.ql
Normal file
24
java/ql/src/Security/CWE/CWE-918/RequestForgeryAutomodel.ql
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @name Server-side request forgery
|
||||
* @description Making web requests based on unvalidated user-input
|
||||
* may cause the server to communicate with malicious servers.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.1
|
||||
* @precision high
|
||||
* @id java/ssrf-automodel
|
||||
* @tags security
|
||||
* external/cwe/cwe-918
|
||||
* ai-generated
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.RequestForgeryConfig
|
||||
import RequestForgeryFlow::PathGraph
|
||||
private import semmle.code.java.AutomodelSinkTriageUtils
|
||||
|
||||
from RequestForgeryFlow::PathNode source, RequestForgeryFlow::PathNode sink
|
||||
where RequestForgeryFlow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink,
|
||||
"Potential server-side request forgery due to a $@." +
|
||||
getSinkModelQueryRepr(sink.getNode().asExpr()), source.getNode(), "user-provided value"
|
||||
2370
java/ql/src/Telemetry/IdentifyReposUsingModels.ql
Normal file
2370
java/ql/src/Telemetry/IdentifyReposUsingModels.ql
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user