Skip to content

Commit

Permalink
HPCC-32999 Sanitize user provided password to ZAP file
Browse files Browse the repository at this point in the history
- Single-quote the entire password to preserve all characters but prevent
  interpretation as metacharacters.
- Replace any single quote in the original string with a sequence of characters
  that breaks the single-quoted password into three parts
    (1) a single-quoted prefix
    (2) a double-quoted single quote and
    (3) a single-quoted suffix
- The shell quote-removal deletes double-quotes around any single quote at the
  same time that it de-quotes the single-quoted prefix and suffix, leaving any
  single quote inside the password string that is tokenized as a single
  argument.

This will require a different approach for Windows targets as a future task.

Signed-off-by: Terrence Asselin <[email protected]>
  • Loading branch information
asselitx committed Dec 12, 2024
1 parent 858a57e commit 1c60d2e
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 1 deletion.
6 changes: 5 additions & 1 deletion esp/services/ws_workunits/ws_workunitsHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4386,7 +4386,11 @@ void CWsWuFileHelper::zipZAPFiles(const char* parentFolder, const char* zapFiles
else
zipCommand.setf("cd %s\nzip -r", parentFolder);
if (!isEmptyString(passwordReq))
zipCommand.append(" --password ").append(passwordReq);
{
StringBuffer sanitizedPassword;
sanitizeCommandArg(passwordReq, sanitizedPassword);
zipCommand.append(" --password ").append(sanitizedPassword);
}
zipCommand.append(" ").append(zipFileNameWithFullPath).append(" ").append(zapFiles);
int zipRet = system(zipCommand);
if (zipRet != 0)
Expand Down
29 changes: 29 additions & 0 deletions system/jlib/jstring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2902,3 +2902,32 @@ const char * stristr (const char *haystack, const char *needle)

return nullptr;
}

/**
* For preventing command injection, sanitize the argument to be passed to the system command.
* - Quote the entire argument with single quotes to prevent interpretation of shell metacharacters.
* - Since a single-quoted string can't contain single quotes, even escaped, replace each single
* quote in the argument with the sequence '"'"' . That closes the single quoted string, appends
* a literal single quote, and reopens the single quoted string
*/
StringBuffer& sanitizeCommandArg(const char* arg, StringBuffer& sanitized)
{
#if defined(__linux__) || defined(__APPLE__)
if (!isEmptyString(arg))
{
size_t len = strlen(arg);
sanitized.append('\'');
for (size_t i = 0; i < len; i++)
{
if (arg[i] == '\'')
sanitized.append(R"('"'"')");
else
sanitized.append(arg[i]);
}
sanitized.append('\'');
}
#else
sanitized.append(arg);
#endif
return sanitized;
}
3 changes: 3 additions & 0 deletions system/jlib/jstring.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,4 +641,7 @@ extern jlib_decl void processOptionString(const char * options, optionCallback c

extern jlib_decl const char * stristr(const char *haystack, const char *needle);

// For preventing command injection, sanitize the argument to be passed to the system command
extern jlib_decl StringBuffer& sanitizeCommandArg(const char* arg, StringBuffer& sanitized);

#endif

0 comments on commit 1c60d2e

Please sign in to comment.