Skip to content

Commit ae057c7

Browse files
committed
Python: ORM: Store step for constructor
1 parent f8a51bb commit ae057c7

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,16 @@ module PrivateDjango {
755755
override predicate storeStep(
756756
DataFlow::Node nodeFrom, DataFlow::Content c, DataFlow::Node nodeTo
757757
) {
758-
none()
758+
// attribute value from constructor call -> object created
759+
exists(DataFlow::CallCfgNode call, string fieldName |
760+
// Note: Currently only supports kwargs, which should by far be the most
761+
// common way to do things. We _should_ investigate how often
762+
// positional-args are used.
763+
call = Model::subclassRef().getACall() and
764+
nodeFrom = call.getArgByName(fieldName) and
765+
c.(DataFlow::AttributeContent).getAttribute() = fieldName and
766+
nodeTo = call
767+
)
759768
}
760769

761770
override predicate jumpStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {

python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.expected

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ edges
1818
| testapp/orm_security_tests.py:51:14:51:53 | ControlFlowNode for Attribute() [Attribute age] | testapp/orm_security_tests.py:55:45:55:50 | ControlFlowNode for person [Attribute age] |
1919
| testapp/orm_security_tests.py:55:45:55:50 | ControlFlowNode for person [Attribute age] | testapp/orm_security_tests.py:55:45:55:54 | ControlFlowNode for Attribute |
2020
| testapp/orm_security_tests.py:55:45:55:54 | ControlFlowNode for Attribute | testapp/orm_security_tests.py:55:25:55:55 | ControlFlowNode for Attribute() |
21+
| testapp/orm_security_tests.py:92:1:92:44 | [orm-model] Class CommentValidatorNotUsed [Attribute text] | testapp/orm_security_tests.py:101:15:101:52 | ControlFlowNode for Attribute() [Attribute text] |
22+
| testapp/orm_security_tests.py:95:37:95:43 | ControlFlowNode for request | testapp/orm_security_tests.py:96:44:96:55 | ControlFlowNode for Attribute |
23+
| testapp/orm_security_tests.py:96:15:96:64 | ControlFlowNode for CommentValidatorNotUsed() [Attribute text] | testapp/orm_security_tests.py:97:5:97:11 | ControlFlowNode for comment [Attribute text] |
24+
| testapp/orm_security_tests.py:96:44:96:55 | ControlFlowNode for Attribute | testapp/orm_security_tests.py:96:44:96:63 | ControlFlowNode for Subscript |
25+
| testapp/orm_security_tests.py:96:44:96:63 | ControlFlowNode for Subscript | testapp/orm_security_tests.py:96:15:96:64 | ControlFlowNode for CommentValidatorNotUsed() [Attribute text] |
26+
| testapp/orm_security_tests.py:97:5:97:11 | ControlFlowNode for comment [Attribute text] | testapp/orm_security_tests.py:92:1:92:44 | [orm-model] Class CommentValidatorNotUsed [Attribute text] |
27+
| testapp/orm_security_tests.py:101:15:101:52 | ControlFlowNode for Attribute() [Attribute text] | testapp/orm_security_tests.py:102:25:102:31 | ControlFlowNode for comment [Attribute text] |
28+
| testapp/orm_security_tests.py:102:25:102:31 | ControlFlowNode for comment [Attribute text] | testapp/orm_security_tests.py:102:25:102:36 | ControlFlowNode for Attribute |
29+
| testapp/orm_security_tests.py:111:1:111:41 | [orm-model] Class CommentValidatorUsed [Attribute text] | testapp/orm_security_tests.py:120:15:120:49 | ControlFlowNode for Attribute() [Attribute text] |
30+
| testapp/orm_security_tests.py:114:33:114:39 | ControlFlowNode for request | testapp/orm_security_tests.py:115:41:115:52 | ControlFlowNode for Attribute |
31+
| testapp/orm_security_tests.py:115:15:115:61 | ControlFlowNode for CommentValidatorUsed() [Attribute text] | testapp/orm_security_tests.py:117:5:117:11 | ControlFlowNode for comment [Attribute text] |
32+
| testapp/orm_security_tests.py:115:41:115:52 | ControlFlowNode for Attribute | testapp/orm_security_tests.py:115:41:115:60 | ControlFlowNode for Subscript |
33+
| testapp/orm_security_tests.py:115:41:115:60 | ControlFlowNode for Subscript | testapp/orm_security_tests.py:115:15:115:61 | ControlFlowNode for CommentValidatorUsed() [Attribute text] |
34+
| testapp/orm_security_tests.py:117:5:117:11 | ControlFlowNode for comment [Attribute text] | testapp/orm_security_tests.py:111:1:111:41 | [orm-model] Class CommentValidatorUsed [Attribute text] |
35+
| testapp/orm_security_tests.py:120:15:120:49 | ControlFlowNode for Attribute() [Attribute text] | testapp/orm_security_tests.py:121:25:121:31 | ControlFlowNode for comment [Attribute text] |
36+
| testapp/orm_security_tests.py:121:25:121:31 | ControlFlowNode for comment [Attribute text] | testapp/orm_security_tests.py:121:25:121:36 | ControlFlowNode for Attribute |
2137
nodes
2238
| testapp/orm_security_tests.py:15:1:15:27 | [orm-model] Class Person [Attribute age] | semmle.label | [orm-model] Class Person [Attribute age] |
2339
| testapp/orm_security_tests.py:15:1:15:27 | [orm-model] Class Person [Attribute name] | semmle.label | [orm-model] Class Person [Attribute name] |
@@ -39,7 +55,27 @@ nodes
3955
| testapp/orm_security_tests.py:55:25:55:55 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
4056
| testapp/orm_security_tests.py:55:45:55:50 | ControlFlowNode for person [Attribute age] | semmle.label | ControlFlowNode for person [Attribute age] |
4157
| testapp/orm_security_tests.py:55:45:55:54 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
58+
| testapp/orm_security_tests.py:92:1:92:44 | [orm-model] Class CommentValidatorNotUsed [Attribute text] | semmle.label | [orm-model] Class CommentValidatorNotUsed [Attribute text] |
59+
| testapp/orm_security_tests.py:95:37:95:43 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
60+
| testapp/orm_security_tests.py:96:15:96:64 | ControlFlowNode for CommentValidatorNotUsed() [Attribute text] | semmle.label | ControlFlowNode for CommentValidatorNotUsed() [Attribute text] |
61+
| testapp/orm_security_tests.py:96:44:96:55 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
62+
| testapp/orm_security_tests.py:96:44:96:63 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
63+
| testapp/orm_security_tests.py:97:5:97:11 | ControlFlowNode for comment [Attribute text] | semmle.label | ControlFlowNode for comment [Attribute text] |
64+
| testapp/orm_security_tests.py:101:15:101:52 | ControlFlowNode for Attribute() [Attribute text] | semmle.label | ControlFlowNode for Attribute() [Attribute text] |
65+
| testapp/orm_security_tests.py:102:25:102:31 | ControlFlowNode for comment [Attribute text] | semmle.label | ControlFlowNode for comment [Attribute text] |
66+
| testapp/orm_security_tests.py:102:25:102:36 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
67+
| testapp/orm_security_tests.py:111:1:111:41 | [orm-model] Class CommentValidatorUsed [Attribute text] | semmle.label | [orm-model] Class CommentValidatorUsed [Attribute text] |
68+
| testapp/orm_security_tests.py:114:33:114:39 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
69+
| testapp/orm_security_tests.py:115:15:115:61 | ControlFlowNode for CommentValidatorUsed() [Attribute text] | semmle.label | ControlFlowNode for CommentValidatorUsed() [Attribute text] |
70+
| testapp/orm_security_tests.py:115:41:115:52 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
71+
| testapp/orm_security_tests.py:115:41:115:60 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
72+
| testapp/orm_security_tests.py:117:5:117:11 | ControlFlowNode for comment [Attribute text] | semmle.label | ControlFlowNode for comment [Attribute text] |
73+
| testapp/orm_security_tests.py:120:15:120:49 | ControlFlowNode for Attribute() [Attribute text] | semmle.label | ControlFlowNode for Attribute() [Attribute text] |
74+
| testapp/orm_security_tests.py:121:25:121:31 | ControlFlowNode for comment [Attribute text] | semmle.label | ControlFlowNode for comment [Attribute text] |
75+
| testapp/orm_security_tests.py:121:25:121:36 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
4276
subpaths
4377
#select
4478
| testapp/orm_security_tests.py:48:25:48:57 | ControlFlowNode for Attribute() | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | testapp/orm_security_tests.py:48:25:48:57 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | a user-provided value |
4579
| testapp/orm_security_tests.py:55:25:55:55 | ControlFlowNode for Attribute() | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | testapp/orm_security_tests.py:55:25:55:55 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | a user-provided value |
80+
| testapp/orm_security_tests.py:102:25:102:36 | ControlFlowNode for Attribute | testapp/orm_security_tests.py:95:37:95:43 | ControlFlowNode for request | testapp/orm_security_tests.py:102:25:102:36 | ControlFlowNode for Attribute | Cross-site scripting vulnerability due to $@. | testapp/orm_security_tests.py:95:37:95:43 | ControlFlowNode for request | a user-provided value |
81+
| testapp/orm_security_tests.py:121:25:121:36 | ControlFlowNode for Attribute | testapp/orm_security_tests.py:114:33:114:39 | ControlFlowNode for request | testapp/orm_security_tests.py:121:25:121:36 | ControlFlowNode for Attribute | Cross-site scripting vulnerability due to $@. | testapp/orm_security_tests.py:114:33:114:39 | ControlFlowNode for request | a user-provided value |

python/ql/test/library-tests/frameworks/django-orm/testapp/orm_security_tests.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def save_comment_validator_not_used(request): # $requestHandler
9999

100100
def display_comment_validator_not_used(request): # $requestHandler
101101
comment = CommentValidatorNotUsed.objects.last()
102-
return HttpResponse(comment.text) # NOT OK
102+
return HttpResponse(comment.text) # NOT OK
103103

104104
# To test this
105105
"""
@@ -118,7 +118,7 @@ def save_comment_validator_used(request): # $requestHandler
118118

119119
def display_comment_validator_used(request): # $requestHandler
120120
comment = CommentValidatorUsed.objects.last()
121-
return HttpResponse(comment.text) # sort of OK
121+
return HttpResponse(comment.text) # sort of OK
122122

123123
# Doing the following will raise a ValidationError
124124
"""

python/ql/test/library-tests/frameworks/django-orm/testapp/orm_tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def test_save1_store():
3434

3535
def test_save1_load():
3636
obj = TestSave1.objects.first()
37-
SINK(obj.text) # $ MISSING: flow
37+
SINK(obj.text) # $ flow="SOURCE, l:-5 -> obj.text"
3838

3939
# --------------------------------------
4040
# Constructor: positional arg

0 commit comments

Comments
 (0)