diff --git a/src/aws-cpp-sdk-transfer/source/transfer/TransferManager.cpp b/src/aws-cpp-sdk-transfer/source/transfer/TransferManager.cpp index 1a26ccb44c3d..addee26d984d 100644 --- a/src/aws-cpp-sdk-transfer/source/transfer/TransferManager.cpp +++ b/src/aws-cpp-sdk-transfer/source/transfer/TransferManager.cpp @@ -1497,6 +1497,7 @@ namespace Aws continue; } + bool wasParentRef = false; if(i + 2 < filePath.size() && '.' == filePath[i+1] && '.' == filePath[i+2]) // if "/.." { if(i + 3 == filePath.size() || (i + 3 < filePath.size() && '/' == filePath[i+3])) // if "/.." or "/../" @@ -1505,9 +1506,13 @@ namespace Aws return false; // attempting to escape parent } level--; + wasParentRef = true; } } - level++; + if (!wasParentRef) + { + level++; + } } } return true; diff --git a/tests/aws-cpp-sdk-transfer-tests/TransferTests.cpp b/tests/aws-cpp-sdk-transfer-tests/TransferTests.cpp index 8bb3f6ed4201..795d2f26168e 100644 --- a/tests/aws-cpp-sdk-transfer-tests/TransferTests.cpp +++ b/tests/aws-cpp-sdk-transfer-tests/TransferTests.cpp @@ -2326,7 +2326,12 @@ TEST_P(TransferTests, TransferManager_TestRelativePrefix) {R"(./)", R"(./.../foo)", true}, {R"(./)", R"(./.../../foo)", true}, {R"(./)", R"(.//.../../foo)", true}, - {R"(./)", R"(.////../test)", false} + {R"(./)", R"(.////../test)", false}, + + {R"(/home/user/dl)", R"(/home/user/dl/safe/../../etc/passwd)", false}, + {R"(/home/user/dl)", R"(/home/user/dl/x/../../../etc/passwd)", false}, + {R"(/home/user/dl)", R"(/home/user/dl/a/b/c/../../../../etc/passwd)", false}, + {R"(/tmp/download)", R"(/tmp/download/subdir/../../../../../../etc/cron.d/evil)", false} }; for(const TestHelperTransferManager::TestCaseEntry& TC_ENTRY : TEST_CASES)