Skip to content
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

Fix cache vulnerability #2516

Merged
merged 2 commits into from Dec 20, 2015
Merged

Conversation

jonas054
Copy link
Collaborator

This addresses the concerns raised in #2484. I really don't want to move the cache location, so I tried a different way.

For symlink attacks, there's no risk that the cache file itself is replaced by a symlink since we create a temporary cache file first and then rename it. There is however a chance that someone replaces a directory in the cache tree with a symlink, and we can avoid that problem by not allowing any symlinks (all the way up to the file system root directory) before writing the file. I disregard the risk of an attacker replacing a directory with a symlink just at the time between us checking and writing, since writing cache files to the wrong directory is a much smaller problem that overwriting existing files with cache data.

A Marshal attack is a more serious problem. I didn't realize this could happen, but I understand now that it can. See http://docs.ruby-lang.org/en/2.0.0/security_rdoc.html#label-Marshal.load

Replacing Marshal with JSON results in a small performance penalty when reading from the cache, around 25% on my system.

@alexdowad
Copy link
Contributor

Thanks @jonas054!

Do not allow any symlinks in the cache directory
tree. Check before writing.
@@ -84,7 +131,7 @@ def abs(path)

describe '#save' do
context 'when the default internal encoding is UTF-8' do
let(:comments) { ["# Hello \xF0"] }
let(:comment_text) { '# Hello \xF0' }
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oops! Should still be double quotes here, but that makes the spec fail. I'll have to fix that.

@jonas054
Copy link
Collaborator Author

Updated.

Use JSON as serialization format instead of Marshal,
which can result in execution of arbitrary code when
unpacking objects that an attacker has packed and put
where we expect to find cached results.
@jonas054
Copy link
Collaborator Author

Corrected typo.

bbatsov added a commit that referenced this pull request Dec 20, 2015
@bbatsov bbatsov merged commit 0582a11 into rubocop:master Dec 20, 2015
@bbatsov
Copy link
Collaborator

bbatsov commented Dec 20, 2015

👍

@jonas054 jonas054 deleted the 2484_fix_cache_vulnerability branch April 15, 2016 04:28
urbanautomaton added a commit to urbanautomaton/rubocop that referenced this pull request Jun 11, 2016
The default location for RuboCop's result cache is `/tmp`, which on the vast
majority of systems is a world-writable directory. This means that a malicious
user might be able to create a symlink to either redirect RuboCop's output to
an unintended location, or cause RuboCop to read malicious input.

Previous work[1,2] introduced protection against such symlink attacks by
symlinks to be present in any cache locations.

However, often CI setups explicitly rely on the ability to symlink cache
locations, so that persistent results can be placed in shared storage, and
symlinked to a predictable location on build machines[3].

This commit adds a new configuration option,
`AllowSymlinksInCacheRootDirectory`, which lets a user permit symlinks if they
are certain that their cache location is secure.

[1] rubocop#2484
[2] rubocop#2516
[3] rubocop#3005
bbatsov pushed a commit that referenced this pull request Jun 11, 2016
)

The default location for RuboCop's result cache is `/tmp`, which on the vast
majority of systems is a world-writable directory. This means that a malicious
user might be able to create a symlink to either redirect RuboCop's output to
an unintended location, or cause RuboCop to read malicious input.

Previous work[1,2] introduced protection against such symlink attacks by
symlinks to be present in any cache locations.

However, often CI setups explicitly rely on the ability to symlink cache
locations, so that persistent results can be placed in shared storage, and
symlinked to a predictable location on build machines[3].

This commit adds a new configuration option,
`AllowSymlinksInCacheRootDirectory`, which lets a user permit symlinks if they
are certain that their cache location is secure.

[1] #2484
[2] #2516
[3] #3005
Neodelf pushed a commit to Neodelf/rubocop that referenced this pull request Oct 15, 2016
…bocop#3199)

The default location for RuboCop's result cache is `/tmp`, which on the vast
majority of systems is a world-writable directory. This means that a malicious
user might be able to create a symlink to either redirect RuboCop's output to
an unintended location, or cause RuboCop to read malicious input.

Previous work[1,2] introduced protection against such symlink attacks by
symlinks to be present in any cache locations.

However, often CI setups explicitly rely on the ability to symlink cache
locations, so that persistent results can be placed in shared storage, and
symlinked to a predictable location on build machines[3].

This commit adds a new configuration option,
`AllowSymlinksInCacheRootDirectory`, which lets a user permit symlinks if they
are certain that their cache location is secure.

[1] rubocop#2484
[2] rubocop#2516
[3] rubocop#3005
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants