Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 0747c3d

Browse files
committedDec 4, 2024·
hashids-with-flask-secret-python
1 parent f1883e7 commit 0747c3d

File tree

3 files changed

+456
-0
lines changed

3 files changed

+456
-0
lines changed
 
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
id: hashids-with-flask-secret-python
2+
severity: warning
3+
language: python
4+
message: >-
5+
The Flask secret key is used as salt in HashIDs. The HashID mechanism
6+
is not secure. By observing sufficient HashIDs, the salt used to construct
7+
them can be recovered. This means the Flask secret key can be obtained by
8+
attackers, through the HashIDs).
9+
note: >-
10+
[CWE-327] Use of a Broken or Risky Cryptographic Algorithm.
11+
[REFERENCES]
12+
- https://flask.palletsprojects.com/en/2.2.x/config/#SECRET_KEY
13+
- http://carnage.github.io/2015/08/cryptanalysis-of-hashids
14+
utils:
15+
hashids.Hashids(..., salt=flask.current_app.config['SECRET_KEY'], ...):
16+
# hashids.Hashids(..., salt=flask.current_app.config['SECRET_KEY'], ...)
17+
kind: call
18+
all:
19+
- has:
20+
stopBy: neighbor
21+
kind: attribute
22+
regex: ^hashids.Hashids$
23+
- has:
24+
stopBy: neighbor
25+
kind: argument_list
26+
has:
27+
stopBy: end
28+
kind: keyword_argument
29+
all:
30+
- has:
31+
stopBy: neighbor
32+
kind: identifier
33+
regex: ^salt$
34+
- has:
35+
stopBy: neighbor
36+
kind: subscript
37+
pattern: flask.current_app.config['SECRET_KEY']
38+
hashids.Hashids(flask.current_app.config['SECRET_KEY'], ...):
39+
# hashids.Hashids(flask.current_app.config['SECRET_KEY'], ...)
40+
kind: call
41+
all:
42+
- has:
43+
stopBy: neighbor
44+
kind: attribute
45+
regex: ^hashids.Hashids$
46+
- has:
47+
stopBy: neighbor
48+
kind: argument_list
49+
has:
50+
stopBy: neighbor
51+
kind: subscript
52+
pattern: flask.current_app.config['SECRET_KEY']
53+
hashids.Hashids($APP.config['SECRET_KEY'], ...):
54+
# hashids.Hashids($APP.config['SECRET_KEY'], ...)
55+
kind: call
56+
all:
57+
- has:
58+
stopBy: neighbor
59+
kind: attribute
60+
regex: ^hashids.Hashids$
61+
- has:
62+
stopBy: neighbor
63+
kind: argument_list
64+
has:
65+
stopBy: neighbor
66+
kind: subscript
67+
pattern: $APP.config['SECRET_KEY']
68+
- inside:
69+
stopBy: end
70+
kind: module
71+
has:
72+
stopBy: end
73+
kind: expression_statement
74+
has:
75+
stopBy: neighbor
76+
kind: assignment
77+
pattern: $APP = flask.Flask($$$)
78+
hashids.Hashids(..., salt=$APP.config['SECRET_KEY'], ...):
79+
# hashids.Hashids(..., salt=$APP.config['SECRET_KEY'], ...)
80+
kind: call
81+
all:
82+
- has:
83+
stopBy: neighbor
84+
kind: attribute
85+
regex: ^hashids.Hashids$
86+
- has:
87+
stopBy: neighbor
88+
kind: argument_list
89+
has:
90+
stopBy: end
91+
kind: keyword_argument
92+
all:
93+
- has:
94+
stopBy: neighbor
95+
kind: identifier
96+
regex: ^salt$
97+
- has:
98+
stopBy: neighbor
99+
kind: subscript
100+
pattern: $APP.config['SECRET_KEY']
101+
- inside:
102+
stopBy: end
103+
kind: module
104+
has:
105+
stopBy: end
106+
kind: expression_statement
107+
has:
108+
stopBy: neighbor
109+
kind: assignment
110+
pattern: $APP = flask.Flask($$$)
111+
Hashids(salt=app.config['SECRET_KEY']):
112+
# from hashids import Hashids
113+
# from flask import current_app as app
114+
# hash_id = Hashids(salt=app.config['SECRET_KEY'])
115+
kind: call
116+
all:
117+
- has:
118+
stopBy: neighbor
119+
kind: identifier
120+
regex: ^Hashids$
121+
- has:
122+
stopBy: neighbor
123+
kind: argument_list
124+
has:
125+
stopBy: end
126+
kind: keyword_argument
127+
all:
128+
- has:
129+
stopBy: neighbor
130+
kind: identifier
131+
regex: ^salt$
132+
- has:
133+
stopBy: neighbor
134+
kind: subscript
135+
pattern: $APP.config['SECRET_KEY']
136+
- inside:
137+
stopBy: end
138+
kind: module
139+
all:
140+
- has:
141+
stopBy: end
142+
kind: import_from_statement
143+
pattern: from hashids import Hashids
144+
- any:
145+
- has:
146+
stopBy: end
147+
kind: import_from_statement
148+
pattern: from flask import current_app as $APP
149+
- has:
150+
stopBy: end
151+
kind: expression_statement
152+
has:
153+
stopBy: end
154+
kind: assignment
155+
pattern: $APP = Flask($$$)
156+
Hashids(salt=current_app.config['SECRET_KEY']):
157+
# from hashids import Hashids
158+
# from flask import current_app
159+
# hashids = Hashids(min_length=5, salt=current_app.config['SECRET_KEY'])
160+
kind: call
161+
all:
162+
- has:
163+
stopBy: neighbor
164+
kind: identifier
165+
regex: ^Hashids$
166+
- has:
167+
stopBy: neighbor
168+
kind: argument_list
169+
has:
170+
stopBy: end
171+
kind: keyword_argument
172+
all:
173+
- has:
174+
stopBy: neighbor
175+
kind: identifier
176+
regex: ^salt$
177+
- has:
178+
stopBy: neighbor
179+
kind: subscript
180+
pattern: current_app.config['SECRET_KEY']
181+
- inside:
182+
stopBy: end
183+
kind: module
184+
all:
185+
- has:
186+
stopBy: end
187+
kind: import_from_statement
188+
pattern: from hashids import Hashids
189+
- has:
190+
stopBy: end
191+
kind: import_from_statement
192+
pattern: from flask import current_app
193+
rule:
194+
kind: call
195+
any:
196+
- matches: hashids.Hashids(..., salt=flask.current_app.config['SECRET_KEY'], ...)
197+
- matches: hashids.Hashids(flask.current_app.config['SECRET_KEY'], ...)
198+
- matches: hashids.Hashids($APP.config['SECRET_KEY'], ...)
199+
- matches: hashids.Hashids(..., salt=$APP.config['SECRET_KEY'], ...)
200+
- matches: Hashids(salt=app.config['SECRET_KEY'])
201+
- matches: Hashids(salt=current_app.config['SECRET_KEY'])
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
id: hashids-with-flask-secret-python
2+
snapshots:
3+
? |-
4+
from hashids import Hashids
5+
app = Flask(__name__.split('.')[0])
6+
hashids = Hashids(min_length=4, salt=app.config['SECRET_KEY'])
7+
: labels:
8+
- source: Hashids(min_length=4, salt=app.config['SECRET_KEY'])
9+
style: primary
10+
start: 74
11+
end: 126
12+
- source: Hashids
13+
style: secondary
14+
start: 74
15+
end: 81
16+
- source: salt
17+
style: secondary
18+
start: 96
19+
end: 100
20+
- source: app.config['SECRET_KEY']
21+
style: secondary
22+
start: 101
23+
end: 125
24+
- source: salt=app.config['SECRET_KEY']
25+
style: secondary
26+
start: 96
27+
end: 125
28+
- source: (min_length=4, salt=app.config['SECRET_KEY'])
29+
style: secondary
30+
start: 81
31+
end: 126
32+
- source: from hashids import Hashids
33+
style: secondary
34+
start: 0
35+
end: 27
36+
- source: app = Flask(__name__.split('.')[0])
37+
style: secondary
38+
start: 28
39+
end: 63
40+
- source: app = Flask(__name__.split('.')[0])
41+
style: secondary
42+
start: 28
43+
end: 63
44+
- source: |-
45+
from hashids import Hashids
46+
app = Flask(__name__.split('.')[0])
47+
hashids = Hashids(min_length=4, salt=app.config['SECRET_KEY'])
48+
style: secondary
49+
start: 0
50+
end: 126
51+
? |
52+
from hashids import Hashids
53+
foo = Flask()
54+
hashids = Hashids(min_length=4, salt=foo.config['SECRET_KEY'])
55+
: labels:
56+
- source: Hashids(min_length=4, salt=foo.config['SECRET_KEY'])
57+
style: primary
58+
start: 52
59+
end: 104
60+
- source: Hashids
61+
style: secondary
62+
start: 52
63+
end: 59
64+
- source: salt
65+
style: secondary
66+
start: 74
67+
end: 78
68+
- source: foo.config['SECRET_KEY']
69+
style: secondary
70+
start: 79
71+
end: 103
72+
- source: salt=foo.config['SECRET_KEY']
73+
style: secondary
74+
start: 74
75+
end: 103
76+
- source: (min_length=4, salt=foo.config['SECRET_KEY'])
77+
style: secondary
78+
start: 59
79+
end: 104
80+
- source: from hashids import Hashids
81+
style: secondary
82+
start: 0
83+
end: 27
84+
- source: foo = Flask()
85+
style: secondary
86+
start: 28
87+
end: 41
88+
- source: foo = Flask()
89+
style: secondary
90+
start: 28
91+
end: 41
92+
- source: |
93+
from hashids import Hashids
94+
foo = Flask()
95+
hashids = Hashids(min_length=4, salt=foo.config['SECRET_KEY'])
96+
style: secondary
97+
start: 0
98+
end: 105
99+
? |
100+
from hashids import Hashids
101+
from flask import current_app
102+
hashids = Hashids(min_length=5, salt=current_app.config['SECRET_KEY'])
103+
: labels:
104+
- source: Hashids(min_length=5, salt=current_app.config['SECRET_KEY'])
105+
style: primary
106+
start: 68
107+
end: 128
108+
- source: Hashids
109+
style: secondary
110+
start: 68
111+
end: 75
112+
- source: salt
113+
style: secondary
114+
start: 90
115+
end: 94
116+
- source: current_app.config['SECRET_KEY']
117+
style: secondary
118+
start: 95
119+
end: 127
120+
- source: salt=current_app.config['SECRET_KEY']
121+
style: secondary
122+
start: 90
123+
end: 127
124+
- source: (min_length=5, salt=current_app.config['SECRET_KEY'])
125+
style: secondary
126+
start: 75
127+
end: 128
128+
- source: from hashids import Hashids
129+
style: secondary
130+
start: 0
131+
end: 27
132+
- source: from flask import current_app
133+
style: secondary
134+
start: 28
135+
end: 57
136+
- source: |
137+
from hashids import Hashids
138+
from flask import current_app
139+
hashids = Hashids(min_length=5, salt=current_app.config['SECRET_KEY'])
140+
style: secondary
141+
start: 0
142+
end: 129
143+
? |
144+
from hashids import Hashids
145+
from flask import current_app as app
146+
hash_id = Hashids(salt=app.config['SECRET_KEY'], min_length=34)
147+
: labels:
148+
- source: Hashids(salt=app.config['SECRET_KEY'], min_length=34)
149+
style: primary
150+
start: 75
151+
end: 128
152+
- source: Hashids
153+
style: secondary
154+
start: 75
155+
end: 82
156+
- source: salt
157+
style: secondary
158+
start: 83
159+
end: 87
160+
- source: app.config['SECRET_KEY']
161+
style: secondary
162+
start: 88
163+
end: 112
164+
- source: salt=app.config['SECRET_KEY']
165+
style: secondary
166+
start: 83
167+
end: 112
168+
- source: (salt=app.config['SECRET_KEY'], min_length=34)
169+
style: secondary
170+
start: 82
171+
end: 128
172+
- source: from hashids import Hashids
173+
style: secondary
174+
start: 0
175+
end: 27
176+
- source: from flask import current_app as app
177+
style: secondary
178+
start: 28
179+
end: 64
180+
- source: |
181+
from hashids import Hashids
182+
from flask import current_app as app
183+
hash_id = Hashids(salt=app.config['SECRET_KEY'], min_length=34)
184+
style: secondary
185+
start: 0
186+
end: 129
187+
? |
188+
from hashids import Hashids
189+
from flask import current_app as app
190+
hashids = Hashids(min_length=4, salt=app.config['SECRET_KEY'])
191+
: labels:
192+
- source: Hashids(min_length=4, salt=app.config['SECRET_KEY'])
193+
style: primary
194+
start: 75
195+
end: 127
196+
- source: Hashids
197+
style: secondary
198+
start: 75
199+
end: 82
200+
- source: salt
201+
style: secondary
202+
start: 97
203+
end: 101
204+
- source: app.config['SECRET_KEY']
205+
style: secondary
206+
start: 102
207+
end: 126
208+
- source: salt=app.config['SECRET_KEY']
209+
style: secondary
210+
start: 97
211+
end: 126
212+
- source: (min_length=4, salt=app.config['SECRET_KEY'])
213+
style: secondary
214+
start: 82
215+
end: 127
216+
- source: from hashids import Hashids
217+
style: secondary
218+
start: 0
219+
end: 27
220+
- source: from flask import current_app as app
221+
style: secondary
222+
start: 28
223+
end: 64
224+
- source: |
225+
from hashids import Hashids
226+
from flask import current_app as app
227+
hashids = Hashids(min_length=4, salt=app.config['SECRET_KEY'])
228+
style: secondary
229+
start: 0
230+
end: 128
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
id: hashids-with-flask-secret-python
2+
valid:
3+
- |
4+
hashids = Hashids(min_length=4, salt=app.config['SECRET_KEY'])
5+
invalid:
6+
- |
7+
from hashids import Hashids
8+
from flask import current_app as app
9+
hash_id = Hashids(salt=app.config['SECRET_KEY'], min_length=34)
10+
- |
11+
from hashids import Hashids
12+
from flask import current_app as app
13+
hashids = Hashids(min_length=4, salt=app.config['SECRET_KEY'])
14+
- |
15+
from hashids import Hashids
16+
from flask import current_app
17+
hashids = Hashids(min_length=5, salt=current_app.config['SECRET_KEY'])
18+
- |
19+
from hashids import Hashids
20+
foo = Flask()
21+
hashids = Hashids(min_length=4, salt=foo.config['SECRET_KEY'])
22+
- |
23+
from hashids import Hashids
24+
app = Flask(__name__.split('.')[0])
25+
hashids = Hashids(min_length=4, salt=app.config['SECRET_KEY'])

0 commit comments

Comments
 (0)
Please sign in to comment.