Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 93750fe

Browse files
committed
python: minimal CSRF implementation
- currectly only looks for custom django middleware
1 parent 3fc2f2f commit 93750fe

5 files changed

Lines changed: 150 additions & 0 deletions

File tree

python/ql/lib/semmle/python/Concepts.qll

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,37 @@ module FileSystemWriteAccess {
105105
}
106106
}
107107

108+
/**
109+
* A data-flow node that may set or unset Cross-site request forgery protection.
110+
*
111+
* Extend this class to refine existing API models. If you want to model new APIs,
112+
* extend `CSRFProtectionSetting::Range` instead.
113+
*/
114+
class CSRFProtectionSetting extends DataFlow::Node instanceof CSRFProtectionSetting::Range {
115+
/**
116+
* Gets the boolean value corresponding to if CSRF protection is enabled
117+
* (`true`) or disabled (`false`) by this node.
118+
*/
119+
boolean getVerificationSetting() { result = super.getVerificationSetting() }
120+
}
121+
122+
/** Provides a class for modeling new CSRF protection setting APIs. */
123+
module CSRFProtectionSetting {
124+
/**
125+
* A data-flow node that may set or unset Cross-site request forgery protection.
126+
*
127+
* Extend this class to model new APIs. If you want to refine existing API models,
128+
* extend `CSRFProtectionSetting` instead.
129+
*/
130+
abstract class Range extends DataFlow::Node {
131+
/**
132+
* Gets the boolean value corresponding to if CSRF protection is enabled
133+
* (`true`) or disabled (`false`) by this node.
134+
*/
135+
abstract boolean getVerificationSetting();
136+
}
137+
}
138+
108139
/** Provides classes for modeling path-related APIs. */
109140
module Path {
110141
/**

python/ql/lib/semmle/python/frameworks/Django.qll

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2313,4 +2313,35 @@ module PrivateDjango {
23132313
.getAnImmediateUse()
23142314
}
23152315
}
2316+
2317+
// ---------------------------------------------------------------------------
2318+
// Settings
2319+
// ---------------------------------------------------------------------------
2320+
/**
2321+
* A custom middleware stack
2322+
*/
2323+
private class DjangoSettingsMiddlewareStack extends CSRFProtectionSetting::Range {
2324+
List list;
2325+
2326+
DjangoSettingsMiddlewareStack() {
2327+
this.asExpr() = list and
2328+
// we look for an assignment to the `MIDDLEWARE` setting
2329+
exists(DataFlow::Node mw, string djangomw |
2330+
mw.asVar().getName() = "MIDDLEWARE" and
2331+
DataFlow::localFlow(this, mw)
2332+
|
2333+
// check that the list contains at least one reference to `django`
2334+
list.getAnElt().(StrConst).getText() = djangomw and
2335+
// TODO: Consider requiring `django.middleware.security.SecurityMiddleware`
2336+
// or something indicating that a security middleware is enabled.
2337+
djangomw.matches("django.%")
2338+
)
2339+
}
2340+
2341+
override boolean getVerificationSetting() {
2342+
if list.getAnElt().(StrConst).getText() = "django.middleware.csrf.CsrfViewMiddleware"
2343+
then result = true
2344+
else result = false
2345+
}
2346+
}
23162347
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
<overview>
7+
<p>
8+
Cross-site request forgery (CSRF) is a type of vulnerability in which an
9+
attacker is able to force a user carry out an action that the user did
10+
not intend.
11+
</p>
12+
13+
<p>
14+
The attacker tricks an authenticated user into submitting a request to the
15+
web application. Typically this request will result in a state change on
16+
the server, such as changing the user's password. The request can be
17+
initiated when the user visits a site controlled by the attacker. If the
18+
web application relies only on cookies for authentication, or on other
19+
credentials that are automatically included in the request, then this
20+
request will appear as legitimate to the server.
21+
</p>
22+
23+
<p>
24+
A common countermeasure for CSRF is to generate a unique token to be
25+
included in the HTML sent from the server to a user. This token can be
26+
used as a hidden field to be sent back with requests to the server, where
27+
the server can then check that the token is valid and associated with the
28+
relevant user session.
29+
</p>
30+
</overview>
31+
32+
<recommendation>
33+
<p>
34+
In many web frameworks, CSRF protection is enabled by default. In these
35+
cases, using the default configuration is sufficient to guard against most
36+
CSRF attacks.
37+
</p>
38+
</recommendation>
39+
40+
<example>
41+
<p>
42+
The following example shows a case where CSRF protection is disabled by
43+
overriding the default middleware stack and not including the one protecting against CSRF.
44+
</p>
45+
46+
<sample src="examples/settings.py"/>
47+
48+
<p>
49+
The protecting middleware was probably commented out during a testing phase, when server-side token generation was not set up.
50+
Simply commenting it back in (or remove the custom middleware stack) will enable CSRF protection.
51+
</p>
52+
53+
</example>
54+
55+
<references>
56+
<li>Wikipedia: <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery">Cross-site request forgery</a></li>
57+
<li>OWASP: <a href="https://owasp.org/www-community/attacks/csrf">Cross-site request forgery</a></li>
58+
</references>
59+
60+
</qhelp>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @name CSRF protection weakened or disabled
3+
* @description Disabling or weakening CSRF protection may make the application
4+
* vulnerable to a Cross-Site Request Forgery (CSRF) attack.
5+
* @kind problem
6+
* @problem.severity warning
7+
* @security-severity 8.8
8+
* @precision high
9+
* @id py/csrf-protection-disabled
10+
* @tags security
11+
* external/cwe/cwe-352
12+
*/
13+
14+
import python
15+
import semmle.python.Concepts
16+
17+
from CSRFProtectionSetting s
18+
where s.getVerificationSetting() = false
19+
select s, "Potential CSRF vulnerability due to forgery protection being disabled or weakened."
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
MIDDLEWARE = [
2+
'django.middleware.security.SecurityMiddleware',
3+
'django.contrib.sessions.middleware.SessionMiddleware',
4+
'django.middleware.common.CommonMiddleware',
5+
# 'django.middleware.csrf.CsrfViewMiddleware',
6+
'django.contrib.auth.middleware.AuthenticationMiddleware',
7+
'django.contrib.messages.middleware.MessageMiddleware',
8+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
9+
]

0 commit comments

Comments
 (0)