From 513b3863d999f91b47d7e9f26710390db55f9463 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" <Jason@zx2c4.com> Date: Thu, 14 Jan 2016 14:28:37 +0100 Subject: ui-shared: prevent malicious filename from injecting headers --- html.c | 26 ++++++++++++++++++++++++++ html.h | 1 + ui-shared.c | 8 +++++--- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/html.c b/html.c index 959148c..d89df3a 100644 --- a/html.c +++ b/html.c @@ -239,6 +239,32 @@ void html_url_arg(const char *txt) html(txt); } +void html_header_arg_in_quotes(const char *txt) +{ + const char *t = txt; + while (t && *t) { + unsigned char c = *t; + const char *e = NULL; + if (c == '\\') + e = "\\\\"; + else if (c == '\r') + e = "\\r"; + else if (c == '\n') + e = "\\n"; + else if (c == '"') + e = "\\\""; + if (e) { + html_raw(txt, t - txt); + html(e); + txt = t + 1; + } + t++; + } + if (t != txt) + html(txt); + +} + void html_hidden(const char *name, const char *value) { html("<input type='hidden' name='"); diff --git a/html.h b/html.h index c554763..c72e845 100644 --- a/html.h +++ b/html.h @@ -23,6 +23,7 @@ extern void html_ntxt(int len, const char *txt); extern void html_attr(const char *txt); extern void html_url_path(const char *txt); extern void html_url_arg(const char *txt); +extern void html_header_arg_in_quotes(const char *txt); extern void html_hidden(const char *name, const char *value); extern void html_option(const char *value, const char *text, const char *selected_value); extern void html_intoption(int value, const char *text, int selected_value); diff --git a/ui-shared.c b/ui-shared.c index 21f581f..54bbde7 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -692,9 +692,11 @@ void cgit_print_http_headers(void) htmlf("Content-Type: %s\n", ctx.page.mimetype); if (ctx.page.size) htmlf("Content-Length: %zd\n", ctx.page.size); - if (ctx.page.filename) - htmlf("Content-Disposition: inline; filename=\"%s\"\n", - ctx.page.filename); + if (ctx.page.filename) { + html("Content-Disposition: inline; filename=\""); + html_header_arg_in_quotes(ctx.page.filename); + html("\"\n"); + } if (!ctx.env.authenticated) html("Cache-Control: no-cache, no-store\n"); htmlf("Last-Modified: %s\n", http_date(ctx.page.modified)); -- cgit 1.4.1-3-g733a5