Skip to content

Commit 0d8129c

Browse files
committed
fix: salt parameter splicing
1 parent 5d3a122 commit 0d8129c

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

altcha/altcha.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,10 @@ def create_challenge(
444444
if salt_params:
445445
salt += "?" + urllib.parse.urlencode(salt_params)
446446

447+
# Add a delimiter to prevent parameter splicing
448+
if not salt.endswith("&"):
449+
salt += "&"
450+
447451
challenge = hash_hex(algorithm, (salt + str(number)).encode())
448452
signature = hmac_hex(algorithm, challenge.encode(), options.hmac_key)
449453

tests/test_altcha.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,30 @@ def test_verify_solution_malformed_expiry(self):
228228
result, _ = verify_solution(payload_encoded, self.hmac_key, check_expires=True)
229229
self.assertFalse(result)
230230

231+
def test_verify_solution_salt_splicing(self):
232+
options = ChallengeOptions(
233+
algorithm="SHA-256",
234+
max_number=1000,
235+
salt_length=16,
236+
hmac_key=self.hmac_key,
237+
expires=datetime.datetime.now().astimezone()
238+
+ datetime.timedelta(minutes=1),
239+
number=123,
240+
)
241+
challenge = create_challenge(options)
242+
payload = Payload(
243+
algorithm="SHA-256",
244+
challenge=challenge.challenge,
245+
number=23,
246+
salt=challenge.salt + "1",
247+
signature=challenge.signature,
248+
)
249+
payload_encoded = base64.b64encode(
250+
json.dumps(payload.__dict__).encode()
251+
).decode()
252+
result, _ = verify_solution(payload_encoded, self.hmac_key, check_expires=False)
253+
self.assertFalse(result)
254+
231255
def test_valid_signature(self):
232256
expire_time = int(time.time()) + 600 # 10 minutes from now
233257
verification_data = (

0 commit comments

Comments
 (0)