From fd79b337ca4618d9cf2ac7b37db98f81d97ffab2 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Tue, 23 May 2023 15:17:59 -0600 Subject: [PATCH] datasets: don't allow absolute or paths with directory traversal For dataset filenames coming from rules, do not allow filenames that are absolute or contain a directory traversal with "..". This prevents datasets from escaping the define data-directory which may allow a bad rule to overwrite any file that Suricata has permission to write to. Add a new configuration option, "datasets.rules.allow-absolute-filenames" to allow absolute filenames in dataset rules. This will be a way to revert back to the pre 6.0.13 behavior where save/state rules could use any filename. Ticket: #6118 --- src/detect-dataset.c | 16 ++++++++++++++-- src/util-path.c | 17 +++++++++++++++++ src/util-path.h | 1 + suricata.yaml.in | 6 ++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/detect-dataset.c b/src/detect-dataset.c index 27792c083b..56bbf2689d 100644 --- a/src/detect-dataset.c +++ b/src/detect-dataset.c @@ -303,8 +303,20 @@ static int SetupSavePath(const DetectEngineCtx *de_ctx, { SCLogDebug("save %s", save); - if (PathIsAbsolute(save)) { - return 0; + int allow_absolute = 0; + (void)ConfGetBool("datasets.rules.allow-absolute-filenames", &allow_absolute); + if (allow_absolute) { + SCLogNotice("Allowing absolute filename for dataset rule: %s", save); + } else { + if (PathIsAbsolute(save)) { + SCLogError("Absolute paths not allowed: %s", save); + return -1; + } + + if (SCPathContainsTraversal(save)) { + SCLogError("Directory traversals not allowed: %s", save); + return -1; + } } // data dir diff --git a/src/util-path.c b/src/util-path.c index ad78f4f678..8182109c68 100644 --- a/src/util-path.c +++ b/src/util-path.c @@ -246,3 +246,20 @@ const char *SCBasename(const char *path) return final + 1; } + +/** + * \brief Check for directory traversal + * + * \param path The path string to check for traversal + * + * \retval true if directory traversal is found, otherwise false + */ +bool SCPathContainsTraversal(const char *path) +{ +#ifdef OS_WIN32 + const char *pattern = "..\\"; +#else + const char *pattern = "../"; +#endif + return strstr(path, pattern) != NULL; +} diff --git a/src/util-path.h b/src/util-path.h index 8030b3adb1..6f788a8f25 100644 --- a/src/util-path.h +++ b/src/util-path.h @@ -41,5 +41,6 @@ bool SCIsRegularDirectory(const struct dirent *const dir_entry); bool SCIsRegularFile(const struct dirent *const dir_entry); char *SCRealPath(const char *path, char *resolved_path); const char *SCBasename(const char *path); +bool SCPathContainsTraversal(const char *path); #endif /* __UTIL_PATH_H__ */ diff --git a/suricata.yaml.in b/suricata.yaml.in index 2b7fd3bef4..c748f0a564 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -1158,6 +1158,12 @@ asn1-max-frames: 256 # defaults: # memcap: 100mb # hashsize: 2048 +# +# rules: +# # Set to true to allow absolute filenames and filenames that use +# # ".." components to reference parent directories in rules that specify +# # their filenames. +# #allow-absolute-filenames: false ############################################################################## ##