|
55 | 55 |
|
56 | 56 | MOCKED_NOW = 1549533574 |
57 | 57 | API_SECRET = 'X7qLTrsES31MzxxkxPPA-pAGGfU' |
| 58 | +API_SIGN_REQUEST_TEST_SECRET = "hdcixPpR2iKERPwqvH6sHdK9cyac" |
| 59 | +API_SIGN_REQUEST_CLOUD_NAME = "dn6ot3ged" |
58 | 60 |
|
59 | 61 |
|
60 | 62 | class TestUtils(unittest.TestCase): |
@@ -1443,17 +1445,50 @@ def test_support_long_url_signature(self): |
1443 | 1445 | expected_url=DEFAULT_UPLOAD_PATH + long_signature + "/" + image_name) |
1444 | 1446 |
|
1445 | 1447 | def test_api_sign_request_sha1(self): |
1446 | | - params = dict( cloud_name="dn6ot3ged", timestamp=1568810420, username="[email protected]") |
1447 | | - signature = api_sign_request(params, "hdcixPpR2iKERPwqvH6sHdK9cyac") |
| 1448 | + params = dict( cloud_name=API_SIGN_REQUEST_CLOUD_NAME, timestamp=1568810420, username="[email protected]") |
| 1449 | + signature = api_sign_request(params, API_SIGN_REQUEST_TEST_SECRET) |
1448 | 1450 | expected = "14c00ba6d0dfdedbc86b316847d95b9e6cd46d94" |
1449 | 1451 | self.assertEqual(expected, signature) |
1450 | 1452 |
|
1451 | 1453 | def test_api_sign_request_sha256(self): |
1452 | | - params = dict( cloud_name="dn6ot3ged", timestamp=1568810420, username="[email protected]") |
1453 | | - signature = api_sign_request(params, "hdcixPpR2iKERPwqvH6sHdK9cyac", cloudinary.utils.SIGNATURE_SHA256) |
| 1454 | + params = dict( cloud_name=API_SIGN_REQUEST_CLOUD_NAME, timestamp=1568810420, username="[email protected]") |
| 1455 | + signature = api_sign_request(params, API_SIGN_REQUEST_TEST_SECRET, cloudinary.utils.SIGNATURE_SHA256) |
1454 | 1456 | expected = "45ddaa4fa01f0c2826f32f669d2e4514faf275fe6df053f1a150e7beae58a3bd" |
1455 | 1457 | self.assertEqual(expected, signature) |
1456 | 1458 |
|
| 1459 | + def test_api_sign_request_prevents_parameter_smuggling(self): |
| 1460 | + """Should prevent parameter smuggling via & characters in parameter values""" |
| 1461 | + # Test with notification_url containing & characters |
| 1462 | + params_with_ampersand = { |
| 1463 | + "cloud_name": API_SIGN_REQUEST_CLOUD_NAME, |
| 1464 | + "timestamp": 1568810420, |
| 1465 | + "notification_url": "https://fake.com/callback?a=1&tags=hello,world" |
| 1466 | + } |
| 1467 | + |
| 1468 | + signature_with_ampersand = api_sign_request(params_with_ampersand, API_SIGN_REQUEST_TEST_SECRET) |
| 1469 | + |
| 1470 | + # Test that attempting to smuggle parameters by splitting the notification_url fails |
| 1471 | + params_smuggled = { |
| 1472 | + "cloud_name": API_SIGN_REQUEST_CLOUD_NAME, |
| 1473 | + "timestamp": 1568810420, |
| 1474 | + "notification_url": "https://fake.com/callback?a=1", |
| 1475 | + "tags": "hello,world" # This would be smuggled if & encoding didn't work |
| 1476 | + } |
| 1477 | + |
| 1478 | + signature_smuggled = api_sign_request(params_smuggled, API_SIGN_REQUEST_TEST_SECRET) |
| 1479 | + |
| 1480 | + # The signatures should be different, proving that parameter smuggling is prevented |
| 1481 | + self.assertNotEqual(signature_with_ampersand, signature_smuggled, |
| 1482 | + "Signatures should be different to prevent parameter smuggling") |
| 1483 | + |
| 1484 | + # Verify the expected signature for the properly encoded case |
| 1485 | + expected_signature = "4fdf465dd89451cc1ed8ec5b3e314e8a51695704" |
| 1486 | + self.assertEqual(expected_signature, signature_with_ampersand) |
| 1487 | + |
| 1488 | + # Verify the expected signature for the smuggled parameters case |
| 1489 | + expected_smuggled_signature = "7b4e3a539ff1fa6e6700c41b3a2ee77586a025f9" |
| 1490 | + self.assertEqual(expected_smuggled_signature, signature_smuggled) |
| 1491 | + |
1457 | 1492 |
|
1458 | 1493 | if __name__ == '__main__': |
1459 | 1494 | unittest.main() |
0 commit comments