Polish documentation.

This commit is contained in:
jorgectf
2021-11-05 21:05:33 +01:00
parent ed74bd6800
commit 83e3de1fed
5 changed files with 68 additions and 6 deletions

View File

@@ -1,10 +1,9 @@
/**
* @name Failure to use secure cookies
* @description Insecure cookies may be sent in cleartext, which makes them vulnerable to
* interception.
* @name Construction of a cookie using user-supplied input.
* @description Constructing cookies from user input may allow an attacker to perform a Cookie Poisoning attack.
* @kind problem
* @problem.severity error
* @id py/insecure-cookie
* @id py/cookie-injection
* @tags security
* external/cwe/cwe-614
*/

View File

@@ -4,12 +4,17 @@
<qhelp>
<overview>
<p>Failing to set the 'secure' flag on a cookie can cause it to be sent in cleartext.
This makes it easier for an attacker to intercept.</p>
<p>Setting the 'secure' flag on a cookie to <code>False</code> can cause it to be sent in cleartext.
Setting the 'httponly' flag on a cookie to <code>False</code> may allow attackers access it via JavaScript.
Setting the 'samesite' flag on a cookie to <code>'None'</code> will make the cookie to be sent in third-party
contexts which may be attacker-controlled.</p>
</overview>
<recommendation>
<p>Always set <code>secure</code> to <code>True</code> or add "; Secure;" to the cookie's raw value.</p>
<p>Always set <code>httponly</code> to <code>True</code> or add "; HttpOnly;" to the cookie's raw value.</p>
<p>Always set <code>samesite</code> to <code>Lax</code> or <code>Strict</code>, or add "; SameSite=Lax;", or
"; Samesite=Strict;" to the cookie's raw header value.</p>
</recommendation>
<example>

View File

@@ -7,6 +7,25 @@ import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import experimental.semmle.python.Concepts
/**
* Gets a header setting a cookie.
*
* Given the following example:
*
* ```py
* @app.route("/")
* def flask_make_response():
* resp = make_response("")
* resp.headers['Set-Cookie'] = "name=value; Secure;"
* return resp
* ```
*
* * `this` would be `resp.headers['Set-Cookie'] = "name=value; Secure;"`.
* * `isSecure()` predicate would succeed.
* * `isHttpOnly()` predicate would fail.
* * `isSameSite()` predicate would fail.
* * `getName()` and `getValue()` results would be `"name=value; Secure;"`.
*/
class CookieHeader extends HeaderDeclaration, Cookie::Range {
CookieHeader() {
this instanceof HeaderDeclaration and

View File

@@ -87,6 +87,25 @@ private module PrivateDjango {
override DataFlow::Node getValueArg() { result = headerInput }
}
/**
* Gets a call to `set_cookie()`.
*
* Given the following example:
*
* ```py
* def django_response(request):
* resp = django.http.HttpResponse()
* resp.set_cookie("name", "value", secure=True, httponly=True, samesite='Lax')
* return resp
* ```
*
* * `this` would be `resp.set_cookie("name", "value", secure=False, httponly=False, samesite='None')`.
* * `getName()`'s result would be `"name"`.
* * `getValue()`'s result would be `"value"`.
* * `isSecure()` predicate would succeed.
* * `isHttpOnly()` predicate would succeed.
* * `isSameSite()` predicate would succeed.
*/
class DjangoSetCookieCall extends DataFlow::CallCfgNode, Cookie::Range {
DjangoSetCookieCall() { this = baseClassRef().getMember("set_cookie").getACall() }

View File

@@ -82,6 +82,26 @@ module ExperimentalFlask {
override DataFlow::Node getValueArg() { result.asExpr() = item.getValue() }
}
/**
* Gets a call to `set_cookie()`.
*
* Given the following example:
*
* ```py
* @app.route("/")
* def false():
* resp = make_response()
* resp.set_cookie("name", value="value", secure=True, httponly=True, samesite='Lax')
* return resp
* ```
*
* * `this` would be `resp.set_cookie("name", value="value", secure=False, httponly=False, samesite='None')`.
* * `getName()`'s result would be `"name"`.
* * `getValue()`'s result would be `"value"`.
* * `isSecure()` predicate would succeed.
* * `isHttpOnly()` predicate would succeed.
* * `isSameSite()` predicate would succeed.
*/
class FlaskSetCookieCall extends DataFlow::CallCfgNode, Cookie::Range {
FlaskSetCookieCall() {
this =