Skip to content

Commit 89c4102

Browse files
author
edvraa
committed
HttpOnly and Secure cookie queries
1 parent 1d56748 commit 89c4102

File tree

115 files changed

+2720
-23
lines changed

Some content is hidden

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

115 files changed

+2720
-23
lines changed

csharp/ql/src/Security Features/CWE-614/RequireSSL.ql

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,6 @@ import csharp
1717
import semmle.code.asp.WebConfig
1818
import semmle.code.csharp.frameworks.system.Web
1919

20-
class FormsElement extends XMLElement {
21-
FormsElement() {
22-
this = any(SystemWebXMLElement sw).getAChild("authentication").getAChild("forms")
23-
}
24-
25-
string getRequireSSL() { result = getAttribute("requireSSL").getValue().trim().toLowerCase() }
26-
27-
predicate isRequireSSL() { getRequireSSL() = "true" }
28-
}
29-
30-
class HttpCookiesElement extends XMLElement {
31-
HttpCookiesElement() { this = any(SystemWebXMLElement sw).getAChild("httpCookies") }
32-
33-
string getRequireSSL() { result = getAttribute("requireSSL").getValue().trim().toLowerCase() }
34-
35-
predicate isRequireSSL() {
36-
getRequireSSL() = "true"
37-
or
38-
not getRequireSSL() = "false" and
39-
exists(FormsElement forms | forms.getFile() = getFile() | forms.isRequireSSL())
40-
}
41-
}
42-
4320
from XMLElement element
4421
where
4522
element instanceof FormsElement and
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
<overview>
7+
<p>
8+
Cookies without <code>HttpOnly</code> flag are accessible to JavaScript running in the same origin. In case of
9+
Cross-Site Scripting (XSS) vulnerability the cookie can be stolen by malicious script. By explicitly setting <code>HttpOnly</code>
10+
property to <code>false</code> the cookie may be accessed by JavaScript.
11+
</p>
12+
</overview>
13+
14+
<recommendation>
15+
<p>
16+
Protect sensitive cookies, such as related to authentication, by setting <code>HttpOnly</code> to <code>true</code> to make
17+
them not accessibe to JavaScript.
18+
</p>
19+
</recommendation>
20+
21+
<example>
22+
23+
<p>
24+
In the example below to <code>Microsoft.AspNetCore.Http.CookieOptions.HttpOnly</code> is set to <code>true</code>.
25+
</p>
26+
27+
<sample src="httponlyflagcore.cs" />
28+
29+
<p>
30+
In the following example <code>CookiePolicyOptions</code> are set programmatically to configure defaults.
31+
</p>
32+
33+
<sample src="cookiepolicyoptions.cs" />
34+
35+
</example>
36+
37+
<references>
38+
39+
<li>MSDN: <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.cookieoptions.httponly">CookieOptions.HttpOnly Property</a></li>
40+
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header</li>
41+
42+
</references>
43+
</qhelp>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* @name 'HttpOnly' attribute is set to false
3+
* @description Setting 'HttpOnly' attribute to false for security sensitive data allows
4+
* malicious JavaScript to steal it in case of XSS vulnerability. Always set
5+
* 'HttpOnly' to 'true' to authentication related cookie to make it
6+
* not accessible by JavaScript.
7+
* @kind problem
8+
* @problem.severity warning
9+
* @precision high
10+
* @id cs/web/cookie-httponly-false-aspnetcore
11+
* @tags security
12+
* external/cwe/cwe-1004
13+
*/
14+
15+
import csharp
16+
import semmle.code.csharp.frameworks.microsoft.AspNetCore
17+
import semmle.code.csharp.dataflow.flowsources.AuthCookie
18+
19+
from Expr val, Assignment a
20+
where
21+
exists(ObjectCreation oc, MethodCall mc, MicrosoftAspNetCoreHttpResponseCookies iResponse |
22+
iResponse.getAppendMethod() = mc.getTarget() and
23+
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
24+
getAValueForProp(oc, a, "HttpOnly") = val and
25+
val.getValue() = "false" and
26+
// there is no callback `OnAppendCookie` that sets `HttpOnly` to true
27+
not exists(
28+
OnAppendCookieHttpOnlyTrackingConfig config, DataFlow::Node source, DataFlow::Node sink
29+
|
30+
config.hasFlow(source, sink)
31+
) and
32+
// It is a sensitive cookie name
33+
exists(AuthCookieNameConfiguration dataflow, DataFlow::Node source, DataFlow::Node sink |
34+
dataflow.hasFlow(source, sink) and
35+
sink.asExpr() = mc.getArgument(0)
36+
) and
37+
// Passed as third argument to `IResponseCookies.Append`
38+
exists(
39+
CookieOptionsTrackingConfiguration cookieTracking, DataFlow::Node creation,
40+
DataFlow::Node append
41+
|
42+
cookieTracking.hasFlow(creation, append) and
43+
creation.asExpr() = oc and
44+
append.asExpr() = mc.getArgument(2)
45+
)
46+
)
47+
or
48+
exists(PropertyWrite pw |
49+
(
50+
pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieBuilder or
51+
pw.getProperty().getDeclaringType() instanceof
52+
MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions
53+
) and
54+
pw.getProperty().getName() = "HttpOnly" and
55+
a.getLValue() = pw and
56+
DataFlow::localExprFlow(val, a.getRValue()) and
57+
val.getValue() = "false"
58+
)
59+
select a.getRValue(), "Cookie attribute 'HttpOnly' is set to false."
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
<overview>
7+
<p>
8+
Cookies without <code>HttpOnly</code> flag are accessible to JavaScript running in the same origin. In case of
9+
Cross-Site Scripting (XSS) vulnerability the cookie can be stolen by malicious script. By default,
10+
cookies are accessibe to JavaScript. By explicitly setting <code>HttpOnly</code>
11+
property to <code>false</code> the cookie may be accessed by JavaScript.
12+
</p>
13+
</overview>
14+
15+
<recommendation>
16+
17+
<p>
18+
When using cookies, ensure that they are not accessible to JavaScript via <code>&lt;httpCookies&gt;</code> element
19+
with the attribute <code>httpOnlyCookies="true"</code>.
20+
It is also possible to require cookies to use SSL programmatically, by setting the property
21+
<code>System.Web.HttpCookie.HttpOnly</code> to <code>true</code>.
22+
</p>
23+
24+
</recommendation>
25+
26+
<example>
27+
28+
<p>
29+
In the example below to <code>System.Web.HttpCookie.HttpOnly</code> is set to <code>true</code>.
30+
</p>
31+
32+
<sample src="httponlyflag.cs" />
33+
34+
</example>
35+
36+
<references>
37+
38+
<li>MSDN:
39+
<a href="https://msdn.microsoft.com/en-us/library/system.web.httpcookie.httponly(v=vs.110).aspx">HttpCookie.HttpOnly Property</a>,
40+
<a href="https://msdn.microsoft.com/library/ms228262%28v=vs.100%29.aspx">httpCookies Element</a>.
41+
</li>
42+
43+
</references>
44+
</qhelp>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* @name 'HttpOnly' attribute is set to false
3+
* @description Setting 'HttpOnly' attribute to false for security sensitive data allows
4+
* malicious JavaScript to steal it in case of XSS vulnerability. Always set
5+
* 'HttpOnly' to 'true' to authentication related cookie to make it
6+
* not accessible by JavaScript.
7+
* @kind problem
8+
* @problem.severity warning
9+
* @precision high
10+
* @id cs/web/cookie-httponly-false-aspnet
11+
* @tags security
12+
* external/cwe/cwe-1004
13+
*/
14+
15+
import csharp
16+
import semmle.code.csharp.frameworks.system.Web
17+
import semmle.code.csharp.dataflow.flowsources.AuthCookie
18+
19+
from ObjectCreation oc, Expr val, Assignment a
20+
where
21+
getAValueForProp(oc, a, "HttpOnly") = val and
22+
val.getValue() = "false" and
23+
oc.getType() instanceof SystemWebHttpCookie and
24+
// It is a sensitive cookie name
25+
exists(AuthCookieNameConfiguration dataflow, DataFlow::Node source, DataFlow::Node sink |
26+
dataflow.hasFlow(source, sink) and
27+
sink.asExpr() = oc.getArgument(0)
28+
)
29+
select a.getRValue(), "Cookie attribute 'HttpOnly' is set to false."
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
<overview>
7+
<p>
8+
Cookies without <code>HttpOnly</code> flag are accessible to JavaScript running in the same origin. In case of
9+
Cross-Site Scripting (XSS) vulnerability the cookie can be stolen by malicious script.
10+
</p>
11+
</overview>
12+
13+
<recommendation>
14+
<p>
15+
Protect sensitive cookies, such as related to authentication, by setting <code>HttpOnly</code> to <code>true</code> to make
16+
them not accessibe to JavaScript.
17+
</p>
18+
</recommendation>
19+
20+
<example>
21+
22+
<p>
23+
In the example below to <code>Microsoft.AspNetCore.Http.CookieOptions.HttpOnly</code> is set to <code>true</code>.
24+
</p>
25+
26+
<sample src="httponlyflagcore.cs" />
27+
28+
</example>
29+
30+
<references>
31+
32+
<li>MSDN: <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.cookieoptions.httponly">CookieOptions.HttpOnly Property</a></li>
33+
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header</li>
34+
35+
</references>
36+
</qhelp>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* @name 'HttpOnly' attribute is not set to true
3+
* @description Omitting the 'HttpOnly' attribute for security sensitive data allows
4+
* malicious JavaScript to steal it in case of XSS vulnerability. Always set
5+
* 'HttpOnly' to 'true' to authentication related cookie to make it
6+
* not accessible by JavaScript.
7+
* @kind problem
8+
* @problem.severity warning
9+
* @precision medium
10+
* @id cs/web/httponly-possibly-not-set-aspnetcore
11+
* @tags security
12+
* external/cwe/cwe-1004
13+
*/
14+
15+
import csharp
16+
import semmle.code.csharp.frameworks.microsoft.AspNetCore
17+
import semmle.code.csharp.dataflow.flowsources.AuthCookie
18+
19+
from Call c, MicrosoftAspNetCoreHttpResponseCookies iResponse, MethodCall mc
20+
where
21+
// default is not configured or is not set to `Always`
22+
not getAValueForCookiePolicyProp("HttpOnly").getValue() = "1" and
23+
// there is no callback `OnAppendCookie` that sets `HttpOnly` to true
24+
not exists(
25+
OnAppendCookieHttpOnlyTrackingConfig config, DataFlow::Node source, DataFlow::Node sink
26+
|
27+
config.hasFlow(source, sink)
28+
) and
29+
// It is a sensitive cookie name
30+
exists(AuthCookieNameConfiguration dataflow, DataFlow::Node source, DataFlow::Node sink |
31+
iResponse.getAppendMethod() = mc.getTarget() and
32+
dataflow.hasFlow(source, sink) and
33+
sink.asExpr() = mc.getArgument(0)
34+
) and
35+
(
36+
// `HttpOnly` property in `CookieOptions` passed to IResponseCookies.Append(...) wasn't set
37+
exists(ObjectCreation oc |
38+
oc = c and
39+
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
40+
not isPropertySet(oc, "HttpOnly") and
41+
exists(
42+
CookieOptionsTrackingConfiguration cookieTracking, DataFlow::Node creation,
43+
DataFlow::Node append
44+
|
45+
cookieTracking.hasFlow(creation, append) and
46+
creation.asExpr() = oc
47+
)
48+
)
49+
or
50+
// IResponseCookies.Append(String, String) was called, `HttpOnly` is set to `false` by default
51+
exists(AuthCookieNameConfiguration dataflow, DataFlow::Node source, DataFlow::Node sink |
52+
mc = c and
53+
iResponse.getAppendMethod() = mc.getTarget() and
54+
mc.getNumberOfArguments() < 3 and
55+
// It is a sensitive cookie name
56+
dataflow.hasFlow(source, sink) and
57+
sink.asExpr() = mc.getArgument(0)
58+
)
59+
)
60+
select c, "Cookie attribute 'HttpOnly' is not set to true."
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
<overview>
7+
<p>
8+
Cookies without <code>HttpOnly</code> flag are accessible to JavaScript running in the same origin. In case of
9+
Cross-Site Scripting (XSS) vulnerability the cookie can be stolen by malicious script. By default,
10+
cookies are accessibe to JavaScript. This setting can be changed by setting the <code>httpOnlyCookies</code>
11+
attribute to <code>"true"</code> in <code>Web.config</code>.
12+
</p>
13+
</overview>
14+
15+
<recommendation>
16+
17+
<p>
18+
When using cookies, ensure that they are not accessible to JavaScript via <code>&lt;httpCookies&gt;</code> element
19+
with the attribute <code>httpOnlyCookies="true"</code>.
20+
It is also possible to require cookies to use SSL programmatically, by setting the property
21+
<code>System.Web.HttpCookie.HttpOnly</code> to <code>true</code>.
22+
</p>
23+
24+
</recommendation>
25+
26+
<example>
27+
28+
<p>
29+
In the example below to <code>System.Web.HttpCookie.HttpOnly</code> is set to <code>true</code>.
30+
</p>
31+
32+
<sample src="httponlyflag.cs" />
33+
34+
</example>
35+
36+
<references>
37+
38+
<li>MSDN:
39+
<a href="https://msdn.microsoft.com/en-us/library/system.web.httpcookie.httponly(v=vs.110).aspx">HttpCookie.HttpOnly Property</a>,
40+
<a href="https://msdn.microsoft.com/library/ms228262%28v=vs.100%29.aspx">httpCookies Element</a>.
41+
</li>
42+
43+
</references>
44+
</qhelp>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* @name 'HttpOnly' attribute is not set to true
3+
* @description Omitting the 'HttpOnly' attribute for security sensitive data allows
4+
* malicious JavaScript to steal it in case of XSS vulnerability. Always set
5+
* 'HttpOnly' to 'true' to authentication related cookie to make it
6+
* not accessible by JavaScript.
7+
* @kind problem
8+
* @problem.severity warning
9+
* @precision high
10+
* @id cs/web/httponly-not-set-aspnet
11+
* @tags security
12+
* external/cwe/cwe-1004
13+
*/
14+
15+
import csharp
16+
import semmle.code.asp.WebConfig
17+
import semmle.code.csharp.frameworks.system.Web
18+
import semmle.code.csharp.dataflow.flowsources.AuthCookie
19+
20+
from ObjectCreation oc
21+
where
22+
oc.getType() instanceof SystemWebHttpCookie and
23+
// the property wasn't explicitly set, so a default value from config is used
24+
not isPropertySet(oc, "HttpOnly") and
25+
// the default in config is not set to `true`
26+
not exists(XMLElement element |
27+
element instanceof HttpCookiesElement and
28+
element.(HttpCookiesElement).isHttpOnlyCookies()
29+
) and
30+
// it is a cookie with a sensitive name
31+
exists(AuthCookieNameConfiguration dataflow, DataFlow::Node source, DataFlow::Node sink |
32+
dataflow.hasFlow(source, sink) and
33+
sink.asExpr() = oc.getArgument(0)
34+
)
35+
select oc, "Cookie attribute 'HttpOnly' is not set to true."

0 commit comments

Comments
 (0)