CVE-2021-32814 (Rust, published 2021-08-03T17:15Z)
Description: value: Skytable is a NoSQL database with automated snapshots and TLS. Versions prior to 0.5.1 are vulnerable to a a directory traversal attack enabling remotely connected clients to destroy and/or manipulate critical files on the host's file system. This security bug has been patched in version 0.5.1. There are no known workarounds aside from upgrading.
Severity: HIGH (CVSS v3 base score: 8.1)
Weakness: CWE-22 \u2014 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
Repository: https://github.com/skytable/skytable
Files changed:
.gitignore
.idea/workspace.xml
Cargo.lock
cli/Cargo.toml
libtdb/Cargo.toml
server/Cargo.toml
server/src/admin/mksnap.rs
server/src/cli.yml
server/src/dbnet.rs
server/src/tests/kvengine.rs
tdb-bench/Cargo.toml
tdb-bench/src/cli.yml
tdb-bench/src/main.rs
tdb-macros/Cargo.toml
tdb-macros/src/lib.rs
Commit message: Add fix and tests for VE/S/00001
This commit now checks if the second value passed to MKSNAP points
to any parent/root directory before performing any action.

Signed-off-by: Sayan Nandan <nandansayan@outlook.com>


Vulnerable code:
snapstore.partmap
version = "0.6.0"
checksum = "e0dcbc35f504eb6fc275a6d20e4ebcda18cf50d40ba6fabff8c711fa16cb3b16"
version = "4.0.0"
checksum = "6035b7b9244bf9637cd7ef80b5e1c54404bef92cccd34738c85c45f04ae8b244"
version = "0.8.2"
checksum = "f26ecb66b4bdca6c1409b40fb255eefc2bd4f6d135dab3c3124f80ffa2a9661e"
[[package]]
name = "futures-core"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399"

version = "0.1.15"
checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
 "cfg-if",
 "wasi 0.9.0+wasi-snapshot-preview1",
version = "0.4.11"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
 "cfg-if",
 "cfg-if",
version = "1.0.7"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
version = "0.7.3"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
 "getrandom",
version = "0.2.2"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
version = "0.5.1"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
version = "0.2.0"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
version = "1.4.2"
checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
version = "0.6.21"
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
version = "1.0.118"
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
version = "1.0.118"
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
version = "1.0.60"
checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779"
[[package]]
name = "slab"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"

 "cfg-if",
version = "1.0.54"
checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
 "wasi 0.10.0+wasi-snapshot-preview1",
version = "0.3.6"
checksum = "720ba21c25078711bf456d607987d95bce90f7c3bea5abe1db587862e7a1e87c"
 "futures-core",
 "slab",
version = "0.3.1"
checksum = "21d30fdbb5dc2d8f91049691aa1a9d4d4ae422a21c334ce8936e5886d30c5c45"
version = "0.5.7"
checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645"
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"

tokio = {version = "0.3.6", features = ["full"]}
bytes = "0.6.0"
regex = "1.4.2"
bytes = "0.6.0"
termcolor = "1.1.1"
tokio = { version = "0.3.6", features = ["full"] }
bytes = "0.6.0"
serde_derive = "1.0.117"
serde = {version = "1.0.118", features= ["derive"]}
toml = "0.5.7"
env_logger = "0.8.2"
log = "0.4.11"
regex = "1.4.2"
tokio = { version = "0.3.6", features = ["test-util"] }
use std::path::PathBuf;
}
name: TerrabaseDB Server
about: The TerrabaseDB Database server
            self.climit.acquire().await.forget();
    use tokio::io::AsyncReadExt;
    use tokio::prelude::*;
        use tokio::prelude::*;
