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

Prevent Usage of Stdlib File/Dir Writing With Static Analysis #7685

Merged
merged 20 commits into from
Nov 9, 2020

Conversation

rauljordan
Copy link
Contributor

@rauljordan rauljordan commented Oct 30, 2020

What type of PR is this?

Feature

What does this PR do? Why is it needed?

This PR prevents usage of ioutil.WriteFile and os.MkdirAll in our repository, as those are unsafe when it comes to checking permissions. For example, an attacker could create a directory p with 777 permissions, and os.MkdirAll(p) will fail silently, without overriding the permissions of the attacker. Instead, we enforce Prysm to use our own shared/fileutil package that properly checks for permissions errors compared to the Go standard library. We enforce this using a static analyzer that prevents os.MkdirAll and ioutil.WriteFile.

Which issues(s) does this PR fix?

Part of #7410 and fixes #7410

@rauljordan rauljordan added Ready For Review A pull request ready for code review Security Security Related Issues Audit labels Oct 30, 2020
@rauljordan rauljordan requested a review from a team as a code owner October 30, 2020 16:24
@rauljordan rauljordan self-assigned this Oct 30, 2020
@rauljordan rauljordan mentioned this pull request Oct 30, 2020
26 tasks
@rauljordan rauljordan removed the Ready For Review A pull request ready for code review label Oct 30, 2020
@rauljordan rauljordan marked this pull request as draft October 30, 2020 16:27
@rauljordan rauljordan marked this pull request as ready for review November 3, 2020 03:08
@rauljordan rauljordan added the Ready For Review A pull request ready for code review label Nov 3, 2020
@codecov
Copy link

codecov bot commented Nov 3, 2020

Codecov Report

Merging #7685 (4451802) into master (15706a3) will decrease coverage by 0.04%.
The diff coverage is 34.28%.

@@            Coverage Diff             @@
##           master    #7685      +/-   ##
==========================================
- Coverage   62.18%   62.13%   -0.05%     
==========================================
  Files         429      429              
  Lines       30205    30248      +43     
==========================================
+ Hits        18782    18794      +12     
- Misses       8513     8530      +17     
- Partials     2910     2924      +14     

Copy link
Contributor

@rkapka rkapka left a comment

Choose a reason for hiding this comment

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

Please add more tests.

if err := fileutil.MkdirAll(dirPath); err != nil {
return nil, err
}
}
datafile := path.Join(dirPath, databaseFileName)
boltDB, err := bolt.Open(datafile, params.BeaconIoConfig().ReadWritePermissions, &bolt.Options{Timeout: 1 * time.Second, InitialMmapSize: 10e6})
Copy link
Contributor

Choose a reason for hiding this comment

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

What if the directory already exists and contains a database? Shouldn't this be an error?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If it already exists that means you already have a database and we should open it normally to start your beacon node

shared/fileutil/fileutil.go Outdated Show resolved Hide resolved
shared/fileutil/fileutil.go Outdated Show resolved Hide resolved
shared/fileutil/fileutil.go Outdated Show resolved Hide resolved
shared/fileutil/fileutil.go Outdated Show resolved Hide resolved
Comment on lines +91 to +100
hasDir, err := fileutil.HasDir(dirPath)
if err != nil {
return nil, err
}
if !hasDir {
if err := fileutil.MkdirAll(dirPath); err != nil {
return nil, err
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please write some tests?

Comment on lines +65 to +73
hasDir, err := fileutil.HasDir(dirPath)
if err != nil {
return nil, err
}
if !hasDir {
if err := fileutil.MkdirAll(dirPath); err != nil {
return nil, err
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please write some tests?

tools/analyzers/writefile/analyzer.go Outdated Show resolved Hide resolved
tools/analyzers/writefile/analyzer.go Outdated Show resolved Hide resolved
case *ast.CallExpr:
// Check if any of disallowed functions have been used.
for pkg, path := range aliases {
for _, fn := range disallowedFns {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not that big of a deal, but since you have a nested loop you check MkdirAll and WriteFile for both packages.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is ok because it's better if it's extensible. In the future we can easily add more functions we want to check against near the top of the file

rkapka
rkapka previously approved these changes Nov 9, 2020
@rauljordan rauljordan merged commit d4c9546 into master Nov 9, 2020
@delete-merged-branch delete-merged-branch bot deleted the osmkdir-static branch November 9, 2020 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Ready For Review A pull request ready for code review Security Security Related Issues
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Trail of Bits audit tracking
3 participants