Skip to content

Commit 2e6a3cd

Browse files
committed
Merge branch 'main' into unsafe-use-of-this-query
2 parents 072adaa + cd20163 commit 2e6a3cd

File tree

696 files changed

+18277
-10848
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

696 files changed

+18277
-10848
lines changed

config/identical-files.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,14 @@
358358
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
359359
"python/ql/test/TestUtilities/InlineExpectationsTest.qll"
360360
],
361+
"C++ ExternalAPIs": [
362+
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
363+
"cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll"
364+
],
365+
"C++ SafeExternalAPIFunction": [
366+
"cpp/ql/src/Security/CWE/CWE-020/SafeExternalAPIFunction.qll",
367+
"cpp/ql/src/Security/CWE/CWE-020/ir/SafeExternalAPIFunction.qll"
368+
],
361369
"XML": [
362370
"cpp/ql/src/semmle/code/cpp/XML.qll",
363371
"csharp/ql/src/semmle/code/csharp/XML.qll",
@@ -409,5 +417,12 @@
409417
"java/ql/src/Metrics/Files/CommentedOutCodeReferences.qhelp",
410418
"javascript/ql/src/Comments/CommentedOutCodeReferences.qhelp",
411419
"python/ql/src/Lexical/CommentedOutCodeReferences.qhelp"
420+
],
421+
"IDE Contextual Queries": [
422+
"cpp/ql/src/IDEContextual.qll",
423+
"csharp/ql/src/IDEContextual.qll",
424+
"java/ql/src/IDEContextual.qll",
425+
"javascript/ql/src/IDEContextual.qll",
426+
"python/ql/src/analysis/IDEContextual.qll"
412427
]
413428
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Two issues causing the 'Unused local variable' query (`cpp/unused-local-variable`) to produce false positive results have been fixed.

cpp/ql/src/Best Practices/Unused Entities/UnusedLocals.ql

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,12 @@ where
5757
not declarationHasSideEffects(v) and
5858
not exists(AsmStmt s | f = s.getEnclosingFunction()) and
5959
not v.getAnAttribute().getName() = "unused" and
60-
not any(ErrorExpr e).getEnclosingFunction() = f // unextracted expr likely used `v`
60+
not any(ErrorExpr e).getEnclosingFunction() = f and // unextracted expr may use `v`
61+
not exists(
62+
Literal l // this case can be removed when the `myFunction2( [obj](){} );` test case doesn't depend on this exclusion
63+
|
64+
l.getEnclosingFunction() = f and
65+
not exists(l.getValue())
66+
) and
67+
not any(ConditionDeclExpr cde).getEnclosingFunction() = f // this case can be removed when the `if (a = b; a)` test case doesn't depend on this exclusion
6168
select v, "Variable " + v.getName() + " is not used"

cpp/ql/src/IDEContextual.qll

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* Provides shared predicates related to contextual queries in the code viewer.
3+
*/
4+
5+
import semmle.files.FileSystem
6+
7+
/**
8+
* Returns the `File` matching the given source file name as encoded by the VS
9+
* Code extension.
10+
*/
11+
cached
12+
File getFileBySourceArchiveName(string name) {
13+
// The name provided for a file in the source archive by the VS Code extension
14+
// has some differences from the absolute path in the database:
15+
// 1. colons are replaced by underscores
16+
// 2. there's a leading slash, even for Windows paths: "C:/foo/bar" ->
17+
// "/C_/foo/bar"
18+
// 3. double slashes in UNC prefixes are replaced with a single slash
19+
// We can handle 2 and 3 together by unconditionally adding a leading slash
20+
// before replacing double slashes.
21+
name = ("/" + result.getAbsolutePath().replaceAll(":", "_")).replaceAll("//", "/")
22+
}

cpp/ql/src/Likely Bugs/Leap Year/UncheckedReturnValueForTimeFunctions.ql

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,12 @@ class SafeTimeGatheringFunction extends Function {
5050
class TimeConversionFunction extends Function {
5151
TimeConversionFunction() {
5252
this.getQualifiedName() =
53-
["FileTimeToSystemTime", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime",
54-
"SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime",
55-
"TzSpecificLocalTimeToSystemTimeEx", "RtlLocalTimeToSystemTime",
56-
"RtlTimeToSecondsSince1970", "_mkgmtime"]
53+
[
54+
"FileTimeToSystemTime", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime",
55+
"SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime",
56+
"TzSpecificLocalTimeToSystemTimeEx", "RtlLocalTimeToSystemTime",
57+
"RtlTimeToSecondsSince1970", "_mkgmtime"
58+
]
5759
}
5860
}
5961

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>Using unsanitized untrusted data in an external API can cause a variety of security issues. This query reports
7+
all external APIs that are used with untrusted data, along with how frequently the API is used, and how many
8+
unique sources of untrusted data flow to this API. This query is designed primarily to help identify which APIs
9+
may be relevant for security analysis of this application.</p>
10+
11+
<p>An external API is defined as a call to a function that is not defined in the source code, and is not
12+
modeled as a taint step in the default taint library. External APIs may be from the C++ standard library,
13+
third party dependencies or from internal dependencies. The query will report the function name, along with
14+
either <code>[param x]</code>, where <code>x</code> indicates the position of the parameter receiving the
15+
untrusted data or <code>[qualifier]</code> indicating the untrusted data is used as the qualifier to the
16+
function call.</p>
17+
18+
</overview>
19+
<recommendation>
20+
21+
<p>For each result:</p>
22+
23+
<ul>
24+
<li>If the result highlights a known sink, no action is required.</li>
25+
<li>If the result highlights an unknown sink for a problem, then add modeling for the sink to the relevant query.</li>
26+
<li>If the result represents a call to an external API which transfers taint, add the appropriate modeling, and
27+
re-run the query to determine what new results have appeared due to this additional modeling.</li>
28+
</ul>
29+
30+
<p>Otherwise, the result is likely uninteresting. Custom versions of this query can extend the <code>SafeExternalAPIFunction</code>
31+
class to exclude known safe external APIs from future analysis.</p>
32+
33+
</recommendation>
34+
<example>
35+
36+
<p>If the query were to return the API <code>fputs [param 1]</code>
37+
then we should first consider whether this a security relevant sink. In this case, this is writing to a <code>FILE*</code>, so we should
38+
consider whether this is an XSS sink. If it is, we should confirm that it is handled by the XSS query.</p>
39+
40+
<p>If the query were to return the API <code>strcat [param 1]</code>, then this should be
41+
reviewed as a possible taint step, because tainted data would flow from the 1st argument to the 0th argument of the call.</p>
42+
43+
<p>Note that both examples are correctly handled by the standard taint tracking library and XSS query.</p>
44+
</example>
45+
<references>
46+
47+
</references>
48+
</qhelp>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* @name Frequency counts for external APIs that are used with untrusted data
3+
* @description This reports the external APIs that are used with untrusted data, along with how
4+
* frequently the API is called, and how many unique sources of untrusted data flow
5+
* to it.
6+
* @id cpp/count-untrusted-data-external-api
7+
* @kind table
8+
* @tags security external/cwe/cwe-20
9+
*/
10+
11+
import cpp
12+
import ExternalAPIs
13+
14+
from ExternalAPIUsedWithUntrustedData externalAPI
15+
select externalAPI, count(externalAPI.getUntrustedDataNode()) as numberOfUses,
16+
externalAPI.getNumberOfUntrustedSources() as numberOfUntrustedSources order by
17+
numberOfUntrustedSources desc
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <cstdio>
2+
3+
void do_get(FILE* request, FILE* response) {
4+
char page[1024];
5+
fgets(page, 1024, request);
6+
7+
char buffer[1024];
8+
strcat(buffer, "The page \"");
9+
strcat(buffer, page);
10+
strcat(buffer, "\" was not found.");
11+
12+
fputs(buffer, response);
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <cstdio>
2+
3+
void do_get(FILE* request, FILE* response) {
4+
char user_id[1024];
5+
fgets(user_id, 1024, request);
6+
7+
char buffer[1024];
8+
strcat(buffer, "SELECT * FROM user WHERE user_id='");
9+
strcat(buffer, user_id);
10+
strcat(buffer, "'");
11+
12+
// ...
13+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Definitions for reasoning about untrusted data used in APIs defined outside the
3+
* database.
4+
*/
5+
6+
private import cpp
7+
private import semmle.code.cpp.models.interfaces.DataFlow
8+
private import semmle.code.cpp.models.interfaces.Taint
9+
import ExternalAPIsSpecific
10+
11+
/** A node representing untrusted data being passed to an external API. */
12+
class UntrustedExternalAPIDataNode extends ExternalAPIDataNode {
13+
UntrustedExternalAPIDataNode() { any(UntrustedDataToExternalAPIConfig c).hasFlow(_, this) }
14+
15+
/** Gets a source of untrusted data which is passed to this external API data node. */
16+
DataFlow::Node getAnUntrustedSource() {
17+
any(UntrustedDataToExternalAPIConfig c).hasFlow(result, this)
18+
}
19+
}
20+
21+
private newtype TExternalAPI =
22+
TExternalAPIParameter(Function f, int index) {
23+
exists(UntrustedExternalAPIDataNode n |
24+
f = n.getExternalFunction() and
25+
index = n.getIndex()
26+
)
27+
}
28+
29+
/** An external API which is used with untrusted data. */
30+
class ExternalAPIUsedWithUntrustedData extends TExternalAPI {
31+
/** Gets a possibly untrusted use of this external API. */
32+
UntrustedExternalAPIDataNode getUntrustedDataNode() {
33+
this = TExternalAPIParameter(result.getExternalFunction(), result.getIndex())
34+
}
35+
36+
/** Gets the number of untrusted sources used with this external API. */
37+
int getNumberOfUntrustedSources() {
38+
result = strictcount(getUntrustedDataNode().getAnUntrustedSource())
39+
}
40+
41+
/** Gets a textual representation of this element. */
42+
string toString() {
43+
exists(Function f, int index, string indexString |
44+
if index = -1 then indexString = "qualifier" else indexString = "param " + index
45+
|
46+
this = TExternalAPIParameter(f, index) and
47+
result = f.toString() + " [" + indexString + "]"
48+
)
49+
}
50+
}

0 commit comments

Comments
 (0)