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

Guard paths to which output can be written #184

Merged

Conversation

drivenflywheel
Copy link
Collaborator

@drivenflywheel drivenflywheel commented Nov 22, 2021

Addresses CodeQL feedback and resolves three CodeQL security alerts
Ticket 5422

@drivenflywheel drivenflywheel changed the title WIP: Guard paths to which output can be written Guard paths to which output can be written Dec 20, 2021
@drivenflywheel drivenflywheel marked this pull request as ready for review December 20, 2021 20:06
@drivenflywheel drivenflywheel added the security There are security/vulnerability implications label Dec 21, 2021
@drivenflywheel drivenflywheel added the needs review Reviews and approvals are still needed label Dec 21, 2021
@@ -77,7 +77,7 @@ private Response processRegisterPeer(String peerKey, String dirName) {
}

final Set<String> set = new HashSet<>();
set.add(KeyManipulator.getDefaultDirectoryKey(peerKey));
set.add(KeyManipulator.getDefaultDirectoryKey("#" + peerKey));
Copy link
Collaborator Author

@drivenflywheel drivenflywheel Dec 22, 2021

Choose a reason for hiding this comment

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

The specific code change on this line has no functional impact (the prefix gets stripped by the KeyManipulator.getDefaultDirectory method).

We have existing and sufficient SSRF mitigation on lines 70-73, which restricts the hosts that can be registered through this endpoint. The "#" prefix added here is used to trigger the CodeQL RequestForgery.HostnameSanitizer flag, which indicates that we've sanitized the hostname to prevent a SSRF attack. This flag is considered when evaluating dataflow paths for SSRF / cwe-918 vulnerability, and we trip the flag to signal that this code path (already) includes hostname sanitation.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agreed.

Would it be worth adding a quick test case for the KeyManipulator that proves this behavior jic functionality gets changes somewhere down the road?

*/
static String filePathIsWithinBaseDirectory(String requiredBase, String filePath) throws IllegalArgumentException {
// probably an overly simplistic test
if (filePath.contains("..")) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The check on this line is a simple guard that satisfies a CodeQL path sanitizer check, our sanization is considered (by CodeQL scans) sufficient to defeat Uncontrolled data used in path expression" vulnerability.

Lines 1099 to 1103 perform more thorough validation to ensure that we consider the filePath resolves to a location we trust (and doesn't try to perform path traversal to an unexpected location), but we need the guard on line 1096 so line 1100 isn't mistakenly flagged as vulnerable code.

This change has no production impact: no existing production code paths reach this method, but it's reachable by legacy public static main(String[] args) methods in numerous Place implementations that call the ServiceProviderPlace.mainRunner method for ad hoc testing.

Copy link
Collaborator

@jpdahlke jpdahlke left a comment

Choose a reason for hiding this comment

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

Good this is getting cleaned up.

Just a few small things.

try {
safePath = filePathIsWithinBaseDirectory(getBaseOutputDir(), fn);
if (Executrix.writeDataToFile(payload.data(), safePath)) {
logger.debug("Wrote attachment output to " + safePath);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd be ok with updating these to parameterized logging.

* @throws IllegalArgumentException if the filePath contains illegal characters or is outside the required base
* directory
*/
static String filePathIsWithinBaseDirectory(String requiredBase, String filePath) throws IllegalArgumentException {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Worth protecting against null/empty inputs?

*
* @param requiredBase required base directory
* @param filePath file path to be tested
* @return the normalized file path is within the required base directory
Copy link
Collaborator

Choose a reason for hiding this comment

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

@return the normalized file path if within the required base directory

When I read it initially, my mind went to a boolean return.

@@ -77,7 +77,7 @@ private Response processRegisterPeer(String peerKey, String dirName) {
}

final Set<String> set = new HashSet<>();
set.add(KeyManipulator.getDefaultDirectoryKey(peerKey));
set.add(KeyManipulator.getDefaultDirectoryKey("#" + peerKey));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Agreed.

Would it be worth adding a quick test case for the KeyManipulator that proves this behavior jic functionality gets changes somewhere down the road?

@jpdahlke jpdahlke added this to the v7.3.0 milestone Dec 24, 2021
@drivenflywheel
Copy link
Collaborator Author

Incorporated feedback

@jpdahlke jpdahlke merged commit 76eff1c into NationalSecurityAgency:master Jan 4, 2022
@burritoqueen burritoqueen removed the needs review Reviews and approvals are still needed label Jan 4, 2022
ukengineer925 pushed a commit to ukengineer925/emissary that referenced this pull request Mar 10, 2022
* Implemented a simple path guard to enforce paths to which output can be written
andrewbp pushed a commit to andrewbp/emissary that referenced this pull request Jul 5, 2022
* Implemented a simple path guard to enforce paths to which output can be written
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
security There are security/vulnerability implications
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants