Skip to content

Commit 1788a53

Browse files
authored
Merge branch 'main' into typenamehandling-queries
2 parents 378e74a + 54da53b commit 1788a53

16 files changed

Lines changed: 297 additions & 3 deletions

File tree

powershell/ql/lib/semmle/code/powershell/security/Sanitizers.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ private import semmle.code.powershell.dataflow.DataFlow
44
/**
55
* A dataflow node that is guarenteed to have a "simple" type.
66
*
7-
* Simple types include integers, floats, characters, booleans, and `datetime`.
7+
* Simple types include integers, floats, characters, booleans, `datetime`, and `guid`.
88
*/
99
class SimpleTypeSanitizer extends DataFlow::Node {
1010
SimpleTypeSanitizer() {
1111
this.asParameter().getStaticType() =
12-
["int32", "int64", "single", "double", "decimal", "char", "boolean", "datetime"]
12+
["int32", "int64", "single", "double", "decimal", "char", "boolean", "datetime", "guid"]
1313
}
1414
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
7+
<p>Using the <code>"none"</code> algorithm when creating a JWT token with
8+
<code>JwtSecurityTokenHandler</code> disables signature verification. This allows attackers to
9+
forge arbitrary tokens that will be accepted as valid, potentially leading to authentication
10+
bypass and privilege escalation.</p>
11+
12+
</overview>
13+
<recommendation>
14+
15+
<p>Always use a secure signing algorithm such as <code>HS256</code>, <code>RS256</code>, or
16+
<code>ES256</code> when creating JWT tokens. Ensure that tokens are signed with a strong secret
17+
or key pair.</p>
18+
19+
</recommendation>
20+
<example>
21+
22+
<p>In this example, a JWT token is created using the <code>"none"</code> algorithm, which produces
23+
an unsigned token:</p>
24+
25+
<sample src="examples/JwtNoneAlgorithmBad.ps1" />
26+
27+
<p>The fix is to use a secure algorithm instead:</p>
28+
29+
<sample src="examples/JwtNoneAlgorithmGood.ps1" />
30+
31+
</example>
32+
<references>
33+
34+
<li>
35+
RFC 7518:
36+
<a href="https://datatracker.ietf.org/doc/html/rfc7518#section-3.6">JSON Web Algorithms - Unsecured JWS</a>.
37+
</li>
38+
39+
<li>
40+
CWE-347:
41+
<a href="https://cwe.mitre.org/data/definitions/347.html">Improper Verification of Cryptographic Signature</a>.
42+
</li>
43+
44+
</references>
45+
</qhelp>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* @name JWT none algorithm usage
3+
* @description Using the "none" algorithm for JWT tokens disables signature verification,
4+
* allowing token forgery.
5+
* @kind problem
6+
* @problem.severity error
7+
* @security-severity 9.8
8+
* @precision high
9+
* @id powershell/jwt-none-algorithm
10+
* @tags security
11+
* external/cwe/cwe-347
12+
*/
13+
14+
import powershell
15+
import semmle.code.powershell.dataflow.DataFlow
16+
17+
/**
18+
* A string literal "none" passed as an algorithm argument to .NET JWT methods
19+
* on a JwtSecurityTokenHandler instance.
20+
*/
21+
class JwtNoneInDotNetCall extends StringConstExpr {
22+
JwtNoneInDotNetCall() {
23+
this.getValueString().toLowerCase() = "none" and
24+
exists(DataFlow::CallNode cn, DataFlow::ObjectCreationNode ocn |
25+
cn.getQualifier().getALocalSource() = ocn and
26+
ocn.getConstructedTypeNode().asExpr().getExpr().(TypeNameExpr).hasQualifiedName("system.identitymodel.tokens.jwt", "jwtsecuritytokenhandler") and
27+
cn.getLowerCaseName() in [
28+
"createtoken", "writetoken", "createjwtsecuritytoken", "createencodedjwt"
29+
] and
30+
cn.getAnArgument().asExpr().getExpr() = this
31+
)
32+
}
33+
}
34+
35+
from JwtNoneInDotNetCall noneAlg
36+
select noneAlg,
37+
"JWT token created with 'none' algorithm via .NET API, disabling signature verification."
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
$handler = [System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler]::new()
2+
3+
# BAD: Creating a JWT token with the "none" algorithm disables signature verification.
4+
$token = $handler.CreateToken("none")
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
$handler = [System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler]::new()
2+
3+
# GOOD: Creating a JWT token with a secure algorithm.
4+
$token = $handler.CreateToken("HS256")
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
2+
<qhelp>
3+
<overview>
4+
<p>
5+
TLS (Transport Layer Security) and its predecessor SSL (Secure Sockets Layer) are protocols
6+
used to secure network communications. Older versions of these protocols have known
7+
vulnerabilities that can be exploited by attackers to compromise the confidentiality and
8+
integrity of data in transit.
9+
</p>
10+
<p>
11+
The following versions are considered deprecated:
12+
</p>
13+
<ul>
14+
<li>SSL 3.0 is vulnerable to the POODLE attack and other weaknesses.</li>
15+
<li>TLS 1.0 has known vulnerabilities including the BEAST attack and weak cipher suites.</li>
16+
<li>TLS 1.1 lacks support for modern cryptographic algorithms and is deprecated by RFC 8996.</li>
17+
</ul>
18+
</overview>
19+
<recommendation>
20+
<p>
21+
Use TLS 1.2 or TLS 1.3 for all secure communications. TLS 1.3 is preferred as it removes
22+
support for legacy cryptographic features and provides improved performance. When configuring
23+
<code>SecurityProtocolType</code>, use <code>Tls12</code> or <code>Tls13</code>.
24+
</p>
25+
</recommendation>
26+
<example>
27+
<p>
28+
In the following example, the script enables the deprecated SSL 3.0 and TLS 1.0 protocols:
29+
</p>
30+
<sample src="examples/DeprecatedTls/DeprecatedTlsBad.ps1" />
31+
<p>
32+
The following example shows the corrected code using TLS 1.2:
33+
</p>
34+
<sample src="examples/DeprecatedTls/DeprecatedTlsGood.ps1" />
35+
</example>
36+
<references>
37+
<li>IETF, RFC 8996: <a href="https://datatracker.ietf.org/doc/html/rfc8996">Deprecating TLS 1.0 and TLS 1.1</a>.</li>
38+
<li>NIST, SP 800-52 Rev. 2: <a href="https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final">Guidelines for the Selection, Configuration, and Use of TLS Implementations</a>.</li>
39+
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html">Transport Layer Security Cheat Sheet</a>.</li>
40+
<li>CWE-757: <a href="https://cwe.mitre.org/data/definitions/757.html">Selection of Less-Secure Algorithm During Negotiation ('Algorithm Downgrade')</a>.</li>
41+
</references>
42+
</qhelp>
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
* @name Use of deprecated TLS/SSL version
3+
* @description Using deprecated TLS/SSL versions (SSL3, TLS 1.0, TLS 1.1) weakens transport security.
4+
* @kind problem
5+
* @problem.severity error
6+
* @security-severity 7.5
7+
* @precision high
8+
* @id powershell/deprecated-tls
9+
* @tags security
10+
* external/cwe/cwe-327
11+
* external/cwe/cwe-757
12+
*/
13+
14+
import powershell
15+
import semmle.code.powershell.ApiGraphs
16+
import semmle.code.powershell.dataflow.DataFlow
17+
18+
/**
19+
* Gets the human-readable name for a deprecated protocol.
20+
*/
21+
bindingset[protocolName]
22+
string getProtocolDisplayName(string protocolName) {
23+
protocolName = "ssl3" and result = "SSL 3.0"
24+
or
25+
protocolName = "tls" and result = "TLS 1.0"
26+
or
27+
protocolName = "tls11" and result = "TLS 1.1"
28+
}
29+
30+
abstract class SecurityProtocol extends Expr {
31+
abstract string getProtocolName();
32+
}
33+
34+
/**
35+
* A reference to a deprecated SecurityProtocolType enum value, e.g.
36+
* [Net.SecurityProtocolType]::Ssl3
37+
*/
38+
class DeprecatedSecurityProtocolType extends SecurityProtocol {
39+
string protocolName;
40+
41+
DeprecatedSecurityProtocolType() {
42+
exists(API::Node node |
43+
(
44+
node =
45+
API::getTopLevelMember("system")
46+
.getMember("net")
47+
.getMember("securityprotocoltype")
48+
.getMember(protocolName)
49+
or
50+
node =
51+
API::getTopLevelMember("net")
52+
.getMember("securityprotocoltype")
53+
.getMember(protocolName)
54+
) and
55+
this = node.asSource().asExpr().getExpr()
56+
)
57+
}
58+
59+
override string getProtocolName() { result = protocolName }
60+
}
61+
62+
/**
63+
* A reference to a deprecated SslProtocols enum value, e.g.
64+
* [System.Security.Authentication.SslProtocols]::Tls
65+
*/
66+
class DeprecatedSslProtocols extends SecurityProtocol {
67+
string protocolName;
68+
69+
DeprecatedSslProtocols() {
70+
exists(API::Node node |
71+
node =
72+
API::getTopLevelMember("system")
73+
.getMember("security")
74+
.getMember("authentication")
75+
.getMember("sslprotocols")
76+
.getMember(protocolName) and
77+
this = node.asSource().asExpr().getExpr()
78+
)
79+
}
80+
81+
override string getProtocolName() { result = protocolName }
82+
}
83+
84+
from SecurityProtocol sp, string protocolName
85+
where
86+
protocolName = sp.getProtocolName() and
87+
protocolName = ["ssl3", "tls", "tls11"]
88+
select sp,
89+
"Use of deprecated protocol " + getProtocolDisplayName(protocolName) +
90+
". Use TLS 1.2 or TLS 1.3 instead."
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# BAD: Using deprecated SSL 3.0
2+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Ssl3
3+
4+
# BAD: Using deprecated TLS 1.0
5+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls
6+
7+
# BAD: Using deprecated TLS 1.1
8+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls11
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# GOOD: Using TLS 1.2
2+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
3+
4+
# GOOD: Using TLS 1.3
5+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls13

powershell/ql/test/query-tests/security/cwe-089/test.ps1

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,13 @@ $QueryConn3 = @{
138138

139139
Invoke-Sqlcmd @QueryConn3 # GOOD
140140

141-
&sqlcmd -e -S $userinput -U "Login" -P "MyPassword" -d "MyDBName" -i "input_file.sql" # GOOD
141+
&sqlcmd -e -S $userinput -U "Login" -P "MyPassword" -d "MyDBName" -i "input_file.sql" # GOOD
142+
143+
function WithGuid {
144+
PARAM([Parameter(Mandatory = $true)] [guid] $r)
145+
146+
$query = "SELECT * FROM MyTable WHERE MyColumn = '$r'"
147+
Invoke-Sqlcmd -ServerInstance "MyServer" -Database "MyDatabase" -q $query # GOOD
148+
}
149+
150+
WithGuid $userinput

0 commit comments

Comments
 (0)