From 17f3e7527ff52bf86a5764fcd51644ba5860dae6 Mon Sep 17 00:00:00 2001 From: Radovan Sroka Date: Sat, 22 Jan 2022 23:12:28 +0100 Subject: [PATCH] Use shell escaping for all string attributes - attributes like object's path (basically all strings) are escaped before logging to stdout/syslog --- src/library/escape.c | 51 ++++++++++++++++++++++++++++++++++++++-- src/library/escape.h | 6 +++-- src/library/policy.c | 9 +++++-- src/library/trust-file.c | 6 ++--- 4 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/library/escape.c b/src/library/escape.c index e4ab571..cb0b7a1 100644 --- a/src/library/escape.c +++ b/src/library/escape.c @@ -51,7 +51,7 @@ static char asciiHex2Bits(char X) * it returns NULL in case of error * */ -char *escape(const char *input, int mode) +char *escape_default(const char *input, int mode) { char buffer[4096 + 1] = {0}; size_t input_len = strlen(input); @@ -114,7 +114,7 @@ char *escape(const char *input, int mode) return strdup(buffer); } -char *unescape(const char *input) +char *unescape_default(const char *input) { char buffer[4096 + 1] = {0}; size_t input_len = strlen(input); @@ -157,3 +157,50 @@ char *unescape(const char *input) return strdup(buffer); } + + +static const char sh_set[] = "\"'`$\\!()| "; + +/* unsigned int need_escape_shell(const char *input) +{ + unsigned int len = strlen(input); + unsigned int i = 0, cnt = 0; + + while (i < len) { + if (input[i] < 32) + cnt++; + else if (strchr(sh_set, input[i])) + cnt++; + i++; + } + return cnt; +} +*/ + +char *escape_shell(const char *input) +{ + char buffer[4096 + 1] = {0}; + + if(!input) + return NULL; + + size_t len = strlen(input); + + unsigned int i = 0, j = 0; + while (i < len) { + if ((unsigned char)input[i] < 32) { + buffer[j++] = ('\\'); + buffer[j++] = ('0' + ((input[i] & 0300) >> 6)); + buffer[j++] = ('0' + ((input[i] & 0070) >> 3)); + buffer[j++] = ('0' + (input[i] & 0007)); + } else if (strchr(sh_set, input[i])) { + buffer[j++] = ('\\'); + buffer[j++] = input[i]; + } else + buffer[j++] = input[i]; + i++; + } + buffer[j] = '\0'; /* terminate string */ + + return strdup(buffer); +} diff --git a/src/library/escape.h b/src/library/escape.h index 0ac6497..de33e4a 100644 --- a/src/library/escape.h +++ b/src/library/escape.h @@ -32,8 +32,10 @@ enum { EVERYTHING }; -char *escape(const char *input, int mode) MALLOCLIKE; -char *unescape(const char *input) MALLOCLIKE; +char *escape_default(const char *input, int mode) MALLOCLIKE; +char *unescape_default(const char *input) MALLOCLIKE; + +char *escape_shell(const char *input); #endif diff --git a/src/library/policy.c b/src/library/policy.c index 0c204f6..fdeb5f6 100644 --- a/src/library/policy.c +++ b/src/library/policy.c @@ -32,6 +32,7 @@ #include #include +#include "escape.h" #include "file.h" #include "rules.h" #include "policy.h" @@ -283,8 +284,10 @@ static char *format_value(int item, unsigned int num, decision_t results, } else if (item >= OBJ_START) { object_attr_t *obj = get_obj_attr(e, item); if (item != OBJ_TRUST) { - if (asprintf(&out, "%s", obj ? obj->o : "?") < 0) + char * str = obj ? escape_shell(obj->o) : "?"; + if (asprintf(&out, "%s", str) < 0) out = NULL; + free(str); } else { if (asprintf(&out, "%d", obj ? (obj->val ? 1 : 0) : 9) < 0) out = NULL; @@ -295,8 +298,10 @@ static char *format_value(int item, unsigned int num, decision_t results, if (asprintf(&out, "%d", subj ? subj->val : -2) < 0) out = NULL; } else if (item >= COMM) { - if (asprintf(&out, "%s", subj ? subj->str : "?") < 0) + char * str = subj ? escape_shell(subj->str) : "?"; + if (asprintf(&out, "%s", str) < 0) out = NULL; + free(str); } else { // GID out = malloc(16*12); // gid's are limited to 16 if (out && subj->set) { diff --git a/src/library/trust-file.c b/src/library/trust-file.c index b115342..6e6eaae 100644 --- a/src/library/trust-file.c +++ b/src/library/trust-file.c @@ -98,7 +98,7 @@ static char *make_path_string(const char *path, int *count) char *line; if (*count) { - const char *escaped = escape(path, WHITESPACES); + const char *escaped = escape_default(path, WHITESPACES); if (escaped == NULL) { msg(LOG_ERR, "Could not escape %s", path); free(hash); @@ -157,7 +157,7 @@ static int write_out_list(list_t *list, const char *dest) for (list_item_t *lptr = list->first; lptr; lptr = lptr->next) { char buf[BUFFER_SIZE + 1]; const char *str = (char *)(lptr->data); - const char *escaped = escape((char *)lptr->index, WHITESPACES); + const char *escaped = escape_default((char *)lptr->index, WHITESPACES); if (escaped == NULL) { msg(LOG_ERR, "Could not escape %s: writing to %s", (char *)lptr->index, dest); continue; @@ -232,7 +232,7 @@ int trust_file_load(const char *fpath, list_t *list) if (asprintf(&data, DATA_FORMAT, tsource, sz, sha) == -1) data = NULL; - index = escaped ? unescape(name) : strdup(name); + index = escaped ? unescape_default(name) : strdup(name); if (index == NULL) { msg(LOG_ERR, "Could not unescape %s from %s", name, fpath); free(data); -- 2.34.1