Merge pull request #20692 from joefarebrother/csharp-secure-cookie-promote

C#: Promote insecure cookie and httponly cookie queries
This commit is contained in:
Joe Farebrother
2025-11-10 15:02:45 +00:00
committed by GitHub
141 changed files with 561 additions and 907 deletions

View File

@@ -16,6 +16,7 @@ ql/csharp/ql/src/Security Features/CWE-090/LDAPInjection.ql
ql/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql ql/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql
ql/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql ql/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql
ql/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql ql/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql
ql/csharp/ql/src/Security Features/CWE-1004/CookieWithoutHttpOnly.ql
ql/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql ql/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql
ql/csharp/ql/src/Security Features/CWE-117/LogForging.ql ql/csharp/ql/src/Security Features/CWE-117/LogForging.ql
ql/csharp/ql/src/Security Features/CWE-119/LocalUnvalidatedArithmetic.ql ql/csharp/ql/src/Security Features/CWE-119/LocalUnvalidatedArithmetic.ql
@@ -33,6 +34,7 @@ ql/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.q
ql/csharp/ql/src/Security Features/CWE-548/ASPNetDirectoryListing.ql ql/csharp/ql/src/Security Features/CWE-548/ASPNetDirectoryListing.ql
ql/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql ql/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql
ql/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql ql/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql
ql/csharp/ql/src/Security Features/CWE-614/CookieWithoutSecure.ql
ql/csharp/ql/src/Security Features/CWE-614/RequireSSL.ql ql/csharp/ql/src/Security Features/CWE-614/RequireSSL.ql
ql/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql ql/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql
ql/csharp/ql/src/Security Features/CWE-730/ReDoS.ql ql/csharp/ql/src/Security Features/CWE-730/ReDoS.ql

View File

@@ -120,6 +120,7 @@ ql/csharp/ql/src/Security Features/CWE-090/LDAPInjection.ql
ql/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql ql/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql
ql/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql ql/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql
ql/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql ql/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql
ql/csharp/ql/src/Security Features/CWE-1004/CookieWithoutHttpOnly.ql
ql/csharp/ql/src/Security Features/CWE-112/MissingXMLValidation.ql ql/csharp/ql/src/Security Features/CWE-112/MissingXMLValidation.ql
ql/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql ql/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql
ql/csharp/ql/src/Security Features/CWE-117/LogForging.ql ql/csharp/ql/src/Security Features/CWE-117/LogForging.ql
@@ -140,6 +141,7 @@ ql/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.q
ql/csharp/ql/src/Security Features/CWE-548/ASPNetDirectoryListing.ql ql/csharp/ql/src/Security Features/CWE-548/ASPNetDirectoryListing.ql
ql/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql ql/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql
ql/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql ql/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql
ql/csharp/ql/src/Security Features/CWE-614/CookieWithoutSecure.ql
ql/csharp/ql/src/Security Features/CWE-614/RequireSSL.ql ql/csharp/ql/src/Security Features/CWE-614/RequireSSL.ql
ql/csharp/ql/src/Security Features/CWE-639/InsecureDirectObjectReference.ql ql/csharp/ql/src/Security Features/CWE-639/InsecureDirectObjectReference.ql
ql/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql ql/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql

View File

@@ -23,6 +23,7 @@ ql/csharp/ql/src/Security Features/CWE-090/LDAPInjection.ql
ql/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql ql/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql
ql/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql ql/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql
ql/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql ql/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql
ql/csharp/ql/src/Security Features/CWE-1004/CookieWithoutHttpOnly.ql
ql/csharp/ql/src/Security Features/CWE-112/MissingXMLValidation.ql ql/csharp/ql/src/Security Features/CWE-112/MissingXMLValidation.ql
ql/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql ql/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql
ql/csharp/ql/src/Security Features/CWE-117/LogForging.ql ql/csharp/ql/src/Security Features/CWE-117/LogForging.ql
@@ -43,6 +44,7 @@ ql/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.q
ql/csharp/ql/src/Security Features/CWE-548/ASPNetDirectoryListing.ql ql/csharp/ql/src/Security Features/CWE-548/ASPNetDirectoryListing.ql
ql/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql ql/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql
ql/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql ql/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql
ql/csharp/ql/src/Security Features/CWE-614/CookieWithoutSecure.ql
ql/csharp/ql/src/Security Features/CWE-614/RequireSSL.ql ql/csharp/ql/src/Security Features/CWE-614/RequireSSL.ql
ql/csharp/ql/src/Security Features/CWE-639/InsecureDirectObjectReference.ql ql/csharp/ql/src/Security Features/CWE-639/InsecureDirectObjectReference.ql
ql/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql ql/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql

View File

@@ -84,9 +84,7 @@ ql/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql
ql/csharp/ql/src/definitions.ql ql/csharp/ql/src/definitions.ql
ql/csharp/ql/src/experimental/CWE-099/TaintedWebClient.ql ql/csharp/ql/src/experimental/CWE-099/TaintedWebClient.ql
ql/csharp/ql/src/experimental/CWE-918/RequestForgery.ql ql/csharp/ql/src/experimental/CWE-918/RequestForgery.ql
ql/csharp/ql/src/experimental/Security Features/CWE-1004/CookieWithoutHttpOnly.ql
ql/csharp/ql/src/experimental/Security Features/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql ql/csharp/ql/src/experimental/Security Features/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql
ql/csharp/ql/src/experimental/Security Features/CWE-614/CookieWithoutSecure.ql
ql/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql ql/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
ql/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.ql ql/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.ql
ql/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/security-validation-disabled.ql ql/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/security-validation-disabled.ql

View File

@@ -1,13 +1,13 @@
/** /**
* Provides classes and predicates for detecting insecure cookies. * Definitions for detecting insecure and non-HttpOnly cookies.
*/ */
deprecated module;
import csharp import csharp
import semmle.code.csharp.frameworks.microsoft.AspNetCore private import semmle.code.csharp.frameworks.system.Web
private import semmle.code.csharp.frameworks.microsoft.AspNetCore
/** /**
* Holds if the expression is a variable with a sensitive name. * Holds if the expression is a sensitive string literal or a variable with a sensitive name.
*/ */
predicate isCookieWithSensitiveName(Expr cookieExpr) { predicate isCookieWithSensitiveName(Expr cookieExpr) {
exists(DataFlow::Node sink | exists(DataFlow::Node sink |
@@ -17,7 +17,7 @@ predicate isCookieWithSensitiveName(Expr cookieExpr) {
} }
/** /**
* Configuration for tracking if a variable with a sensitive name is used as an argument. * Configuration for tracking if a sensitive string literal or a variable with a sensitive name is used as an argument.
*/ */
private module AuthCookieNameConfig implements DataFlow::ConfigSig { private module AuthCookieNameConfig implements DataFlow::ConfigSig {
private predicate isAuthVariable(Expr expr) { private predicate isAuthVariable(Expr expr) {
@@ -33,7 +33,15 @@ private module AuthCookieNameConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isAuthVariable(source.asExpr()) } predicate isSource(DataFlow::Node source) { isAuthVariable(source.asExpr()) }
predicate isSink(DataFlow::Node sink) { exists(Call c | sink.asExpr() = c.getAnArgument()) } predicate isSink(DataFlow::Node sink) {
exists(Call c |
sink.asExpr() = c.getAnArgument() and
(
c.getTarget() = any(MicrosoftAspNetCoreHttpResponseCookies cls).getAppendMethod() or
c.(ObjectCreation).getType() instanceof SystemWebHttpCookie
)
)
}
} }
/** /**
@@ -119,13 +127,13 @@ private signature string propertyName();
/** /**
* Configuration for tracking if a callback used in `OnAppendCookie` sets a cookie property to `true`. * Configuration for tracking if a callback used in `OnAppendCookie` sets a cookie property to `true`.
*
* ` getPropertyName` specifies the cookie property name to track.
*/ */
private module OnAppendCookieTrackingConfig<propertyName/0 getPropertyName> implements private module OnAppendCookieTrackingConfig<propertyName/0 getPropertyName> implements
DataFlow::ConfigSig DataFlow::ConfigSig
{ {
/** /** Source is the parameter of a callback passed to `OnAppendCookie` */
* Specifies the cookie property name to track.
*/
predicate isSource(DataFlow::Node source) { predicate isSource(DataFlow::Node source) {
exists(PropertyWrite pw, Assignment delegateAssign, Callable c | exists(PropertyWrite pw, Assignment delegateAssign, Callable c |
pw.getProperty().getName() = "OnAppendCookie" and pw.getProperty().getName() = "OnAppendCookie" and
@@ -146,6 +154,7 @@ private module OnAppendCookieTrackingConfig<propertyName/0 getPropertyName> impl
) )
} }
/** Sink is a property write that sets the given property to `true`. */
predicate isSink(DataFlow::Node sink) { predicate isSink(DataFlow::Node sink) {
exists(PropertyWrite pw, Assignment a | exists(PropertyWrite pw, Assignment a |
pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieOptions and pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
@@ -178,7 +187,7 @@ private module OnAppendCookieSecureTrackingConfig =
OnAppendCookieTrackingConfig<getPropertyNameSecure/0>; OnAppendCookieTrackingConfig<getPropertyNameSecure/0>;
/** /**
* Tracks if a callback used in `OnAppendCookie` sets `Secure` to `true`. * Tracks if a callback used in `OnAppendCookie` sets `Secure` to `true`, and thus cookies appended to responses are secure by default.
*/ */
module OnAppendCookieSecureTracking = DataFlow::Global<OnAppendCookieSecureTrackingConfig>; module OnAppendCookieSecureTracking = DataFlow::Global<OnAppendCookieSecureTrackingConfig>;
@@ -191,6 +200,6 @@ private module OnAppendCookieHttpOnlyTrackingConfig =
OnAppendCookieTrackingConfig<getPropertyNameHttpOnly/0>; OnAppendCookieTrackingConfig<getPropertyNameHttpOnly/0>;
/** /**
* Tracks if a callback used in `OnAppendCookie` sets `HttpOnly` to `true`. * Tracks if a callback used in `OnAppendCookie` sets `HttpOnly` to `true`, and thus cookies appended to responses are httponly by default.
*/ */
module OnAppendCookieHttpOnlyTracking = DataFlow::Global<OnAppendCookieHttpOnlyTrackingConfig>; module OnAppendCookieHttpOnlyTracking = DataFlow::Global<OnAppendCookieHttpOnlyTrackingConfig>;

View File

@@ -0,0 +1,60 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Cookies without the <code>HttpOnly</code> flag set are accessible to client-side scripts such as JavaScript running in the same origin.
In case of a Cross-Site Scripting (XSS) vulnerability, the cookie can be stolen by a malicious script.
If a sensitive cookie does not need to be accessed directly by client-side JS, the <code>HttpOnly</code> flag should be set.</p>
</overview>
<recommendation>
<p>
Set the <code>HttpOnly</code> flag to <code>true</code> for authentication cookies to ensure they are not accessible to client-side scripts.
</p>
<p>
When using ASP.NET Core, <code>CookiePolicyOptions</code> can be used to set a default policy for cookies.
When using ASP.NET Web Forms, a default may also be configured in the <code>Web.config</code> file, using the <code>httpOnlyCookies</code> attribute of the
the <code>&lt;httpCookies&gt;</code> element.
</p>
</recommendation>
<example>
<p>
In the example below, <code>Microsoft.AspNetCore.Http.CookieOptions.HttpOnly</code> is set to <code>true</code>.
</p>
<sample src="httponlyflagcore.cs" />
<p>
In the following example, <code>CookiePolicyOptions</code> are set programmatically to configure defaults.
</p>
<sample src="cookiepolicyoptions.cs" />
<p>
In the example below, <code>System.Web.HttpCookie.HttpOnly</code> is set to <code>true</code>.
</p>
<sample src="httponlyflag.cs" />
<p>
In the example below, the <code>httpOnlyCookies</code> attribute is set to <code>true</code> in the <code>Web.config</code> file.
</p>
<sample src="Web.config"/>
</example>
<references>
<li>ASP.Net Core docs: <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.cookieoptions.httponly">CookieOptions.HttpOnly Property</a>.</li>
<li>MDN: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header.</li>
<li>Web Forms docs: <a href="https://msdn.microsoft.com/en-us/library/system.web.httpcookie.httponly(v=vs.110).aspx">HttpCookie.HttpOnly Property</a>.</li>
<li>Web Forms docs: <a href="https://msdn.microsoft.com/library/ms228262%28v=vs.100%29.aspx">httpCookies Element</a>.</li>
<li>PortSwigger: <a href="https://portswigger.net/kb/issues/00500600_cookie-without-httponly-flag-set">Cookie without HttpOnly flag set</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,118 @@
/**
* @name Cookie 'HttpOnly' attribute is not set to true
* @description Sensitive cookies without the `HttpOnly` property set are accessible by client-side scripts such as JavaScript.
* This makes them more vulnerable to being stolen by an XSS attack.
* @kind problem
* @problem.severity warning
* @security-severity 5.0
* @precision high
* @id cs/web/cookie-httponly-not-set
* @tags security
* external/cwe/cwe-1004
*/
import csharp
import semmle.code.asp.WebConfig
import semmle.code.csharp.frameworks.system.Web
import semmle.code.csharp.frameworks.microsoft.AspNetCore
import semmle.code.csharp.security.auth.SecureCookies
predicate cookieAppendHttpOnlyByDefault() {
// default is set to `Always`
getAValueForCookiePolicyProp("HttpOnly").getValue() = "1"
or
// there is an `OnAppendCookie` callback that sets `HttpOnly` to true
OnAppendCookieHttpOnlyTracking::flowTo(_)
}
predicate httpOnlyFalse(ObjectCreation oc) {
exists(Assignment a |
getAValueForProp(oc, a, "HttpOnly") = a.getRValue() and
a.getRValue().getValue() = "false"
)
}
predicate httpOnlyFalseOrNotSet(ObjectCreation oc) {
httpOnlyFalse(oc)
or
not isPropertySet(oc, "HttpOnly")
}
predicate nonHttpOnlyCookieOptionsCreation(ObjectCreation oc, MethodCall append) {
// `HttpOnly` property in `CookieOptions` passed to IResponseCookies.Append(...) wasn't set
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
httpOnlyFalseOrNotSet(oc) and
exists(DataFlow::Node creation, DataFlow::Node sink |
CookieOptionsTracking::flow(creation, sink) and
creation.asExpr() = oc and
sink.asExpr() = append.getArgument(2)
)
}
predicate nonHttpOnlySystemWebSensitiveCookieCreation(ObjectCreation oc) {
oc.getType() instanceof SystemWebHttpCookie and
isCookieWithSensitiveName(oc.getArgument(0)) and
(
httpOnlyFalse(oc)
or
// the property wasn't explicitly set, so a default value from config is used
not isPropertySet(oc, "HttpOnly") and
// the default in config is not set to `true`
not exists(XmlElement element |
element instanceof HttpCookiesElement and
element.(HttpCookiesElement).isHttpOnlyCookies()
)
)
}
predicate sensitiveCookieAppend(MethodCall mc) {
exists(MicrosoftAspNetCoreHttpResponseCookies iResponse |
iResponse.getAppendMethod() = mc.getTarget() and
isCookieWithSensitiveName(mc.getArgument(0))
)
}
predicate nonHttpOnlyCookieCall(Call c) {
(
not cookieAppendHttpOnlyByDefault() and
exists(MethodCall mc |
sensitiveCookieAppend(mc) and
(
nonHttpOnlyCookieOptionsCreation(c, mc)
or
// IResponseCookies.Append(String, String) was called, `HttpOnly` is set to `false` by default
mc = c and
mc.getNumberOfArguments() < 3 and
mc.getTarget().getParameter(0).getType() instanceof StringType
)
)
or
nonHttpOnlySystemWebSensitiveCookieCreation(c)
)
}
predicate nonHttpOnlyCookieBuilderAssignment(Assignment a, Expr val) {
val.getValue() = "false" and
exists(PropertyWrite pw |
(
pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieBuilder or
pw.getProperty().getDeclaringType() instanceof
MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions
) and
pw.getProperty().getName() = "HttpOnly" and
a.getLValue() = pw and
DataFlow::localExprFlow(val, a.getRValue())
)
}
from Expr httpOnlySink
where
(
nonHttpOnlyCookieCall(httpOnlySink)
or
exists(Assignment a |
httpOnlySink = a.getRValue() and
nonHttpOnlyCookieBuilderAssignment(a, _)
)
)
select httpOnlySink, "Cookie attribute 'HttpOnly' is not set to true."

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<configuration> <configuration>
<system.web> <system.web>
<httpCookies requireSSL="false" /> <httpCookies httpOnlyCookies="true"/>
</system.web> </system.web>
</configuration> </configuration>

View File

@@ -0,0 +1,61 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Cookies without the <code>Secure</code> flag set may be transmitted using HTTP instead of HTTPS.
This leaves them vulnerable to being read by a third party attacker. If a sensitive cookie such as a session
key is intercepted this way, it would allow the attacker to perform actions on a user's behalf.</p>
</overview>
<recommendation>
<p>
When using ASP.NET Core, ensure cookies have the secure flag set by setting <code>Microsoft.AspNetCore.Http.CookieOptions.Secure</code> to <code>true</code>, or
using <code>CookiePolicyOptions</code> to set a default security policy.
</p>
<p>
When using ASP.NET Web Forms, cookies can be configured as secure by default in the <code>Web.config</code> file, setting the <code>requireSSL</code> attribute to <code>true</code> in the <code>forms</code> or <code>httpCookies</code> element.
Cookies may also be set to be secure programmatically by setting the <code>System.Web.HttpCookie.Secure</code> attribute to <code>true</code>.
</p>
</recommendation>
<example>
<p>
In the example below, <code>Microsoft.AspNetCore.Http.CookieOptions.Secure</code> is set to <code>true</code>.
</p>
<sample src="secureflagcore.cs" />
<p>
In the following example, <code>CookiePolicyOptions</code> are set programmatically to configure defaults.
</p>
<sample src="cookiepolicyoptions.cs" />
<p>
In the example below <code>System.Web.HttpCookie.Secure</code> is set to <code>true</code> programmatically.
</p>
<sample src="secureflag.cs" />
<p>
In the example below, the <code>requireSSL</code> attribute is set to <code>true</code> in the <code>forms</code> element of the <code>Web.config</code> file.
</p>
<sample src="Web.config" />
</example>
<references>
<li>ASP.NET Core docs: <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.cookieoptions.secure">CookieOptions.Secure Property</a>.</li>
<li>MDN: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header.</li>
<li>Web Forms docs: <a href="https://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.requiressl(v=vs.110).aspx">FormsAuthentication.RequireSSL Property</a>.</li>
<li>Web Forms docs: <a href="https://msdn.microsoft.com/en-us/library/1d3t3c61(v=vs.100).aspx">forms Element for authentication</a>.</li>
<li>Web Forms docs: <a href="https://msdn.microsoft.com/library/ms228262%28v=vs.100%29.aspx">httpCookies Element</a>.</li>
<li>Detectify: <a href="https://support.detectify.com/support/solutions/articles/48001048982-cookie-lack-secure-flag">Cookie lack Secure flag</a>.</li>
<li>PortSwigger: <a href="https://portswigger.net/kb/issues/00500200_tls-cookie-without-secure-flag-set">TLS cookie without secure flag set</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,116 @@
/**
* @name Cookie 'Secure' attribute is not set to true
* @description Cookies without the `Secure` flag may be sent in cleartext.
* This makes them vulnerable to be intercepted by an attacker.
* @kind problem
* @problem.severity error
* @security-severity 5.0
* @precision high
* @id cs/web/cookie-secure-not-set
* @tags security
* external/cwe/cwe-319
* external/cwe/cwe-614
*/
import csharp
import semmle.code.asp.WebConfig
import semmle.code.csharp.frameworks.system.Web
import semmle.code.csharp.frameworks.microsoft.AspNetCore
import semmle.code.csharp.security.auth.SecureCookies
predicate cookieAppendSecureByDefault() {
// default is set to `Always` or `SameAsRequest`
(
getAValueForCookiePolicyProp("Secure").getValue() = "0" or
getAValueForCookiePolicyProp("Secure").getValue() = "1"
)
or
//callback `OnAppendCookie` that sets `Secure` to true
OnAppendCookieSecureTracking::flowTo(_)
}
predicate secureFalse(ObjectCreation oc) {
exists(Assignment a |
getAValueForProp(oc, a, "Secure") = a.getRValue() and
a.getRValue().getValue() = "false"
)
}
predicate secureFalseOrNotSet(ObjectCreation oc) {
secureFalse(oc)
or
not isPropertySet(oc, "Secure")
}
predicate insecureCookieOptionsCreation(ObjectCreation oc) {
// `Secure` property in `CookieOptions` passed to IResponseCookies.Append(...) wasn't set
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
secureFalseOrNotSet(oc) and
exists(DataFlow::Node creation |
CookieOptionsTracking::flow(creation, _) and
creation.asExpr() = oc
)
}
predicate insecureCookieAppend(Expr sink) {
// IResponseCookies.Append(String, String) was called, `Secure` is set to `false` by default
exists(MethodCall mc, MicrosoftAspNetCoreHttpResponseCookies iResponse |
mc = sink and
iResponse.getAppendMethod() = mc.getTarget() and
mc.getNumberOfArguments() < 3 and
mc.getTarget().getParameter(0).getType() instanceof StringType
)
}
predicate insecureSystemWebCookieCreation(ObjectCreation oc) {
oc.getType() instanceof SystemWebHttpCookie and
(
secureFalse(oc)
or
// `Secure` property in `System.Web.HttpCookie` wasn't set, so a default value from config is used
not isPropertySet(oc, "Secure") and
// the default in config is not set to `true`
not exists(XmlElement element |
element instanceof FormsElement and
element.(FormsElement).isRequireSsl()
or
element instanceof HttpCookiesElement and
element.(HttpCookiesElement).isRequireSsl()
)
)
}
predicate insecureCookieCall(Call c) {
not cookieAppendSecureByDefault() and
(
insecureCookieOptionsCreation(c)
or
insecureCookieAppend(c)
)
or
insecureSystemWebCookieCreation(c)
}
predicate insecureSecurePolicyAssignment(Assignment a, Expr val) {
exists(PropertyWrite pw |
(
pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieBuilder or
pw.getProperty().getDeclaringType() instanceof
MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions
) and
pw.getProperty().getName() = "SecurePolicy" and
a.getLValue() = pw and
DataFlow::localExprFlow(val, a.getRValue()) and
val.getValue() = "2" // None
)
}
from Expr secureSink
where
insecureCookieCall(secureSink)
or
exists(Assignment a |
secureSink = a.getRValue() and
insecureSecurePolicyAssignment(a, _)
)
select secureSink, "Cookie attribute 'Secure' is not set to true."

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
The `cs/web/cookie-secure-not-set` and `cs/web/cookie-httponly-not-set` queries have been promoted from experimental to the main query pack.

View File

@@ -1,51 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Cookies without <code>HttpOnly</code> flag are accessible to JavaScript running in the same origin. In case of
Cross-Site Scripting (XSS) vulnerability the cookie can be stolen by malicious script.
</p>
</overview>
<recommendation>
<p>
Protect sensitive cookies, such as related to authentication, by setting <code>HttpOnly</code> to <code>true</code> to make
them not accessible to JavaScript. In ASP.NET case it is also possible to set the attribute via <code>&lt;httpCookies&gt;</code> element
of <code>web.config</code> with the attribute <code>httpOnlyCookies="true"</code>.
</p>
</recommendation>
<example>
<p>
In the example below <code>Microsoft.AspNetCore.Http.CookieOptions.HttpOnly</code> is set to <code>true</code>.
</p>
<sample src="httponlyflagcore.cs" />
<p>
In the following example <code>CookiePolicyOptions</code> are set programmatically to configure defaults.
</p>
<sample src="cookiepolicyoptions.cs" />
<p>
In the example below <code>System.Web.HttpCookie.HttpOnly</code> is set to <code>true</code>.
</p>
<sample src="httponlyflag.cs" />
</example>
<references>
<li><a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.cookieoptions.httponly">CookieOptions.HttpOnly Property,</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header,</li>
<li><a href="https://msdn.microsoft.com/en-us/library/system.web.httpcookie.httponly(v=vs.110).aspx">HttpCookie.HttpOnly Property,</a></li>
<li><a href="https://msdn.microsoft.com/library/ms228262%28v=vs.100%29.aspx">httpCookies Element,</a></li>
</references>
</qhelp>

View File

@@ -1,107 +0,0 @@
/**
* @name 'HttpOnly' attribute is not set to true
* @description Omitting the 'HttpOnly' attribute for security sensitive data allows
* malicious JavaScript to steal it in case of XSS vulnerability. Always set
* 'HttpOnly' to 'true' to authentication related cookie to make it
* not accessible by JavaScript.
* @kind problem
* @problem.severity warning
* @precision high
* @id cs/web/cookie-httponly-not-set
* @tags security
* experimental
* external/cwe/cwe-1004
*/
import csharp
import semmle.code.asp.WebConfig
import semmle.code.csharp.frameworks.system.Web
import semmle.code.csharp.frameworks.microsoft.AspNetCore
deprecated import experimental.dataflow.flowsources.AuthCookie
deprecated query predicate problems(Expr httpOnlySink, string message) {
(
exists(Assignment a, Expr val |
httpOnlySink = a.getRValue() and
val.getValue() = "false" and
(
exists(ObjectCreation oc |
getAValueForProp(oc, a, "HttpOnly") = val and
(
oc.getType() instanceof SystemWebHttpCookie and
isCookieWithSensitiveName(oc.getArgument(0))
or
exists(MethodCall mc, MicrosoftAspNetCoreHttpResponseCookies iResponse |
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
iResponse.getAppendMethod() = mc.getTarget() and
isCookieWithSensitiveName(mc.getArgument(0)) and
// there is no callback `OnAppendCookie` that sets `HttpOnly` to true
not OnAppendCookieHttpOnlyTracking::flowTo(_) and
// Passed as third argument to `IResponseCookies.Append`
exists(DataFlow::Node creation, DataFlow::Node append |
CookieOptionsTracking::flow(creation, append) and
creation.asExpr() = oc and
append.asExpr() = mc.getArgument(2)
)
)
)
)
or
exists(PropertyWrite pw |
(
pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieBuilder or
pw.getProperty().getDeclaringType() instanceof
MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions
) and
pw.getProperty().getName() = "HttpOnly" and
a.getLValue() = pw and
DataFlow::localExprFlow(val, a.getRValue())
)
)
)
or
exists(Call c |
httpOnlySink = c and
(
exists(MicrosoftAspNetCoreHttpResponseCookies iResponse, MethodCall mc |
// default is not configured or is not set to `Always`
not getAValueForCookiePolicyProp("HttpOnly").getValue() = "1" and
// there is no callback `OnAppendCookie` that sets `HttpOnly` to true
not OnAppendCookieHttpOnlyTracking::flowTo(_) and
iResponse.getAppendMethod() = mc.getTarget() and
isCookieWithSensitiveName(mc.getArgument(0)) and
(
// `HttpOnly` property in `CookieOptions` passed to IResponseCookies.Append(...) wasn't set
exists(ObjectCreation oc |
oc = c and
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
not isPropertySet(oc, "HttpOnly") and
exists(DataFlow::Node creation |
CookieOptionsTracking::flow(creation, _) and
creation.asExpr() = oc
)
)
or
// IResponseCookies.Append(String, String) was called, `HttpOnly` is set to `false` by default
mc = c and
mc.getNumberOfArguments() < 3
)
)
or
exists(ObjectCreation oc |
oc = c and
oc.getType() instanceof SystemWebHttpCookie and
isCookieWithSensitiveName(oc.getArgument(0)) and
// the property wasn't explicitly set, so a default value from config is used
not isPropertySet(oc, "HttpOnly") and
// the default in config is not set to `true`
not exists(XmlElement element |
element instanceof HttpCookiesElement and
element.(HttpCookiesElement).isHttpOnlyCookies()
)
)
)
)
) and
message = "Cookie attribute 'HttpOnly' is not set to true."
}

View File

@@ -1,55 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Sensitive data that is transmitted using HTTP is vulnerable to being read by a third party. By default,
cookies are sent via HTTP, not HTTPS.
</p>
</overview>
<recommendation>
<p>
In ASP.NET case when using cookies ensure that HTTPS is used by setting the property <code>Microsoft.AspNetCore.Http.CookieOptions.Secure</code> to <code>true</code>.
</p>
<p>
In ASP.NET Core case when using cookies, ensure that HTTPS is used, either via the <code>&lt;forms&gt;</code> attribute above, or
the <code>&lt;httpCookies&gt;</code> element, with the attribute <code>requireSSL="true"</code>. It is also possible to require cookies
to use HTTPS programmatically, by setting the property <code>System.Web.HttpCookie.Secure</code> to <code>true</code>.
</p>
</recommendation>
<example>
<p>
In the example below <code>Microsoft.AspNetCore.Http.CookieOptions.Secure</code> is set to <code>true</code> programmatically.
</p>
<sample src="secureflagcore.cs" />
<p>
In the following example <code>CookiePolicyOptions</code> are set programmatically to configure defaults.
</p>
<sample src="cookiepolicyoptions.cs" />
<p>
In the example below <code>System.Web.HttpCookie.Secure</code> is set to <code>true</code> programmatically.
</p>
<sample src="secureflag.cs" />
</example>
<references>
<li><a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.cookieoptions.secure">CookieOptions.Secure Property,</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header,</li>
<li><a href="https://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.requiressl(v=vs.110).aspx">FormsAuthentication.RequireSSL Property,</a></li>
<li><a href="https://msdn.microsoft.com/en-us/library/1d3t3c61(v=vs.100).aspx">forms Element for authentication,</a></li>
<li><a href="https://msdn.microsoft.com/library/ms228262%28v=vs.100%29.aspx">httpCookies Element,</a></li>
</references>
</qhelp>

View File

@@ -1,107 +0,0 @@
/**
* @name 'Secure' attribute is not set to true
* @description Omitting the 'Secure' attribute allows data to be transmitted insecurely
* using HTTP. Always set 'Secure' to 'true' to ensure that HTTPS
* is used at all times.
* @kind problem
* @problem.severity error
* @precision high
* @id cs/web/cookie-secure-not-set
* @tags security
* experimental
* external/cwe/cwe-319
* external/cwe/cwe-614
*/
import csharp
import semmle.code.asp.WebConfig
import semmle.code.csharp.frameworks.system.Web
import semmle.code.csharp.frameworks.microsoft.AspNetCore
deprecated import experimental.dataflow.flowsources.AuthCookie
deprecated query predicate problems(Expr secureSink, string message) {
(
exists(Call c |
secureSink = c and
(
// default is not configured or is not set to `Always` or `SameAsRequest`
not (
getAValueForCookiePolicyProp("Secure").getValue() = "0" or
getAValueForCookiePolicyProp("Secure").getValue() = "1"
) and
// there is no callback `OnAppendCookie` that sets `Secure` to true
not OnAppendCookieSecureTracking::flowTo(_) and
(
// `Secure` property in `CookieOptions` passed to IResponseCookies.Append(...) wasn't set
exists(ObjectCreation oc |
oc = c and
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
not isPropertySet(oc, "Secure") and
exists(DataFlow::Node creation |
CookieOptionsTracking::flow(creation, _) and
creation.asExpr() = oc
)
)
or
// IResponseCookies.Append(String, String) was called, `Secure` is set to `false` by default
exists(MethodCall mc, MicrosoftAspNetCoreHttpResponseCookies iResponse |
mc = c and
iResponse.getAppendMethod() = mc.getTarget() and
mc.getNumberOfArguments() < 3
)
)
or
exists(ObjectCreation oc |
oc = c and
oc.getType() instanceof SystemWebHttpCookie and
// the property wasn't explicitly set, so a default value from config is used
not isPropertySet(oc, "Secure") and
// the default in config is not set to `true`
// the `exists` below covers the `cs/web/requiressl-not-set`
not exists(XmlElement element |
element instanceof FormsElement and
element.(FormsElement).isRequireSsl()
or
element instanceof HttpCookiesElement and
element.(HttpCookiesElement).isRequireSsl()
)
)
)
)
or
exists(Assignment a, Expr val |
secureSink = a.getRValue() and
(
exists(ObjectCreation oc |
getAValueForProp(oc, a, "Secure") = val and
val.getValue() = "false" and
(
oc.getType() instanceof SystemWebHttpCookie
or
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
// there is no callback `OnAppendCookie` that sets `Secure` to true
not OnAppendCookieSecureTracking::flowTo(_) and
// the cookie option is passed to `Append`
exists(DataFlow::Node creation |
CookieOptionsTracking::flow(creation, _) and
creation.asExpr() = oc
)
)
)
or
exists(PropertyWrite pw |
(
pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieBuilder or
pw.getProperty().getDeclaringType() instanceof
MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions
) and
pw.getProperty().getName() = "SecurePolicy" and
a.getLValue() = pw and
DataFlow::localExprFlow(val, a.getRValue()) and
val.getValue() = "2" // None
)
)
)
) and
message = "Cookie attribute 'Secure' is not set to true."
}

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<authentication>
<forms
requireSSL="true"
... />
</authentication>
<httpCookies
requireSSL="true"
... />
</system.web>
</configuration>

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1,4 +0,0 @@
| Program.cs:25:34:25:38 | false | Cookie attribute 'HttpOnly' is not set to true. |
| Program.cs:38:88:38:92 | false | Cookie attribute 'HttpOnly' is not set to true. |
| Program.cs:61:34:61:34 | access to local variable v | Cookie attribute 'HttpOnly' is not set to true. |
| Program.cs:68:88:68:88 | access to local variable v | Cookie attribute 'HttpOnly' is not set to true. |

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1,37 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
public class MyController : Microsoft.AspNetCore.Mvc.Controller
{
public void CookieDefault()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
cookieOptions.HttpOnly = false;
Response.Cookies.Append("auth", "secret", cookieOptions); // GOOD: HttpOnly is set in callback
}
}
public class Startup
{
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCookiePolicy();
}
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.OnAppendCookie = cookieContext => SetCookies(cookieContext.CookieOptions);
});
}
private void SetCookies(CookieOptions options)
{
options.Secure = true;
options.HttpOnly = true;
}
}

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj

View File

@@ -1,4 +0,0 @@
| Program.cs:23:27:23:31 | false | Cookie attribute 'HttpOnly' is not set to true. |
| Program.cs:28:74:28:78 | false | Cookie attribute 'HttpOnly' is not set to true. |
| Program.cs:48:27:48:27 | access to local variable v | Cookie attribute 'HttpOnly' is not set to true. |
| Program.cs:54:74:54:74 | access to local variable v | Cookie attribute 'HttpOnly' is not set to true. |

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs

View File

@@ -1,2 +0,0 @@
| Program.cs:5:9:5:49 | call to method Append | Cookie attribute 'HttpOnly' is not set to true. |
| Program.cs:15:29:15:73 | object creation of type CookieOptions | Cookie attribute 'HttpOnly' is not set to true. |

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1,52 +0,0 @@
public class MyController : Microsoft.AspNetCore.Mvc.Controller
{
public void CookieDefault()
{
Response.Cookies.Append("auth", "secret"); // BAD: HttpOnly is set to false by default
}
public void CookieDefaultForgery()
{
Response.Cookies.Append("antiforgerytoken", "secret"); // GOOD: not an auth cookie
}
public void CookieDefault2()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
Response.Cookies.Append("auth", "secret", cookieOptions); // BAD: HttpOnly is set to false by default
}
public void CookieDelete()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
Response.Cookies.Delete("auth", cookieOptions); // GOOD: Delete call
}
void CookieDirectTrue()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
cookieOptions.HttpOnly = true;
Response.Cookies.Append("auth", "secret", cookieOptions); // GOOD
}
void CookieDirectTrueInitializer()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { HttpOnly = true };
Response.Cookies.Append("auth", "secret", cookieOptions); // GOOD
}
void CookieIntermediateTrue()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
bool v = true;
cookieOptions.HttpOnly = v;
Response.Cookies.Append("auth", "secret", cookieOptions); // GOOD: should track local data flow
}
void CookieIntermediateTrueInitializer()
{
bool v = true;
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { HttpOnly = v };
Response.Cookies.Append("auth", "secret", cookieOptions); // GOOD: should track local data flow
}
}

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj

View File

@@ -1 +0,0 @@
| Program.cs:5:22:5:59 | object creation of type HttpCookie | Cookie attribute 'HttpOnly' is not set to true. |

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1,36 +0,0 @@
class Program
{
void CookieDefault()
{
var cookie = new System.Web.HttpCookie("sessionID"); // BAD: httpOnlyCookies is set to false by default
}
void CookieDefaultForgery()
{
var cookie = new System.Web.HttpCookie("anticsrftoken"); // GOOD: not an auth cookie
}
void CookieDirectTrue()
{
var cookie = new System.Web.HttpCookie("sessionID");
cookie.HttpOnly = true; // GOOD
}
void CookieDirectTrueInitializer()
{
var cookie = new System.Web.HttpCookie("sessionID") { HttpOnly = true }; // GOOD
}
void CookieIntermediateTrue()
{
var cookie = new System.Web.HttpCookie("sessionID");
bool v = true;
cookie.HttpOnly = v; // GOOD: should track local data flow
}
void CookieIntermediateTrueInitializer()
{
bool v = true;
var cookie = new System.Web.HttpCookie("sessionID") { HttpOnly = v }; // GOOD: should track local data flow
}
}

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs

View File

@@ -1 +0,0 @@
| Program.cs:5:22:5:59 | object creation of type HttpCookie | Cookie attribute 'HttpOnly' is not set to true. |

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1,36 +0,0 @@
class Program
{
void CookieDefault()
{
var cookie = new System.Web.HttpCookie("sessionID"); // BAD: httpOnlyCookies is set to false in config
}
void CookieDefaultForgery()
{
var cookie = new System.Web.HttpCookie("anticsrftoken"); // GOOD: not an auth cookie
}
void CookieDirectTrue()
{
var cookie = new System.Web.HttpCookie("sessionID");
cookie.HttpOnly = true; // GOOD
}
void CookieDirectTrueInitializer()
{
var cookie = new System.Web.HttpCookie("sessionID") { HttpOnly = true }; // GOOD
}
void CookieIntermediateTrue()
{
var cookie = new System.Web.HttpCookie("sessionID");
bool v = true;
cookie.HttpOnly = v; // GOOD: should track local data flow
}
void CookieIntermediateTrueInitializer()
{
bool v = true;
var cookie = new System.Web.HttpCookie("sessionID") { HttpOnly = v }; // GOOD: should track local data flow
}
}

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<httpCookies httpOnlyCookies="false" />
</system.web>
</configuration>

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1,36 +0,0 @@
class Program
{
void CookieDefault()
{
var cookie = new System.Web.HttpCookie("sessionID"); // GOOD: httpOnlyCookies is set to true in config
}
void CookieDefaultForgery()
{
var cookie = new System.Web.HttpCookie("anticsrftoken"); // GOOD: not an auth cookie
}
void CookieDirectTrue()
{
var cookie = new System.Web.HttpCookie("sessionID");
cookie.HttpOnly = true; // GOOD
}
void CookieDirectTrueInitializer()
{
var cookie = new System.Web.HttpCookie("sessionID") { HttpOnly = true }; // GOOD
}
void CookieIntermediateTrue()
{
var cookie = new System.Web.HttpCookie("sessionID");
bool v = true;
cookie.HttpOnly = v; // GOOD: should track local data flow
}
void CookieIntermediateTrueInitializer()
{
bool v = true;
var cookie = new System.Web.HttpCookie("sessionID") { HttpOnly = v }; // GOOD: should track local data flow
}
}

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<httpCookies httpOnlyCookies="true" />
</system.web>
</configuration>

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs

View File

@@ -1,47 +0,0 @@
public class MyController : Microsoft.AspNetCore.Mvc.Controller
{
public void CookieDefault()
{
Response.Cookies.Append("name", "value"); // BAD: requireSSL is set to false by default
}
public void CookieDefault2()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
Response.Cookies.Append("name", "value", cookieOptions); // BAD: requireSSL is set to false by default
}
public void CookieDelete()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
Response.Cookies.Delete("name", cookieOptions); // GOOD: Delete call
}
void CookieDirectTrue()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
cookieOptions.Secure = true;
Response.Cookies.Append("auth", "secret", cookieOptions); // GOOD
}
void CookieDirectTrueInitializer()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { Secure = true };
Response.Cookies.Append("auth", "secret", cookieOptions); // GOOD
}
void CookieIntermediateTrue()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
bool v = true;
cookieOptions.Secure = v;
Response.Cookies.Append("auth", "secret", cookieOptions); // GOOD: should track local data flow
}
void CookieIntermediateTrueInitializer()
{
bool v = true;
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { Secure = v };
Response.Cookies.Append("auth", "secret", cookieOptions); // GOOD: should track local data flow
}
}

View File

@@ -1,2 +0,0 @@
| Program.cs:5:9:5:48 | call to method Append | Cookie attribute 'Secure' is not set to true. |
| Program.cs:10:29:10:73 | object creation of type CookieOptions | Cookie attribute 'Secure' is not set to true. |

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-614/CookieWithoutSecure.ql

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-614/CookieWithoutSecure.ql

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-614/CookieWithoutSecure.ql

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-614/CookieWithoutSecure.ql

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-614/CookieWithoutSecure.ql

View File

@@ -1,4 +0,0 @@
| Program.cs:25:32:25:36 | false | Cookie attribute 'Secure' is not set to true. |
| Program.cs:31:86:31:90 | false | Cookie attribute 'Secure' is not set to true. |
| Program.cs:54:32:54:32 | access to local variable v | Cookie attribute 'Secure' is not set to true. |
| Program.cs:61:86:61:86 | access to local variable v | Cookie attribute 'Secure' is not set to true. |

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-614/CookieWithoutSecure.ql

View File

@@ -1,37 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
public class MyController : Microsoft.AspNetCore.Mvc.Controller
{
public void CookieDefault()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
cookieOptions.Secure = false;
Response.Cookies.Append("auth", "secret", cookieOptions); // GOOD: Secure is set in callback
}
}
public class Startup
{
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCookiePolicy();
}
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.OnAppendCookie = cookieContext => SetCookies(cookieContext.CookieOptions);
});
}
private void SetCookies(CookieOptions options)
{
options.Secure = true;
options.HttpOnly = true;
}
}

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-614/CookieWithoutSecure.ql

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj

View File

@@ -1,4 +0,0 @@
| Program.cs:17:25:17:29 | false | Cookie attribute 'Secure' is not set to true. |
| Program.cs:22:73:22:77 | false | Cookie attribute 'Secure' is not set to true. |
| Program.cs:42:25:42:25 | access to local variable v | Cookie attribute 'Secure' is not set to true. |
| Program.cs:48:73:48:73 | access to local variable v | Cookie attribute 'Secure' is not set to true. |

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-614/CookieWithoutSecure.ql

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<httpCookies />
</system.web>
</configuration>

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs

