remove securepath, simply reject relative paths: .., check / prefix - geomyidae - A small C-based gopherd. HTML git clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/ DIR Log DIR Files DIR Refs DIR Tags DIR README DIR LICENSE --- DIR commit 4028ae9814ff6ca97632004c67557e04ce639df3 DIR parent 3ed956cf71a15015b443dd7ab36299c242acd1af HTML Author: Hiltjo Posthuma <hiltjo@codemadness.org> Date: Fri, 30 Jun 2017 15:12:40 +0200 remove securepath, simply reject relative paths: .., check / prefix we could escape the path if for example the base dir was "base" and a secret directory starts with a name: "base.secret". The request ".secret/secretfile" would translate to "base.secret/secretfile". reject relative paths: securepath() currently converts paths from "/../file" to "/.//file" which won't work, so remove it. always check if a path starts with "/" or is empty. Signed-off-by: Christoph Lohmann <20h@r-36.net> Diffstat: M main.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) --- DIR diff --git a/main.c b/main.c @@ -82,28 +82,6 @@ dropprivileges(struct group *gr, struct passwd *pw) return 0; } -char * -securepath(char *p, int len) -{ - int i; - - if(len < 2) - return p; - - for(i = 1; i < strlen(p); i++) { - if(p[i - 1] == '.' && p[i] == '.') { - if(p[i - 2] == '/') - p[i] = '/'; - if(p[i + 1] == '/') - p[i] = '/'; - if(len == 2) - p[i] = '/'; - } - } - - return p; -} - void logentry(char *host, char *port, char *qry, char *status) { @@ -171,11 +149,12 @@ handlerequest(int sock, char *base, char *ohost, char *port, char *clienth, if(args != nil) *args++ = '\0'; - securepath(recvb, len - 2); - if(strlen(recvb) == 0) { + if(recvb[0] == '\0') { recvb[0] = '/'; recvb[1] = '\0'; } + if(recvb[0] != '/' || strstr(recvb, "..")) + return; snprintf(path, sizeof(path), "%s%s", base, recvb);