rand = "0.7.3"
devtimer = "4.0.0"
serde = {version="1.0.118", features=["derive"]}
serde_json = "1.0.60"
name: TerrabaseDB Benchmark Tool
version: 0.5.0
        The TerrabaseDB benchmark tool can be used to benchmark TerrabaseDB installations. 
        If you find any issues, then report one here: https://github.com/terrabasedb/terrabasedb
 * This file is a part of TerrabaseDB
    use rand::{thread_rng, Rng};
        let rand = thread_rng();
                    .map(|_| {
                        let rand_string: String = rand.sample_iter(&Alphanumeric).take(8).collect();
                        rand_string
                    })
                    .map(|_| {
                        let rand_string: String = rand.sample_iter(&Alphanumeric).take(8).collect();
                        rand_string
                    })
        let rand = thread_rng();
            .map(|_| {
                let rand_string: String =
                    rand.sample_iter(&Alphanumeric).take(packet_size).collect();
                rand_string
            })
            .map(|_| {
                let rand_string: String =
                    rand.sample_iter(&Alphanumeric).take(packet_size).collect();
                rand_string
            })
}
syn = {version = "1.0.54", features = ["full"]}
quote = "1.0.7"
rand = "0.7.3"
        stream.shutdown(::std::net::Shutdown::Write).unwrap();
        let mut rand: u16 = rng.gen_range(1025, 65535);
                rand = rng.gen_range(1025, 65535);
                rand = rng.gen_range(1025, 65535);

Fixed code:
snapstore.partmap
/snapshots 
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true">
    <generated />
  </component>
  <component name="CMakeSettings">
    <configurations>
      <configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" ENABLED="true" />
    </configurations>
  </component>
  <component name="CargoProjects">
    <cargoProject FILE="$PROJECT_DIR$/Cargo.toml" />
  </component>
  <component name="ChangeListManager">
    <list default="true" id="05446e12-25fb-4f56-ae52-664b69a61212" name="Default Changelist" comment="">
      <change beforePath="$PROJECT_DIR$/server/src/main.rs" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/main.rs" afterDir="false" />
    </list>
    <option name="SHOW_DIALOG" value="false" />
    <option name="HIGHLIGHT_CONFLICTS" value="true" />
    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
    <option name="LAST_RESOLUTION" value="IGNORE" />
  </component>
  <component name="ClangdSettings">
    <option name="formatViaClangd" value="false" />
  </component>
  <component name="Git.Settings">
    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
  </component>
  <component name="GitSEFilterConfiguration">
    <file-type-list>
      <filtered-out-file-type name="LOCAL_BRANCH" />
      <filtered-out-file-type name="REMOTE_BRANCH" />
      <filtered-out-file-type name="TAG" />
      <filtered-out-file-type name="COMMIT_BY_MESSAGE" />
    </file-type-list>
  </component>
  <component name="MacroExpansionManager">
    <option name="directoryName" value="k3yyr5y2" />
  </component>
  <component name="ProjectId" id="1mjP2LZbFlEc2swjliVmxauGK9Q" />
  <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
  <component name="ProjectViewState">
    <option name="hideEmptyMiddlePackages" value="true" />
    <option name="showLibraryContents" value="true" />
    <option name="showVisibilityIcons" value="true" />
  </component>
  <component name="PropertiesComponent">
    <property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
    <property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
    <property name="WebServerToolWindowFactoryState" value="false" />
    <property name="cf.first.check.clang-format" value="false" />
    <property name="last_opened_file_path" value="$PROJECT_DIR$" />
    <property name="nodejs_package_manager_path" value="npm" />
    <property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" />
  </component>
  <component name="RustProjectSettings">
    <option name="toolchainHomeDirectory" value="$USER_HOME$/.cargo/bin" />
  </component>
  <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
  <component name="TaskManager">
    <task active="true" id="Default" summary="Default task">
      <changelist id="05446e12-25fb-4f56-ae52-664b69a61212" name="Default Changelist" comment="" />
      <created>1610003825159</created>
      <option name="number" value="Default" />
      <option name="presentableId" value="Default" />
      <updated>1610003825159</updated>
      <workItem from="1610003832233" duration="85000" />
      <workItem from="1610003959549" duration="724000" />
    </task>
    <servers />
  </component>
  <component name="TypeScriptGeneratedFilesManager">
    <option name="version" value="3" />
  </component>
</project>
version = "1.0.1"
checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"

version = "4.0.1"
checksum = "907339959a92f6b98846570500c0a567c9aecbb3871cef00561eb5d20d47b7c1"
version = "0.8.3"
checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f"
version = "0.2.2"
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
 "cfg-if 1.0.0",
 "wasi",
version = "0.4.14"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
 "cfg-if 1.0.0",
 "cfg-if 0.1.10",