View File

@@ -1,31 +0,0 @@
class Program
{
void CookieDefault()
{
var cookie = new System.Web.HttpCookie("cookieName"); // BAD: requireSSL is set to false by default
}
void CookieDirectTrue()
{
var cookie = new System.Web.HttpCookie("cookieName");
cookie.Secure = true; // GOOD
}
void CookieDirectTrueInitializer()
{
var cookie = new System.Web.HttpCookie("cookieName") { Secure = true }; // GOOD
}
void CookieIntermediateTrue()
{
var cookie = new System.Web.HttpCookie("cookieName");
bool v = true;
cookie.Secure = v; // GOOD: should track local data flow
}
void CookieIntermediateTrueInitializer()
{
bool v = true;
var cookie = new System.Web.HttpCookie("cookieName") { Secure = v }; // GOOD: should track local data flow
}
}

View File

@@ -1 +0,0 @@
| Program.cs:5:22:5:60 | object creation of type HttpCookie | Cookie attribute 'Secure' is not set to true. |

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-614/CookieWithoutSecure.ql

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs

View File

@@ -1,31 +0,0 @@
class Program
{
void CookieDefault()
{
var cookie = new System.Web.HttpCookie("cookieName"); // BAD: requireSSL is set to false in config
}
void CookieDirectTrue()
{
var cookie = new System.Web.HttpCookie("cookieName");
cookie.Secure = true; // GOOD
}
void CookieDirectTrueInitializer()
{
var cookie = new System.Web.HttpCookie("cookieName") { Secure = true }; // GOOD
}
void CookieIntermediateTrue()
{
var cookie = new System.Web.HttpCookie("cookieName");
bool v = true;
cookie.Secure = v; // GOOD: should track local data flow
}
void CookieIntermediateTrueInitializer()
{
bool v = true;
var cookie = new System.Web.HttpCookie("cookieName") { Secure = v }; // GOOD: should track local data flow
}
}

View File

@@ -1 +0,0 @@
| Program.cs:5:22:5:60 | object creation of type HttpCookie | Cookie attribute 'Secure' is not set to true. |

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-614/CookieWithoutSecure.ql

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs

View File

@@ -1,31 +0,0 @@
class Program
{
void CookieDefault()
{
var cookie = new System.Web.HttpCookie("cookieName"); // GOOD: requireSSL is set to true in config
}
void CookieDirectTrue()
{
var cookie = new System.Web.HttpCookie("cookieName");
cookie.Secure = true; // GOOD
}
void CookieDirectTrueInitializer()
{
var cookie = new System.Web.HttpCookie("cookieName") { Secure = true }; // GOOD
}
void CookieIntermediateTrue()
{
var cookie = new System.Web.HttpCookie("cookieName");
bool v = true;
cookie.Secure = v; // GOOD: should track local data flow
}
void CookieIntermediateTrueInitializer()
{
bool v = true;
var cookie = new System.Web.HttpCookie("cookieName") { Secure = v }; // GOOD: should track local data flow
}
}

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-614/CookieWithoutSecure.ql

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs

View File

@@ -1,31 +0,0 @@
class Program
{
void CookieDefault()
{
var cookie = new System.Web.HttpCookie("cookieName"); // GOOD: requireSSL is set to true in config
}
void CookieDirectTrue()
{
var cookie = new System.Web.HttpCookie("cookieName");
cookie.Secure = true; // GOOD
}
void CookieDirectTrueInitializer()
{
var cookie = new System.Web.HttpCookie("cookieName") { Secure = true }; // GOOD
}
void CookieIntermediateTrue()
{
var cookie = new System.Web.HttpCookie("cookieName");
bool v = true;
cookie.Secure = v; // GOOD: should track local data flow
}
void CookieIntermediateTrueInitializer()
{
bool v = true;
var cookie = new System.Web.HttpCookie("cookieName") { Secure = v }; // GOOD: should track local data flow
}
}

