8000 [Cache] Make directory hashing case insensitive by nicolas-grekas · Pull Request #20453 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Cache] Make directory hashing case insensitive #20453

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 9, 2016

Conversation

nicolas-grekas
Copy link
Member
Q A
Branch? 3.1
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #20450
License MIT
Doc PR -

Fixes this situation: a Windows OS, running a Debian via VirtualBox and Vagrant. So the cache folder is on a Windows partition while the PHP command is running inside Debian...

Not testable without this specific setup...

@@ -147,7 +147,7 @@ protected function doSave(array $values, $lifetime)
private function getFile($id, $mkdir = false)
{
$hash = str_replace('/', '-', base64_encode(md5($id, true)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it base64_encode an md5 hash? Seems pointless to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ref #18085

Copy link
Member Author
@nicolas-grekas nicolas-grekas Nov 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a constraint on the length of paths (at least on Windows).

  • strlen(md5('', false)) => 32
  • strlen(base64_encode(md5('', true))) => 22 (padding = removed)

That's the reason.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using md5 which has known collisions with just 64 bytes is already unsafe. But ignoring the case of base64_encode will make it even worse. This basically means it unsafe to use untrusted cache keys for the cache component. This needs to be highlighted.

Copy link
Member Author
@nicolas-grekas nicolas-grekas Nov 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MD5 weaknesses make it not suitable for any security related job (signatures, etc.). Here, we only need to be reasonably sure that keys won't collide. Making two bytes case insensitive won't invalidate this.
As far as security is concerned, if a collision occurs, it will be caught by the unhashed key comparison done when opening files.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum, my bad, I'm wrong here! Give me lunch time to give the correct number so we can talk with numbers...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whatever the probably is, it just means, you cannot trust cache keys. E.g. it's not safe to use the current request info as cache key. That should be documented.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as security is concerned, if a collision occurs, it will be caught by the unhashed key comparison done when opening files.

This doesn't solve the security problem. When a cache key doesn't exist which it looks like when a collision happens with the key comparison, then clients usually write the cache with the collided key. So it will overwrite the cache of another key. This basically means anybody can prune the cache by using collisions.

8000
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for the proba part, worse case on windows: the 128bits MD5 being turned to case insensitive base64 means 38^21*4 = 6e+33 key space cardinality. On NTFS that handles at most 2^32-1 files per partition, this means that filling at 100% has 1/1.4e+24 chance of generating a collision. I'd say this is enough space for any use cases here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, considering that I still think having short paths is desired to make things work seamlessly on Windows, considering also that truncating a sha256 looks fine for the use case, I replaced md5 by a truncated sha256. Case insensitivity is here equivalent to truncating a bit more the hash on Windows, which seems safe also for the use case (see previous comment). OK for you?

@nicolas-grekas nicolas-grekas changed the title [Cache] Make directory hashing case insensitve [Cache] Make directory hashing case insensitive Nov 9, 2016
@Tobion
Copy link
Contributor
Tobion commented Nov 9, 2016

Status: Reviewed
👍

@fabpot
Copy link
Member
fabpot commented Nov 9, 2016

Thank you @nicolas-grekas.

@fabpot fabpot merged commit 6d4a658 into symfony:3.1 Nov 9, 2016
fabpot added a commit that referenced this pull request Nov 9, 2016
…rekas)

This PR was merged into the 3.1 branch.

Discussion
----------

[Cache] Make directory hashing case insensitive

| Q             | A
| ------------- | ---
| Branch?       | 3.1
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #20450
| License       | MIT
| Doc PR        | -

Fixes this situation: a Windows OS, running a Debian via VirtualBox and Vagrant. So the cache folder is on a Windows partition while the PHP command is running inside Debian...

Not testable without this specific setup...

Commits
-------

6d4a658 [Cache] Make directory hashing case insensitive
@nicolas-grekas nicolas-grekas deleted the cache-case branch November 10, 2016 08:24
@Tobion
Copy link
Contributor
Tobion commented Nov 13, 2016

Btw, PHP 7.1 might have fixed the Windows PHP length limit.

Long paths support is transparent. Paths longer than 260 bytes get
automatically prefixed with ?. The max path length is limited to
2048 bytes. Be aware, that the path segment limit (basename length) still
persists.

https://github.com/php/php-src/blob/php-7.1.0RC5/UPGRADING

I didn't try it. But might we worth considering to decrease collision probability.

This was referenced Nov 17, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants
0