version = "1.0.9"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
version = "0.8.3"
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
version = "0.3.0"
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
version = "0.6.2"
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
version = "0.3.0"
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
version = "1.4.3"
checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
version = "0.6.22"
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
version = "1.0.123"
checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
version = "1.0.123"
checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
version = "1.0.62"
checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
 "cfg-if 0.1.10",
version = "1.0.60"
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
 "wasi",
version = "1.2.0"
checksum = "e8190d04c665ea9e6b6a0dc45523ade572c088d2e6566244c1122671dbf4ae3a"
version = "1.1.0"
checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57"
version = "0.5.8"
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
tokio = {version = "1.2.0", features = ["full"]}
bytes = "1.0.1"
regex = "1.4.3"
bytes = "1.0.1"
termcolor = "1.1.2"
tokio = { version = "1.2.0", features = ["full"] }
bytes = "1.0.1"
serde_derive = "1.0.123"
serde = {version = "1.0.123", features= ["derive"]}
toml = "0.5.8"
env_logger = "0.8.3"
log = "0.4.14"
regex = "1.4.3"
tokio = { version = "1.2.0", features = ["test-util"] }
use std::path::{Component, PathBuf};
            let illegal_snapshot = path
                .components()
                .filter(|dir| {
                    // Sanitize snapshot name, to avoid directory traversal attacks
                    // If the snapshot name has any root directory or parent directory, then
                    // we'll allow it to pass through this adaptor.
                    // As a result, this iterator will give us a count of the 'bad' components
                    dir == &Component::RootDir || dir == &Component::ParentDir
                })
                .count()
                != 0;
            if illegal_snapshot {
                con.write_response(GroupBegin(1)).await?;
                return con
                    .write_response(RespCodes::OtherError(Some(
                        "err-invalid-snapshot-name".to_owned(),
                    )))
                    .await;
            }
}
name: Skybase Server
about: The Skybase Database server
            self.climit.acquire().await.unwrap().forget();
    use tokio::io::{AsyncReadExt, AsyncWriteExt};
    async fn test_mksnap_sanitization() {
        let res_should_be = "#2\n*1\n#2\n&1\n!25\nerr-invalid-snapshot-name\n"
            .to_owned()
            .into_bytes();
        // First check parent directory syntax
        let query = terrapipe::proc_query("MKSNAP ../../badsnappy");
        stream.write_all(&query).await.unwrap();
        let mut response = vec![0; res_should_be.len()];
        stream.read_exact(&mut response).await.unwrap();
        assert_eq!(res_should_be, response);
        // Now check root directory syntax
        let query = terrapipe::proc_query("MKSNAP /var/omgcrazysnappy");
        stream.write_all(&query).await.unwrap();
        let mut response = vec![0; res_should_be.len()];
        stream.read_exact(&mut response).await.unwrap();
        assert_eq!(res_should_be, response);
    }
rand = "0.8.3"
devtimer = "4.0.1"
serde = {version="1.0.123", features=["derive"]}
serde_json = "1.0.62"
name: Skybase Benchmark Tool
version: 0.5-hotfix.1
        The Skybase benchmark tool can be used to benchmark Skybase installations. 
        If you find any issues, then report one here: https://github.com/skybasedb/skybase
 * This file is a part of Skybase
    use rand::thread_rng;
        let mut rand = thread_rng();
                    .map(|_| ran_string(8, &mut rand))
                    .map(|_| ran_string(8, &mut rand))
        let mut rand = thread_rng();
            .map(|_| ran_string(packet_size, &mut rand))
            .map(|_| ran_string(packet_size, &mut rand))

    fn ran_string(len: usize, rand: impl rand::Rng) -> String {
        let rand_string: String = rand
            .sample_iter(&Alphanumeric)
            .take(len)
            .map(char::from)
            .collect();
        rand_string
    }
}
syn = {version = "1.0.60", features = ["full"]}
quote = "1.0.9"
rand = "0.8.3"
        stream.shutdown().await.unwrap();
        let mut rand: u16 = rng.gen_range(1025..=65535);
                rand = rng.gen_range(1025..=65535);
                rand = rng.gen_range(1025..=65535);