View File

@@ -1 +0,0 @@
experimental/Security Features/CWE-614/CookieWithoutSecure.ql

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs

View File

@@ -0,0 +1,2 @@
query: Security Features/CWE-1004/CookieWithoutHttpOnly.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -10,14 +10,14 @@ public class Startup
{ {
services.AddAuthentication().AddCookie(o => services.AddAuthentication().AddCookie(o =>
{ {
o.Cookie.HttpOnly = false; o.Cookie.HttpOnly = false; // $ Alert
o.Cookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.None; o.Cookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.None;
}); });
services.AddSession(options => services.AddSession(options =>
{ {
options.Cookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.None; options.Cookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.None;
options.Cookie.HttpOnly = false; options.Cookie.HttpOnly = false; // $ Alert
}); });
} }
} }

View File

@@ -0,0 +1,4 @@
| Program.cs:5:9:5:48 | call to method Append | Cookie attribute 'HttpOnly' is not set to true. |
| Program.cs:10:29:10:73 | object creation of type CookieOptions | Cookie attribute 'HttpOnly' is not set to true. |
| Program.cs:42:29:42:73 | object creation of type CookieOptions | Cookie attribute 'HttpOnly' is not set to true. |
| Program.cs:49:29:49:94 | object creation of type CookieOptions | Cookie attribute 'HttpOnly' is not set to true. |

View File

@@ -0,0 +1,2 @@
query: Security Features/CWE-1004/CookieWithoutHttpOnly.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,11 +1,29 @@
public class MyController : Microsoft.AspNetCore.Mvc.Controller public class MyController : Microsoft.AspNetCore.Mvc.Controller
{ {
public void CookieDefault()
{
Response.Cookies.Append("auth", "value"); // $Alert // BAD: HttpOnly is set to false by default
}
public void CookieDefault2()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $Alert
Response.Cookies.Append("auth", "value", cookieOptions); // BAD: HttpOnly is set to false by default
}
public void CookieDelete() public void CookieDelete()
{ {
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
Response.Cookies.Delete("auth", cookieOptions); // GOOD: Delete call Response.Cookies.Delete("auth", cookieOptions); // GOOD: Delete call
} }
void CookieDirectFalseForgery()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
cookieOptions.HttpOnly = false;
Response.Cookies.Append("antiforgerytoken", "secret", cookieOptions); // GOOD: not an auth cookie
}
void CookieDirectTrue() void CookieDirectTrue()
{ {
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
@@ -21,21 +39,14 @@ public class MyController : Microsoft.AspNetCore.Mvc.Controller
void CookieDirectFalse() void CookieDirectFalse()
{ {
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $Alert
cookieOptions.HttpOnly = false; cookieOptions.HttpOnly = false;
Response.Cookies.Append("auth", "secret", cookieOptions); // BAD Response.Cookies.Append("auth", "secret", cookieOptions); // BAD
} }
void CookieDirectFalseForgery()
{
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
cookieOptions.HttpOnly = false;
Response.Cookies.Append("antiforgerytoken", "secret", cookieOptions); // GOOD: not an auth cookie
}
void CookieDirectFalseInitializer() void CookieDirectFalseInitializer()
{ {
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { HttpOnly = false }; var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { HttpOnly = false }; // $Alert
Response.Cookies.Append("auth", "secret", cookieOptions); // BAD Response.Cookies.Append("auth", "secret", cookieOptions); // BAD
} }
@@ -56,16 +67,16 @@ public class MyController : Microsoft.AspNetCore.Mvc.Controller
void CookieIntermediateFalse() void CookieIntermediateFalse()
{ {
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $MISSING:Alert
bool v = false; bool v = false;
cookieOptions.HttpOnly = v; cookieOptions.HttpOnly = v;
Response.Cookies.Append("auth", "secret", cookieOptions); // BAD Response.Cookies.Append("auth", "secret", cookieOptions); // BAD, but not detected
} }
void CookieIntermediateFalseInitializer() void CookieIntermediateFalseInitializer()
{ {
bool v = false; bool v = false;
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { HttpOnly = v }; var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { HttpOnly = v }; // $MISSING:Alert
Response.Cookies.Append("auth", "secret", cookieOptions); // BAD Response.Cookies.Append("auth", "secret", cookieOptions); // BAD, but not detected
} }
} }

View File

@@ -0,0 +1,2 @@
query: Security Features/CWE-1004/CookieWithoutHttpOnly.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -20,6 +20,6 @@ public class Startup
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{ {
app.UseCookiePolicy(new CookiePolicyOptions() { HttpOnly = Microsoft.AspNetCore.CookiePolicy.HttpOnlyPolicy.Always}); app.UseCookiePolicy(new CookiePolicyOptions() { HttpOnly = Microsoft.AspNetCore.CookiePolicy.HttpOnlyPolicy.Always });
} }
} }

View File

@@ -0,0 +1,2 @@
query: Security Features/CWE-1004/CookieWithoutHttpOnly.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -6,6 +6,11 @@ using Microsoft.AspNetCore.Http;
public class MyController : Microsoft.AspNetCore.Mvc.Controller public class MyController : Microsoft.AspNetCore.Mvc.Controller
{ {
public void CookieDefault() public void CookieDefault()
{
Response.Cookies.Append("auth", "secret"); // GOOD: HttpOnly is set in callback
}
public void CookieDefault2()
{ {
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions();
Response.Cookies.Append("auth", "secret", cookieOptions); // GOOD: HttpOnly is set in callback Response.Cookies.Append("auth", "secret", cookieOptions); // GOOD: HttpOnly is set in callback

View File

@@ -0,0 +1,2 @@
query: Security Features/CWE-1004/CookieWithoutHttpOnly.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

Some files were not shown because too many files have changed in this diff Show More