Merge branch 'main' into dataflow/provenance-postprocess-qltest

This commit is contained in:
Owen Mansel-Chan
2024-07-26 08:04:05 +01:00
committed by GitHub
368 changed files with 27155 additions and 5548 deletions

View File

@@ -1,3 +1,7 @@
## 1.0.4
No user-facing changes.
## 1.0.3
No user-facing changes.

View File

@@ -0,0 +1,3 @@
## 1.0.4
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.0.3
lastReleaseVersion: 1.0.4

View File

@@ -1,5 +1,5 @@
name: codeql/java-automodel-queries
version: 1.0.4-dev
version: 1.0.5-dev
groups:
- java
- automodel

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>maven-sample</artifactId>
<version>1.0-SNAPSHOT</version>
<name>maven-sample</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>exec-maven-plugin</artifactId>
<groupId>org.codehaus.mojo</groupId>
<version>1.1.1</version>
<executions>
<execution>
<id>check-maven-version</id>
<phase>package</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.example.App</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.19.1</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
<configuration>
<java>
<licenseHeader>
<content>/* FAIL ME */</content>
</licenseHeader>
</java>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-maven</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>[3.1.1,)</version>
</requireMavenVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -0,0 +1,30 @@
package com.example;
import java.util.regex.Pattern;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
String expectedVersion = System.getenv("EXPECT_MAVEN");
Path mavenHome = Paths.get(System.getProperty("maven.home")).normalize();
String observedVersion = mavenHome.getFileName().toString();
if (expectedVersion != null && !expectedVersion.equals(observedVersion)) {
System.err.println("Wrong maven version, expected '" + expectedVersion + "' but got '" + observedVersion + "'" + mavenHome);
System.exit(1);
}
String commandMatcher = System.getenv("EXPECT_COMMAND_REGEX");
String command = System.getProperty("sun.java.command");
if (commandMatcher != null && !Pattern.matches(commandMatcher, command)) {
System.err.println("Wrong command line, '" + command + "' does not match '" + commandMatcher + "'");
System.exit(1);
}
}
}

View File

@@ -0,0 +1,8 @@
<html>
<head>
<title>A sample</title>
</head>
<body>
<p>Hello world!</p>
</body>
</html>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<struts>
This is a sample file
</struts>

View File

@@ -0,0 +1,20 @@
package com.example;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/**
* Unit test for simple App.
*/
public class AppTest
{
/**
* Rigorous Test :-)
*/
@Test
public void shouldAnswerWithTrue()
{
assertTrue( true );
}
}

View File

@@ -0,0 +1,15 @@
#select
| src/main/java/com/example/App.java:0:0:0:0 | App |
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
xmlFiles
| pom.xml:0:0:0:0 | pom.xml |
| src/main/resources/page.xml:0:0:0:0 | src/main/resources/page.xml |
| src/main/resources/struts.xml:0:0:0:0 | src/main/resources/struts.xml |
| target/classes/page.xml:0:0:0:0 | target/classes/page.xml |
| target/classes/struts.xml:0:0:0:0 | target/classes/struts.xml |
propertiesFiles
| src/main/resources/my-app.properties:0:0:0:0 | src/main/resources/my-app.properties |
| target/classes/my-app.properties:0:0:0:0 | target/classes/my-app.properties |
| target/maven-archiver/pom.properties:0:0:0:0 | target/maven-archiver/pom.properties |
| test-db/log/ext/javac-1.properties:0:0:0:0 | test-db/log/ext/javac-1.properties |
| test-db/log/ext/javac.properties:0:0:0:0 | test-db/log/ext/javac.properties |

View File

@@ -0,0 +1,5 @@
import sys
from create_database_utils import *
run_codeql_database_create([], lang="java")

View File

@@ -0,0 +1,9 @@
import java
from File f
where f.isSourceFile()
select f
query predicate xmlFiles(XmlFile x) { any() }
query predicate propertiesFiles(File f) { f.getExtension() = "properties" }

View File

@@ -1,3 +1,24 @@
## 2.0.0
### Breaking Changes
* The Java extractor no longer supports the `SEMMLE_DIST` legacy environment variable.
### Deprecated APIs
* The predicate `isAndroid` from the module `semmle.code.java.security.AndroidCertificatePinningQuery` has been deprecated. Use `semmle.code.java.frameworks.android.Android::inAndroidApplication(File)` instead.
### New Features
* Kotlin support is now out of beta, and generally available
* Kotlin versions up to 2.0.2*x* are now supported.
### Minor Analysis Improvements
* Added a path-injection sink for `hudson.FilePath.exists()`.
* Added summary models for `org.apache.commons.io.IOUtils.toByteArray`.
* Java build-mode `none` analyses now only report a warning on the CodeQL status page when there are significant analysis problems-- defined as 5% of expressions lacking a type, or 5% of call targets being unknown. Other messages reported on the status page are downgraded from warnings to notes and so are less prominent, but are still available for review.
## 1.1.2
### Minor Analysis Improvements

View File

@@ -1,4 +0,0 @@
---
category: deprecated
---
* The predicate `isAndroid` from the module `semmle.code.java.security.AndroidCertificatePinningQuery` has been deprecated. Use `semmle.code.java.frameworks.android.Android::inAndroidApplication(File)` instead.

View File

@@ -0,0 +1,4 @@
---
category: majorAnalysis
---
* We previously considered reverse DNS resolutions (IP address -> domain name) as sources of untrusted data, since compromised/malicious DNS servers could potentially return malicious responses to arbitrary requests. We have now removed this source from the default set of untrusted sources and made a new threat model kind for them, called "reverse-dns". You can optionally include other threat models as appropriate when using the CodeQL CLI and in GitHub code scanning. For more information, see [Analyzing your code with CodeQL queries](https://docs.github.com/code-security/codeql-cli/getting-started-with-the-codeql-cli/analyzing-your-code-with-codeql-queries#including-model-packs-to-add-potential-sources-of-tainted-data>) and [Customizing your advanced setup for code scanning](https://docs.github.com/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#extending-codeql-coverage-with-threat-models).

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* Kotlin versions up to 2.0.2\ *x* are now supported.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Java build-mode `none` analyses now only report a warning on the CodeQL status page when there are significant analysis problems-- defined as 5% of expressions lacking a type, or 5% of call targets being unknown. Other messages reported on the status page are downgraded from warnings to notes and so are less prominent, but are still available for review.

View File

@@ -1,4 +0,0 @@
---
category: breaking
---
* The Java extractor no longer supports the `SEMMLE_DIST` legacy environment variable.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added a path-injection sink for `hudson.FilePath.exists()`.

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* Kotlin support is now out of beta, and generally available

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added summary models for `org.apache.commons.io.IOUtils.toByteArray`.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Adds models for request handlers using the `org.lastaflute.web` web framework.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added flow through some methods of the class `java.net.URL` by ensuring that the fields of a URL are tainted.

View File

@@ -0,0 +1,20 @@
## 2.0.0
### Breaking Changes
* The Java extractor no longer supports the `SEMMLE_DIST` legacy environment variable.
### Deprecated APIs
* The predicate `isAndroid` from the module `semmle.code.java.security.AndroidCertificatePinningQuery` has been deprecated. Use `semmle.code.java.frameworks.android.Android::inAndroidApplication(File)` instead.
### New Features
* Kotlin support is now out of beta, and generally available
* Kotlin versions up to 2.0.2*x* are now supported.
### Minor Analysis Improvements
* Added a path-injection sink for `hudson.FilePath.exists()`.
* Added summary models for `org.apache.commons.io.IOUtils.toByteArray`.
* Java build-mode `none` analyses now only report a warning on the CodeQL status page when there are significant analysis problems-- defined as 5% of expressions lacking a type, or 5% of call targets being unknown. Other messages reported on the status page are downgraded from warnings to notes and so are less prominent, but are still available for review.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.1.2
lastReleaseVersion: 2.0.0

View File

@@ -3,6 +3,7 @@ extensions:
pack: codeql/java-all
extensible: sinkModel
data:
# Note these sinks do not use the sink kind `regex-use[0]` because they should be considered as sinks for regex injection but not polynomial ReDoS.
- ["org.apache.commons.lang3", "RegExUtils", False, "removeAll", "(String,String)", "", "Argument[1]", "regex-use", "manual"]
- ["org.apache.commons.lang3", "RegExUtils", False, "removeFirst", "(String,String)", "", "Argument[1]", "regex-use", "manual"]
- ["org.apache.commons.lang3", "RegExUtils", False, "removePattern", "(String,String)", "", "Argument[1]", "regex-use", "manual"]

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: sourceModel
data:
- ["org.lastaflute.web", "Execute", False, "", "", "Annotated", "Parameter", "remote", "manual"]

View File

@@ -0,0 +1,9 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: summaryModel
data:
- ["org.lastaflute.web.ruts.multipart", "MultipartFormFile", True, "getContentType", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["org.lastaflute.web.ruts.multipart", "MultipartFormFile", True, "getFileData", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["org.lastaflute.web.ruts.multipart", "MultipartFormFile", True, "getFileName", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["org.lastaflute.web.ruts.multipart", "MultipartFormFile", True, "getInputStream", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]

View File

@@ -1,5 +1,5 @@
name: codeql/java-all
version: 1.1.3-dev
version: 2.0.1-dev
groups: java
dbscheme: config/semmlecode.dbscheme
extractor: java

View File

@@ -119,21 +119,6 @@ private predicate variableStep(Expr tracked, VarAccess sink) {
)
}
private class ReverseDnsSource extends RemoteFlowSource {
ReverseDnsSource() {
// Try not to trigger on `localhost`.
exists(MethodCall m | m = this.asExpr() |
m.getMethod() instanceof ReverseDnsMethod and
not exists(MethodCall l |
(variableStep(l, m.getQualifier()) or l = m.getQualifier()) and
(l.getMethod().getName() = "getLocalHost" or l.getMethod().getName() = "getLoopbackAddress")
)
)
}
override string getSourceType() { result = "reverse DNS lookup" }
}
private class MessageBodyReaderParameterSource extends RemoteFlowSource {
MessageBodyReaderParameterSource() {
exists(MessageBodyReaderRead m |
@@ -388,6 +373,24 @@ class AndroidJavascriptInterfaceMethodParameter extends RemoteFlowSource {
}
}
/** A node with input that comes from a reverse DNS lookup. */
abstract class ReverseDnsUserInput extends UserInput {
override string getThreatModel() { result = "reverse-dns" }
}
private class ReverseDnsSource extends ReverseDnsUserInput {
ReverseDnsSource() {
// Try not to trigger on `localhost`.
exists(MethodCall m | m = this.asExpr() |
m.getMethod() instanceof ReverseDnsMethod and
not exists(MethodCall l |
(variableStep(l, m.getQualifier()) or l = m.getQualifier()) and
(l.getMethod().getName() = "getLocalHost" or l.getMethod().getName() = "getLoopbackAddress")
)
)
}
}
/**
* A data flow source node for an API, which should be considered
* supported for a modeling perspective.

View File

@@ -22,6 +22,7 @@ private module Frameworks {
private import semmle.code.java.frameworks.IoJsonWebToken
private import semmle.code.java.frameworks.jackson.JacksonSerializability
private import semmle.code.java.frameworks.InputStream
private import semmle.code.java.frameworks.Networking
private import semmle.code.java.frameworks.Properties
private import semmle.code.java.frameworks.Protobuf
private import semmle.code.java.frameworks.ThreadLocal

View File

@@ -356,8 +356,12 @@ RefType getErasedRepr(Type t) {
t instanceof NullType and result instanceof TypeObject
}
class DataFlowType extends SrcRefType {
final private class SrcRefTypeFinal = SrcRefType;
class DataFlowType extends SrcRefTypeFinal {
DataFlowType() { this = getErasedRepr(_) }
string toString() { result = ppReprType(this) }
}
pragma[nomagic]
@@ -371,7 +375,7 @@ DataFlowType getNodeType(Node n) {
}
/** Gets a string representation of a type returned by `getErasedRepr`. */
string ppReprType(DataFlowType t) {
private string ppReprType(SrcRefType t) {
if t.(BoxedType).getPrimitiveType().getName() = "double"
then result = "Number"
else result = t.toString()

View File

@@ -3,6 +3,8 @@
*/
import semmle.code.java.Type
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.FlowSteps
/** The type `java.net.URLConnection`. */
class TypeUrlConnection extends RefType {
@@ -24,6 +26,11 @@ class TypeUrl extends RefType {
TypeUrl() { this.hasQualifiedName("java.net", "URL") }
}
/** Specifies that if a `URL` is tainted, then so are its synthetic fields. */
private class UrlFieldsInheritTaint extends DataFlow::SyntheticFieldContent, TaintInheritingContent {
UrlFieldsInheritTaint() { this.getField().matches("java.net.URL.%") }
}
/** The type `java.net.URLDecoder`. */
class TypeUrlDecoder extends RefType {
TypeUrlDecoder() { this.hasQualifiedName("java.net", "URLDecoder") }

View File

@@ -13,9 +13,15 @@ private class ExploitableStringLiteral extends StringLiteral {
/**
* Holds if `kind` is an external sink kind that is relevant for regex flow.
* `full` is true if sinks with this kind match against the full string of its input.
* `strArg` is the index of the argument to methods with this sink kind that contan the string to be matched against,
* where -1 is the qualifier; or -2 if no such argument exists.
* `full` is true if sinks with this kind match against the full string of its
* input.
* `strArg` is the index of the argument to methods with this sink kind that
* contain the string to be matched against, where -1 is the qualifier; or -2
* if no such argument exists.
*
* Note that `regex-use` is deliberately not a possible value for `kind` here,
* as it is used for regular expression injection sinks that should not be used
* as polynomial ReDoS sinks.
*/
private predicate regexSinkKindInfo(string kind, boolean full, int strArg) {
sinkModel(_, _, _, _, _, _, _, kind, _, _) and

View File

@@ -7,6 +7,9 @@ import semmle.code.java.security.SensitiveActions
import semmle.code.java.frameworks.android.Compose
private import semmle.code.java.security.Sanitizers
/** A data flow source node for sensitive logging sources. */
abstract class SensitiveLoggerSource extends DataFlow::Node { }
/** A variable that may hold sensitive information, judging by its name. */
class VariableWithSensitiveName extends Variable {
VariableWithSensitiveName() {
@@ -26,6 +29,10 @@ class CredentialExpr extends VarAccess {
}
}
private class CredentialExprSource extends SensitiveLoggerSource {
CredentialExprSource() { this.asExpr() instanceof CredentialExpr }
}
/** An instantiation of a (reflexive, transitive) subtype of `java.lang.reflect.Type`. */
private class TypeType extends RefType {
pragma[nomagic]
@@ -42,7 +49,7 @@ private class TypeType extends RefType {
deprecated class SensitiveLoggerConfiguration extends TaintTracking::Configuration {
SensitiveLoggerConfiguration() { this = "SensitiveLoggerConfiguration" }
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CredentialExpr }
override predicate isSource(DataFlow::Node source) { source instanceof SensitiveLoggerSource }
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "log-injection") }
@@ -59,7 +66,7 @@ deprecated class SensitiveLoggerConfiguration extends TaintTracking::Configurati
/** A data-flow configuration for identifying potentially-sensitive data flowing to a log output. */
module SensitiveLoggerConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CredentialExpr }
predicate isSource(DataFlow::Node source) { source instanceof SensitiveLoggerSource }
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "log-injection") }

View File

@@ -1,3 +1,9 @@
## 1.1.1
### Minor Analysis Improvements
* The heuristic to enable certain Android queries has been improved. Now it ignores Android Manifests which don't define an activity, content provider or service. We also only consider files which are under a folder containing such an Android Manifest for these queries. This should remove some false positive alerts.
## 1.1.0
### Major Analysis Improvements

View File

@@ -8,6 +8,7 @@
* @id java/non-https-url
* @tags security
* external/cwe/cwe-319
* external/cwe/cwe-345
*/
import java

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added the extensible abstract class `SensitiveLoggerSource`. Now this class can be extended to add more sources to the `java/sensitive-log` query or for customizations overrides.

View File

@@ -1,4 +1,5 @@
---
category: minorAnalysis
---
## 1.1.1
### Minor Analysis Improvements
* The heuristic to enable certain Android queries has been improved. Now it ignores Android Manifests which don't define an activity, content provider or service. We also only consider files which are under a folder containing such an Android Manifest for these queries. This should remove some false positive alerts.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.1.0
lastReleaseVersion: 1.1.1

View File

@@ -1,5 +1,5 @@
name: codeql/java-queries
version: 1.1.1-dev
version: 1.1.2-dev
groups:
- java
- queries

View File

@@ -19,18 +19,18 @@ edges
| SpringUrlRedirect.java:104:39:104:56 | redirectUrl : String | SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | provenance | |
| SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders | SpringUrlRedirect.java:108:68:108:78 | httpHeaders | provenance | |
| SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders [<map.value>, <element>] : String | SpringUrlRedirect.java:108:68:108:78 | httpHeaders | provenance | |
| SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders | provenance | MaD:49240 |
| SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders [<map.value>, <element>] : String | provenance | MaD:49481 |
| SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders | provenance | MaD:49245 |
| SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders [<map.value>, <element>] : String | provenance | MaD:49486 |
| SpringUrlRedirect.java:112:39:112:56 | redirectUrl : String | SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | provenance | |
| SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders | SpringUrlRedirect.java:116:37:116:47 | httpHeaders | provenance | |
| SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders [<map.value>, <element>] : String | SpringUrlRedirect.java:116:37:116:47 | httpHeaders | provenance | |
| SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders | provenance | MaD:49240 |
| SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders [<map.value>, <element>] : String | provenance | MaD:49481 |
| SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders | provenance | MaD:49245 |
| SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders [<map.value>, <element>] : String | provenance | MaD:49486 |
| SpringUrlRedirect.java:120:33:120:50 | redirectUrl : String | SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | provenance | |
| SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders | SpringUrlRedirect.java:124:49:124:59 | httpHeaders | provenance | |
| SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders [<map.value>, <element>] : String | SpringUrlRedirect.java:124:49:124:59 | httpHeaders | provenance | |
| SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders | provenance | MaD:49240 |
| SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders [<map.value>, <element>] : String | provenance | MaD:49481 |
| SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders | provenance | MaD:49245 |
| SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders [<map.value>, <element>] : String | provenance | MaD:49486 |
| SpringUrlRedirect.java:128:33:128:50 | redirectUrl : String | SpringUrlRedirect.java:130:44:130:54 | redirectUrl : String | provenance | |
| SpringUrlRedirect.java:130:9:130:19 | httpHeaders : HttpHeaders | SpringUrlRedirect.java:132:49:132:59 | httpHeaders | provenance | |
| SpringUrlRedirect.java:130:33:130:55 | create(...) : URI | SpringUrlRedirect.java:130:9:130:19 | httpHeaders : HttpHeaders | provenance | Config |

View File

@@ -43,7 +43,12 @@ public class A {
};
sink(new URL("test").openConnection().getInputStream()); // $hasRemoteValueFlow
sink(new Socket("test", 1234).getInputStream()); // $hasRemoteValueFlow
sink(InetAddress.getByName("test").getHostName()); // $hasRemoteValueFlow
sink(InetAddress.getByName("test").getHostName()); // $hasReverseDnsValueFlow
sink(InetAddress.getLocalHost().getHostName());
sink(InetAddress.getLoopbackAddress().getHostName());
sink(InetAddress.getByName("test").getCanonicalHostName()); // $hasReverseDnsValueFlow
sink(InetAddress.getLocalHost().getCanonicalHostName());
sink(InetAddress.getLoopbackAddress().getCanonicalHostName());
sink(System.in); // $hasLocalValueFlow
sink(new FileInputStream("test")); // $hasLocalValueFlow

View File

@@ -2,16 +2,12 @@ import java
import semmle.code.java.dataflow.FlowSources
import TestUtilities.InlineExpectationsTest
class LocalSource extends DataFlow::Node instanceof UserInput {
LocalSource() { not this instanceof RemoteFlowSource }
}
predicate isTestSink(DataFlow::Node n) {
exists(MethodCall ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument())
}
module LocalValueConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) { n instanceof LocalSource }
predicate isSource(DataFlow::Node n) { n instanceof LocalUserInput }
predicate isSink(DataFlow::Node n) { isTestSink(n) }
}
@@ -19,7 +15,7 @@ module LocalValueConfig implements DataFlow::ConfigSig {
module LocalValueFlow = DataFlow::Global<LocalValueConfig>;
module LocalTaintConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) { n instanceof LocalSource }
predicate isSource(DataFlow::Node n) { n instanceof LocalUserInput }
predicate isSink(DataFlow::Node n) { isTestSink(n) }
}

View File

@@ -0,0 +1,2 @@
failures
testFailures

View File

@@ -0,0 +1,47 @@
import java
import semmle.code.java.dataflow.FlowSources
import TestUtilities.InlineExpectationsTest
predicate isTestSink(DataFlow::Node n) {
exists(MethodCall ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument())
}
module ReverseDnsValueConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) { n instanceof ReverseDnsUserInput }
predicate isSink(DataFlow::Node n) { isTestSink(n) }
}
module ReverseDnsValueFlow = DataFlow::Global<ReverseDnsValueConfig>;
module ReverseDnsTaintConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) { n instanceof ReverseDnsUserInput }
predicate isSink(DataFlow::Node n) { isTestSink(n) }
}
module ReverseDnsTaintFlow = TaintTracking::Global<ReverseDnsTaintConfig>;
module ReverseDnsFlowTest implements TestSig {
string getARelevantTag() { result = ["hasReverseDnsValueFlow", "hasReverseDnsTaintFlow"] }
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasReverseDnsValueFlow" and
exists(DataFlow::Node sink | ReverseDnsValueFlow::flowTo(sink) |
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
or
tag = "hasReverseDnsTaintFlow" and
exists(DataFlow::Node src, DataFlow::Node sink |
ReverseDnsTaintFlow::flow(src, sink) and not ReverseDnsValueFlow::flow(src, sink)
|
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
}
}
import MakeTest<ReverseDnsFlowTest>

View File

@@ -90,6 +90,14 @@ public class Test {
out = in.toURL();
sink(out); // $ hasTaintFlow
}
{
// manual test for `URI.toURL().getPath()`; checks that if a `URL` is tainted, then so are its synthetic fields
// java.net;URL;False;getPath;();;Argument[this].SyntheticField[java.net.URL.path];ReturnValue;taint;ai-manual
URL out = null;
URI in = (URI) source();
out = in.toURL();
sink(out.getPath()); // $ hasTaintFlow
}
{
// "java.net;URL;false;URL;(String);;Argument[0];Argument[this];taint;manual"
URL out = null;
@@ -97,6 +105,14 @@ public class Test {
out = new URL(in);
sink(out); // $ hasTaintFlow
}
{
// manual test for `URL(String).getPath()`; checks that if a `URL` is tainted, then so are its synthetic fields
// java.net;URL;False;getPath;();;Argument[this].SyntheticField[java.net.URL.path];ReturnValue;taint;ai-manual
URL out = null;
String in = (String) source();
out = new URL(in);
sink(out.getPath()); // $ hasTaintFlow
}
{
// "java.net;URL;false;URL;(URL,String);;Argument[0];Argument[this];taint;ai-generated"
URL out = null;

View File

@@ -0,0 +1,27 @@
import java.io.IOException;
import org.lastaflute.web.Execute;
import org.lastaflute.web.ruts.multipart.MultipartFormFile;
public class Test {
void sink(Object o) {
}
public class TestForm {
public MultipartFormFile file;
}
@Execute
public String index(TestForm form) throws IOException {
MultipartFormFile file = form.file;
sink(file.getFileData()); // $hasTaintFlow
sink(file.getInputStream()); // $hasTaintFlow
return "index.jsp";
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/lastaflute

View File

@@ -0,0 +1,11 @@
import java
import semmle.code.java.dataflow.FlowSources
import TestUtilities.InlineFlowTest
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node n) { DefaultFlowConfig::isSink(n) }
}
import TaintFlowTest<Config>

View File

@@ -5,12 +5,14 @@ import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.servlet.http.HttpServletRequest;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.io.FileUtils;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.DirectoryScanner;
@@ -24,10 +26,10 @@ import org.springframework.util.FileCopyUtils;
public class Test {
private InetAddress address;
private HttpServletRequest request;
public Object source() {
return address.getHostName();
return request.getParameter("source");
}
void test() throws IOException {
@@ -166,8 +168,8 @@ public class Test {
new LargeText((File) source(), null, false, false); // $ hasTaintFlow
}
void doGet6(String root, InetAddress address) throws IOException {
String temp = address.getHostName();
void doGet6(String root, HttpServletRequest request) throws IOException {
String temp = request.getParameter("source");
// GOOD: Use `contains` and `startsWith` to check if the path is safe
if (!temp.contains("..") && temp.startsWith(root + "/")) {
File file = new File(temp);

View File

@@ -90,50 +90,50 @@ edges
| LdapInjection.java:196:32:196:78 | uBadSearchRequestSetFilter : String | LdapInjection.java:199:17:199:42 | uBadSearchRequestSetFilter : String | provenance | |
| LdapInjection.java:199:5:199:5 | s : SearchRequest | LdapInjection.java:200:14:200:14 | s | provenance | Sink:MaD:1933 |
| LdapInjection.java:199:17:199:42 | uBadSearchRequestSetFilter : String | LdapInjection.java:199:5:199:5 | s : SearchRequest | provenance | Config |
| LdapInjection.java:229:30:229:54 | sBad : String | LdapInjection.java:230:36:230:55 | ... + ... | provenance | Sink:MaD:49370 |
| LdapInjection.java:229:57:229:83 | sBadDN : String | LdapInjection.java:230:14:230:33 | ... + ... | provenance | Sink:MaD:49370 |
| LdapInjection.java:234:30:234:54 | sBad : String | LdapInjection.java:235:88:235:107 | ... + ... | provenance | Sink:MaD:49360 |
| LdapInjection.java:229:30:229:54 | sBad : String | LdapInjection.java:230:36:230:55 | ... + ... | provenance | Sink:MaD:49375 |
| LdapInjection.java:229:57:229:83 | sBadDN : String | LdapInjection.java:230:14:230:33 | ... + ... | provenance | Sink:MaD:49375 |
| LdapInjection.java:234:30:234:54 | sBad : String | LdapInjection.java:235:88:235:107 | ... + ... | provenance | Sink:MaD:49365 |
| LdapInjection.java:234:57:234:92 | sBadDNLNBuilder : String | LdapInjection.java:235:48:235:76 | ... + ... : String | provenance | |
| LdapInjection.java:235:20:235:77 | newInstance(...) : LdapNameBuilder | LdapInjection.java:235:20:235:85 | build(...) | provenance | Config Sink:MaD:49360 |
| LdapInjection.java:235:20:235:77 | newInstance(...) : LdapNameBuilder | LdapInjection.java:235:20:235:85 | build(...) | provenance | Config Sink:MaD:49365 |
| LdapInjection.java:235:48:235:76 | ... + ... : String | LdapInjection.java:235:20:235:77 | newInstance(...) : LdapNameBuilder | provenance | Config |
| LdapInjection.java:239:30:239:54 | sBad : String | LdapInjection.java:240:100:240:119 | ... + ... | provenance | Sink:MaD:49372 |
| LdapInjection.java:239:30:239:54 | sBad : String | LdapInjection.java:240:100:240:119 | ... + ... | provenance | Sink:MaD:49377 |
| LdapInjection.java:239:57:239:95 | sBadDNLNBuilderAdd : String | LdapInjection.java:240:57:240:88 | ... + ... : String | provenance | |
| LdapInjection.java:240:23:240:89 | add(...) : LdapNameBuilder | LdapInjection.java:240:23:240:97 | build(...) | provenance | Config Sink:MaD:49357 |
| LdapInjection.java:240:23:240:89 | add(...) : LdapNameBuilder | LdapInjection.java:240:23:240:97 | build(...) | provenance | Config Sink:MaD:49372 |
| LdapInjection.java:240:23:240:89 | add(...) : LdapNameBuilder | LdapInjection.java:240:23:240:97 | build(...) | provenance | Config Sink:MaD:49362 |
| LdapInjection.java:240:23:240:89 | add(...) : LdapNameBuilder | LdapInjection.java:240:23:240:97 | build(...) | provenance | Config Sink:MaD:49377 |
| LdapInjection.java:240:57:240:88 | ... + ... : String | LdapInjection.java:240:23:240:89 | add(...) : LdapNameBuilder | provenance | Config |
| LdapInjection.java:244:30:244:63 | sBadLdapQuery : String | LdapInjection.java:245:47:245:75 | ... + ... : String | provenance | |
| LdapInjection.java:245:47:245:75 | ... + ... : String | LdapInjection.java:245:15:245:76 | filter(...) | provenance | Config Sink:MaD:49369 |
| LdapInjection.java:245:47:245:75 | ... + ... : String | LdapInjection.java:245:15:245:76 | filter(...) | provenance | Config Sink:MaD:49374 |
| LdapInjection.java:249:30:249:60 | sBadFilter : String | LdapInjection.java:250:86:250:111 | ... + ... : String | provenance | |
| LdapInjection.java:249:63:249:98 | sBadDNLdapUtils : String | LdapInjection.java:250:34:250:62 | ... + ... : String | provenance | |
| LdapInjection.java:250:34:250:62 | ... + ... : String | LdapInjection.java:250:12:250:63 | newLdapName(...) | provenance | Config Sink:MaD:49368 |
| LdapInjection.java:250:86:250:111 | ... + ... : String | LdapInjection.java:250:66:250:112 | new HardcodedFilter(...) | provenance | Config Sink:MaD:49368 |
| LdapInjection.java:250:34:250:62 | ... + ... : String | LdapInjection.java:250:12:250:63 | newLdapName(...) | provenance | Config Sink:MaD:49373 |
| LdapInjection.java:250:86:250:111 | ... + ... : String | LdapInjection.java:250:66:250:112 | new HardcodedFilter(...) | provenance | Config Sink:MaD:49373 |
| LdapInjection.java:254:30:254:63 | sBadLdapQuery : String | LdapInjection.java:255:56:255:84 | ... + ... : String | provenance | |
| LdapInjection.java:255:56:255:84 | ... + ... : String | LdapInjection.java:255:24:255:85 | filter(...) | provenance | Config Sink:MaD:49371 |
| LdapInjection.java:255:56:255:84 | ... + ... : String | LdapInjection.java:255:24:255:85 | filter(...) | provenance | Config Sink:MaD:49376 |
| LdapInjection.java:259:30:259:64 | sBadLdapQuery2 : String | LdapInjection.java:260:51:260:80 | ... + ... : String | provenance | |
| LdapInjection.java:260:19:260:81 | filter(...) : LdapQuery | LdapInjection.java:261:24:261:24 | q | provenance | Sink:MaD:49371 |
| LdapInjection.java:260:19:260:81 | filter(...) : LdapQuery | LdapInjection.java:261:24:261:24 | q | provenance | Sink:MaD:49376 |
| LdapInjection.java:260:51:260:80 | ... + ... : String | LdapInjection.java:260:19:260:81 | filter(...) : LdapQuery | provenance | Config |
| LdapInjection.java:265:30:265:73 | sBadLdapQueryWithFilter : String | LdapInjection.java:266:76:266:114 | ... + ... : String | provenance | |
| LdapInjection.java:266:56:266:115 | new HardcodedFilter(...) : HardcodedFilter | LdapInjection.java:266:24:266:116 | filter(...) | provenance | Config Sink:MaD:49371 |
| LdapInjection.java:266:56:266:115 | new HardcodedFilter(...) : HardcodedFilter | LdapInjection.java:266:24:266:116 | filter(...) | provenance | Config Sink:MaD:49376 |
| LdapInjection.java:266:76:266:114 | ... + ... : String | LdapInjection.java:266:56:266:115 | new HardcodedFilter(...) : HardcodedFilter | provenance | Config |
| LdapInjection.java:270:30:270:74 | sBadLdapQueryWithFilter2 : String | LdapInjection.java:271:68:271:107 | ... + ... : String | provenance | |
| LdapInjection.java:271:48:271:108 | new HardcodedFilter(...) : HardcodedFilter | LdapInjection.java:272:56:272:56 | f : HardcodedFilter | provenance | |
| LdapInjection.java:271:68:271:107 | ... + ... : String | LdapInjection.java:271:48:271:108 | new HardcodedFilter(...) : HardcodedFilter | provenance | Config |
| LdapInjection.java:272:56:272:56 | f : HardcodedFilter | LdapInjection.java:272:24:272:57 | filter(...) | provenance | Config Sink:MaD:49371 |
| LdapInjection.java:272:56:272:56 | f : HardcodedFilter | LdapInjection.java:272:24:272:57 | filter(...) | provenance | Config Sink:MaD:49376 |
| LdapInjection.java:276:31:276:68 | sBadLdapQueryBase : String | LdapInjection.java:277:42:277:58 | sBadLdapQueryBase : String | provenance | |
| LdapInjection.java:277:12:277:59 | base(...) : LdapQueryBuilder | LdapInjection.java:277:12:277:66 | base(...) | provenance | Config Sink:MaD:49368 |
| LdapInjection.java:277:12:277:59 | base(...) : LdapQueryBuilder | LdapInjection.java:277:12:277:66 | base(...) | provenance | Config Sink:MaD:49373 |
| LdapInjection.java:277:42:277:58 | sBadLdapQueryBase : String | LdapInjection.java:277:12:277:59 | base(...) : LdapQueryBuilder | provenance | Config |
| LdapInjection.java:281:31:281:71 | sBadLdapQueryComplex : String | LdapInjection.java:282:54:282:73 | sBadLdapQueryComplex : String | provenance | |
| LdapInjection.java:282:24:282:74 | base(...) : LdapQueryBuilder | LdapInjection.java:282:24:282:87 | where(...) : ConditionCriteria | provenance | Config |
| LdapInjection.java:282:24:282:87 | where(...) : ConditionCriteria | LdapInjection.java:282:24:282:98 | is(...) | provenance | Config Sink:MaD:49371 |
| LdapInjection.java:282:24:282:87 | where(...) : ConditionCriteria | LdapInjection.java:282:24:282:98 | is(...) | provenance | Config Sink:MaD:49376 |
| LdapInjection.java:282:54:282:73 | sBadLdapQueryComplex : String | LdapInjection.java:282:24:282:74 | base(...) : LdapQueryBuilder | provenance | Config |
| LdapInjection.java:286:31:286:69 | sBadFilterToString : String | LdapInjection.java:287:38:287:71 | ... + ... : String | provenance | |
| LdapInjection.java:287:18:287:72 | new HardcodedFilter(...) : HardcodedFilter | LdapInjection.java:287:18:287:83 | toString(...) | provenance | Config Sink:MaD:49370 |
| LdapInjection.java:287:18:287:72 | new HardcodedFilter(...) : HardcodedFilter | LdapInjection.java:287:18:287:83 | toString(...) | provenance | Config Sink:MaD:49375 |
| LdapInjection.java:287:38:287:71 | ... + ... : String | LdapInjection.java:287:18:287:72 | new HardcodedFilter(...) : HardcodedFilter | provenance | Config |
| LdapInjection.java:291:31:291:67 | sBadFilterEncode : String | LdapInjection.java:293:25:293:56 | ... + ... : String | provenance | |
| LdapInjection.java:293:5:293:57 | new HardcodedFilter(...) : HardcodedFilter | LdapInjection.java:293:66:293:66 | s : StringBuffer | provenance | Config |
| LdapInjection.java:293:25:293:56 | ... + ... : String | LdapInjection.java:293:5:293:57 | new HardcodedFilter(...) : HardcodedFilter | provenance | Config |
| LdapInjection.java:293:66:293:66 | s : StringBuffer | LdapInjection.java:294:18:294:18 | s : StringBuffer | provenance | |
| LdapInjection.java:294:18:294:18 | s : StringBuffer | LdapInjection.java:294:18:294:29 | toString(...) | provenance | MaD:42727 Sink:MaD:49370 |
| LdapInjection.java:294:18:294:18 | s : StringBuffer | LdapInjection.java:294:18:294:29 | toString(...) | provenance | MaD:42727 Sink:MaD:49375 |
| LdapInjection.java:314:30:314:54 | aBad : String | LdapInjection.java:316:36:316:55 | ... + ... | provenance | Sink:MaD:47462 |
| LdapInjection.java:314:57:314:83 | aBadDN : String | LdapInjection.java:316:14:316:33 | ... + ... | provenance | Sink:MaD:47462 |
| LdapInjection.java:320:30:320:54 | aBad : String | LdapInjection.java:322:65:322:84 | ... + ... | provenance | Sink:MaD:47462 |

View File

@@ -0,0 +1,5 @@
package org.lastaflute.web;
public @interface Execute {
}

View File

@@ -0,0 +1,14 @@
package org.lastaflute.web.ruts.multipart;
import java.io.InputStream;
import java.io.IOException;
public interface MultipartFormFile {
byte[] getFileData() throws IOException;
InputStream getInputStream() throws IOException;
String getFileName();
String getContentType();
}