mirror of
https://github.com/hohn/codeql-lab.git
synced 2025-12-16 09:53:04 +01:00
Rename directories to include language. Also update files
This commit is contained in:
committed by
=Michael Hohn
parent
fe1baf7dc1
commit
102c18cce5
320
codeql-jedis-java/README.org
Normal file
320
codeql-jedis-java/README.org
Normal file
@@ -0,0 +1,320 @@
|
||||
* Jedis Codeql Setup
|
||||
- fork at https://github.com/hohn/jedis
|
||||
- github db build: enable code scanning, advanced config
|
||||
- only java-kotlin, build-mode: none.
|
||||
- creates https://github.com/hohn/jedis/blob/master/.github/workflows/codeql.yml
|
||||
- action run at https://github.com/hohn/jedis/actions/workflows/codeql.yml
|
||||
- db download
|
||||
#+BEGIN_SRC sh
|
||||
# list dbs
|
||||
curl -H "Authorization: token $GITHUB_TOKEN" \
|
||||
https://api.github.com/repos/hohn/jedis/code-scanning/analyses
|
||||
|
||||
|
||||
# Get DB via curl
|
||||
cd ~/work-gh/codeql-lab/assets
|
||||
curl -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/zip" \
|
||||
-L \
|
||||
https://api.github.com/repos/hohn/jedis/code-scanning/codeql/databases/java \
|
||||
-o jedis-database-gh.zip
|
||||
#+END_SRC
|
||||
- db at ~/work-gh/codeql-lab/assets/jedis-database-gh.zip
|
||||
- local db build:
|
||||
#+BEGIN_SRC sh
|
||||
cd ~/work-gh/codeql-lab/
|
||||
|
||||
# Add the submodule
|
||||
git submodule add https://github.com/hohn/jedis extern/jedis
|
||||
|
||||
# Initialize and clone the submodule
|
||||
git submodule update --init --recursive
|
||||
|
||||
|
||||
# Build directly once to resolve any errors
|
||||
cd ~/work-gh/codeql-lab/extern/jedis
|
||||
mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
|
||||
|
||||
# Build under codeql
|
||||
# Step 1: Clean any prior Maven builds
|
||||
cd ~/work-gh/codeql-lab/extern/jedis
|
||||
mvn clean
|
||||
|
||||
# Step 2: Run CodeQL DB creation with mvn install
|
||||
cd ~/work-gh/codeql-lab
|
||||
codeql database create assets/jedis-db-local \
|
||||
--overwrite \
|
||||
--language=java \
|
||||
--command="mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V" \
|
||||
--source-root=extern/jedis
|
||||
#+END_SRC
|
||||
|
||||
* Jedis Codeql Modeling
|
||||
** Setup and Start
|
||||
#+BEGIN_SRC sh
|
||||
# Step 1: Go to your CodeQL lab directory
|
||||
cd ~/work-gh/codeql-lab
|
||||
|
||||
# Step 2: Extract the prebuilt CodeQL database for the Jedis project
|
||||
unzip -q assets/jedis-db-local.zip
|
||||
|
||||
# Step 3: Extract the CodeQL command-line tools (platform-specific)
|
||||
unzip -q assets/codeql-osx64.zip
|
||||
|
||||
# Step 4: Change directory to the unpacked CodeQL CLI tools
|
||||
cd ~/work-gh/codeql-lab/codeql
|
||||
|
||||
# Step 5: Add the CodeQL CLI directory to your shell's PATH
|
||||
# This allows you to run `codeql` from any location
|
||||
export PATH="$(pwd):$PATH"
|
||||
|
||||
# Step 6: Launch Visual Studio Code with the lab workspace
|
||||
code qllab.code-workspace
|
||||
|
||||
# In VS Code, perform the following setup manually:
|
||||
# - Set the current database to: jedis-db-local
|
||||
# (Usually from the CodeQL extension pane – this connects the UI to your analysis DB)
|
||||
# - Set the CodeQL CLI executable to: ~/work-gh/codeql-lab/codeql/codeql
|
||||
# (Tell the extension where to find the CLI you just extracted)
|
||||
# - In the CodeQL extension tab, scroll to the bottom and select:
|
||||
# 'CodeQL: Method modeling' to begin a guided modeling tutorial
|
||||
|
||||
#+END_SRC
|
||||
** Using the Editor
|
||||
Note that just by starting =CodeQL: Method modeling=, the new file
|
||||
: .github/codeql/extensions/jedis-db-local-java/codeql-pack.yml
|
||||
is created.
|
||||
|
||||
** Relevant Queries
|
||||
A quick =grep= shows
|
||||
#+BEGIN_SRC text
|
||||
grep 'java.*modelgen' files |grep -v test/
|
||||
|
||||
ql/java/ql/src/utils/modelgenerator
|
||||
ql/java/ql/src/utils/modelgenerator/CaptureNeutralModels.ql
|
||||
ql/java/ql/src/utils/modelgenerator/CaptureTypeBasedSummaryModels.ql
|
||||
ql/java/ql/src/utils/modelgenerator/CaptureSinkModels.ql
|
||||
ql/java/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql
|
||||
ql/java/ql/src/utils/modelgenerator/internal
|
||||
ql/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll
|
||||
ql/java/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll
|
||||
ql/java/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll
|
||||
ql/java/ql/src/utils/modelgenerator/CaptureSummaryModels.ql
|
||||
ql/java/ql/src/utils/modelgenerator/RegenerateModels.py
|
||||
ql/java/ql/src/utils/modelgenerator/CaptureSourceModels.ql
|
||||
ql/java/ql/src/utils/modelgenerator/debug
|
||||
ql/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql
|
||||
ql/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql
|
||||
ql/java/ql/src/utils/modelgenerator/debug/README.md
|
||||
#+END_SRC
|
||||
|
||||
** Primary Query File
|
||||
The primary query file is
|
||||
: ../ql/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll
|
||||
This acts as the backbone, exposing traits like:
|
||||
|
||||
- SummaryModelGeneratorInput
|
||||
- ModelGeneratorCommonInput
|
||||
- isPrimitiveTypeUsedForBulkData(...)
|
||||
- Likely common predicates such as:
|
||||
+ hasNoSideEffects(...)
|
||||
+ isNeutralReturn(...)
|
||||
+ isBulkGetterLike(...)
|
||||
|
||||
These are imported by:
|
||||
- CaptureSinkModels.ql
|
||||
- CaptureSummaryModels.ql
|
||||
- CaptureContentSummaryModels.ql
|
||||
- CaptureHeuristicSummaryModels.ql
|
||||
|
||||
- Design: Three Modeling Targets
|
||||
| Module | Implements | Purpose |
|
||||
| ---------------------------- | ------------------------------- | ------------------------------------------------ |
|
||||
| `SummaryModelGeneratorInput` | `SummaryModelGeneratorInputSig` | Models pass-through or computed summaries |
|
||||
| `SourceModelGeneratorInput` | `SourceModelGeneratorInputSig` | Models user-controlled or origin taint sources |
|
||||
| `SinkModelGeneratorInput` | `SinkModelGeneratorInputSig` | Models taint sinks (e.g., logging, SQL, network) |
|
||||
|
||||
- Shared Input System
|
||||
ModelGeneratorCommonInput provides:
|
||||
- Name formatting
|
||||
- Type filtering (isRelevantType)
|
||||
- Signature stringification
|
||||
- “Approximate output” helpers like Argument[pos].Element
|
||||
|
||||
This gives a stable data interface to the rest of the system.
|
||||
|
||||
- Filtering logic
|
||||
#+BEGIN_SRC java
|
||||
private predicate relevant(Callable api) {
|
||||
api.isPublic() and
|
||||
api.getDeclaringType().isPublic() and
|
||||
api.fromSource() and
|
||||
not isUninterestingForModels(api) and
|
||||
not isInfrequentlyUsed(api.getCompilationUnit())
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
** Experiment with test clone
|
||||
The needed imports are private, so clone
|
||||
: ql/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql
|
||||
and experiment there.
|
||||
|
||||
#+BEGIN_SRC java
|
||||
import java
|
||||
import utils.modelgenerator.internal.CaptureModels
|
||||
import SourceModels
|
||||
import utils.test.InlineMadTest
|
||||
|
||||
module InlineMadTestConfig implements InlineMadTestConfigSig {
|
||||
string getCapturedModel(Callable c) { result = Heuristic::captureSource(c) }
|
||||
|
||||
string getKind() { result = "source" }
|
||||
}
|
||||
|
||||
import InlineMadTest<InlineMadTestConfig>
|
||||
|
||||
|
||||
#+END_SRC
|
||||
|
||||
* Modeling Jedis as a Dependency in Model Editor
|
||||
** Set up and run Editor
|
||||
To model =jedis= for taint analysis using the /model editor/, select the /"model
|
||||
as dependency"/ option.
|
||||
|
||||
When this mode is active, the following CodeQL query is used:
|
||||
: /Users/hohn/work-gh/codeql-lab/ql/java/ql/src/utils/modeleditor/FrameworkModeEndpoints.ql
|
||||
|
||||
This query defines:
|
||||
#+BEGIN_SRC java
|
||||
from PublicEndpointFromSource endpoint, boolean supported, string type
|
||||
where
|
||||
supported = isSupported(endpoint) and
|
||||
type = supportedType(endpoint)
|
||||
select endpoint, endpoint.getPackageName(), endpoint.getTypeName(), endpoint.getName(),
|
||||
endpoint.getParameterTypes(), supported,
|
||||
endpoint.getCompilationUnit().getParentContainer().getBaseName(), type
|
||||
#+END_SRC
|
||||
|
||||
There is a direct connection between output columns in the model editor:
|
||||
- =supported = true= → shows in the UI as /"Method already modeled"/
|
||||
- =supported = false= → shown as /"Unmodeled"/
|
||||
|
||||
** Files Created or Modified by the Modeling Workflow
|
||||
- Upon launching ==CodeQL: Method modeling==, a new pack manifest is created:
|
||||
[[../.github/codeql/extensions/jedis-db-local-java/codeql-pack.yml]]
|
||||
- After selecting methods and saving, modeling results are written to:
|
||||
[[../.github/codeql/extensions/jedis-db-local-java/models/redis.clients.jedis.model.yml]]
|
||||
|
||||
** Workspace Configuration Required
|
||||
|
||||
WHAT SETTING?
|
||||
|
||||
To ensure that these model extensions are applied during query runs, include
|
||||
this setting in the workspace configuration file [[../qllab.code-workspace]]
|
||||
|
||||
In some environments (e.g., older VS Code versions), you may also need to
|
||||
replicate this setting in [[../.vscode/settings.json]]
|
||||
|
||||
* Verifying the Modeled Sink
|
||||
Once the modeling is in place, a dataflow query like the following can be used
|
||||
to confirm the modeled sinks:
|
||||
|
||||
#+BEGIN_SRC java
|
||||
import java
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
|
||||
from DataFlow::Node n, string type
|
||||
where sinkNode(n, type) and type = "code-injection"
|
||||
select n, type
|
||||
#+END_SRC
|
||||
|
||||
Sample query result (run on the =jedis-db-local= database):
|
||||
- example.ql on jedis-db-local - finished in 2 seconds (14 results)
|
||||
| 1 | script | code-injection |
|
||||
| 2 | getBytes(...) | code-injection |
|
||||
| 3 | script | code-injection |
|
||||
| 4 | script | code-injection |
|
||||
| 5 | script | code-injection |
|
||||
| 6 | script | code-injection |
|
||||
| 7 | "return redis.call('get','foo')" | code-injection |
|
||||
| 8 | "return redis.call('get','foo')" | code-injection |
|
||||
| 9 | encode(...) | code-injection |
|
||||
| 10 | encode(...) | code-injection |
|
||||
| 11 | "return redis.call('get','foo')" | code-injection |
|
||||
| 12 | "return redis.call('get','foo')" | code-injection |
|
||||
| 13 | script | code-injection |
|
||||
| 14 | "return {}" | code-injection |
|
||||
|
||||
* Identify usage of injection-related models in existing queries
|
||||
To verify whether existing CodeQL queries make use of the injection-related
|
||||
models, we can search for files in the =ql/java= and =ql/cpp= directories that
|
||||
contain the string =-injection=. This string often appears in taint-tracking
|
||||
configuration or query metadata.
|
||||
|
||||
** Java Queries
|
||||
|
||||
The following command locates =.ql= and =.qll= files in the Java query suite that reference =-injection=:
|
||||
|
||||
#+BEGIN_SRC sh
|
||||
rg -l -- '-injection' ql/java | grep '\.qll*'
|
||||
#+END_SRC
|
||||
|
||||
Example output:
|
||||
|
||||
#+BEGIN_SRC text
|
||||
ql/java/ql/src/Security/CWE/CWE-643/XPathInjection.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-078/ExecTainted.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-117/LogInjection.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-470/FragmentInjection.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-470/FragmentInjectionInPreferenceActivity.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-730/RegexInjection.ql
|
||||
ql/java/ql/lib/semmle/code/java/security/XsltInjection.qll
|
||||
ql/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql
|
||||
ql/java/ql/lib/semmle/code/java/security/GroovyInjection.qll
|
||||
ql/java/ql/lib/semmle/code/java/security/XPath.qll
|
||||
ql/java/ql/lib/semmle/code/java/security/TaintedEnvironmentVariableQuery.qll
|
||||
ql/java/ql/src/Security/CWE/CWE-074/XsltInjection.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-074/JndiInjection.ql
|
||||
...
|
||||
ql/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll
|
||||
#+END_SRC
|
||||
|
||||
These files include both top-level queries (under =src/Security/...=) and reusable model libraries (under =lib/semmle/...=). Experimental and framework-specific queries are also included.
|
||||
|
||||
** C++ Queries
|
||||
Likewise, to check for C++ queries that reference =-injection=, use:
|
||||
|
||||
#+BEGIN_SRC sh
|
||||
rg -l -- '-injection' ql/cpp | grep '\.qll*'
|
||||
#+END_SRC
|
||||
|
||||
Example output:
|
||||
|
||||
#+BEGIN_SRC text
|
||||
ql/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql
|
||||
ql/cpp/ql/src/experimental/Security/CWE/CWE-078/WordexpTainted.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql
|
||||
#+END_SRC
|
||||
|
||||
These files indicate active use of injection-related taint tracking in the C++ suite as well.
|
||||
|
||||
* TODO for java, the sqltainted query will find the sink, not the source yet.
|
||||
[[../ql/java/ql/src/Security/CWE/CWE-089/SqlTainted.ql]]
|
||||
|
||||
* TODO Modeling sqlite as dependency
|
||||
The tree [[../codeql-sqlite-java/]] contains a trivial sample taken from a workshop. It
|
||||
uses =sqlite-jdbc-3.36.0.1.jar=, so we can use it to illustrate modeling on a
|
||||
smaller example. This one is unusual; the function
|
||||
java.io.Console.readLine() is already modeled, but as a taint step, not a
|
||||
source. We need it as source. The model editor won't show it at all because it
|
||||
is already modeled,
|
||||
|
||||
|
||||
|
||||
* TODO vulnerable sample, sqlite
|
||||
For .eval() to show in a query, it has to be used in an application. So we
|
||||
modify src-sqlite/AddUser.java for jedis.
|
||||
|
||||
4
codeql-jedis-java/codeql-pack.lock.yml
Normal file
4
codeql-jedis-java/codeql-pack.lock.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
lockVersion: 1.0.0
|
||||
dependencies: {}
|
||||
compiled: false
|
||||
13
codeql-jedis-java/example.ql
Normal file
13
codeql-jedis-java/example.ql
Normal file
@@ -0,0 +1,13 @@
|
||||
import java
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
|
||||
from DataFlow::Node n, string type
|
||||
where sinkNode(n, type)
|
||||
and type = "code-injection"
|
||||
select n, type
|
||||
|
||||
// // See if we have calls to eval() in the library
|
||||
// from Call c
|
||||
// where c.getCallee().hasQualifiedName("redis.clients.jedis","Jedis", "eval")
|
||||
// select c
|
||||
6
codeql-jedis-java/qlpack.yml
Normal file
6
codeql-jedis-java/qlpack.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
name: codeql-jedis/codeql-extra-queries-java
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
# This uses the latest version of the codeql/java-all library.
|
||||
# You may want to change to a more precise semver string.
|
||||
codeql/java-all: "*"
|
||||
Reference in New Issue
Block a user