Fixes #1497 ZCA-009 by restricting data exporting to user defined folder.

Previously the RPC interface allowed z_exportwallet, backupwallet and
dumpwallet to write data to an arbitrary filename.  ZCA-009 demonstrates
how this is vulnerable.  The resolution is to only allow data to
written when the -exportdir has been configured.  Also filenames are
restricted to alphanumeric characters.
This commit is contained in:
Simon
2017-01-09 21:25:42 -08:00
parent 57a0725ae1
commit 9064d73bf8
8 changed files with 104 additions and 17 deletions

View File

@@ -1766,21 +1766,38 @@ Value backupwallet(const Array& params, bool fHelp)
if (fHelp || params.size() != 1)
throw runtime_error(
"backupwallet \"destination\"\n"
"\nSafely copies wallet.dat to destination, which can be a directory or a path with filename.\n"
"\nSafely copies wallet.dat to destination filename\n"
"\nArguments:\n"
"1. \"destination\" (string) The destination directory or file\n"
"1. \"destination\" (string, required) The destination filename, saved in the directory set by -exportdir option.\n"
"\nResult:\n"
"\"path\" (string) The full path of the destination file\n"
"\nExamples:\n"
+ HelpExampleCli("backupwallet", "\"backup.dat\"")
+ HelpExampleRpc("backupwallet", "\"backup.dat\"")
+ HelpExampleCli("backupwallet", "\"backupdata\"")
+ HelpExampleRpc("backupwallet", "\"backupdata\"")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
string strDest = params[0].get_str();
if (!BackupWallet(*pwalletMain, strDest))
boost::filesystem::path exportdir;
try {
exportdir = GetExportDir();
} catch (const std::runtime_error& e) {
throw JSONRPCError(RPC_INTERNAL_ERROR, e.what());
}
if (exportdir.empty()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot backup wallet until the -exportdir option has been set");
}
std::string unclean = params[0].get_str();
std::string clean = SanitizeFilename(unclean);
if (clean.compare(unclean) != 0) {
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Filename is invalid as only alphanumeric characters are allowed. Try '%s' instead.", clean));
}
boost::filesystem::path exportfilepath = exportdir / clean;
if (!BackupWallet(*pwalletMain, exportfilepath.string()))
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
return Value::null;
return exportfilepath.string();
}