From 85399d2b28ba0bbd3b66e1ab50fde43a9f301f68 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Oct 2018 12:38:19 +0200 Subject: aptwebserver: Prevent XSS in debug and file listing We sometimes autogenerate HTML pages e.g. for listing files in a directory or for various error codes. If this would be a serious webserver this would be a security problem (althrough a bit hard to exploit), but as it is not shipped and intended to be used by our testcases only the world hasn't ended & we can ignore it for changelog and fix it for brownie points. Gbp-Dch: Ignore --- test/interactive-helper/aptwebserver.cc | 60 ++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc index 4eebcaaeb..5da715253 100644 --- a/test/interactive-helper/aptwebserver.cc +++ b/test/interactive-helper/aptwebserver.cc @@ -31,6 +31,21 @@ #include #include +static std::string HTMLEncode(std::string encode) /*{{{*/ +{ + constexpr std::array,6> htmlencode = {{ + {{ "&", "&" }}, + {{ "<", "<" }}, + {{ ">", ">" }}, + {{ "\"", """ }}, + {{ "'", "'" }}, + {{ "/", "/" }}, + }}; + for (auto &&h: htmlencode) + encode = SubstVar(encode, h[0], h[1]); + return encode; +} + /*}}}*/ static std::string httpcodeToStr(int const httpcode) /*{{{*/ { switch (httpcode) @@ -250,22 +265,23 @@ static bool sendData(int const client, std::list const &headers, st static void sendError(std::ostream &log, int const client, int const httpcode, std::string const &request,/*{{{*/ bool const content, std::string const &error, std::list &headers) { + auto const quotedCode = HTMLEncode(httpcodeToStr(httpcode)); std::string response(""); - response.append(httpcodeToStr(httpcode)).append(""); - response.append("

").append(httpcodeToStr(httpcode)).append("

"); + response.append(quotedCode).append(""); + response.append("

").append(quotedCode).append("

"); if (httpcode != 200) response.append("

Error: "); else response.append("

Success: "); if (error.empty() == false) - response.append(error); + response.append(HTMLEncode(error)); else - response.append(httpcodeToStr(httpcode)); + response.append(quotedCode); if (httpcode != 200) response.append("

This error is a result of the request:
");
    else
       response.append("The successfully executed operation was requested by: 
");
-   response.append(request).append("
"); + response.append(HTMLEncode(request)).append("
"); if (httpcode != 200) { if (_config->FindB("aptwebserver::closeOnError", false) == true) @@ -290,12 +306,13 @@ static void sendRedirect(std::ostream &log, int const client, int const httpcode std::string const &uri, std::string const &request, bool content) { std::list headers; + auto const quotedCode = HTMLEncode(httpcodeToStr(httpcode)); std::string response(""); - response.append(httpcodeToStr(httpcode)).append(""); - response.append("

").append(httpcodeToStr(httpcode)).append("You should be redirected to ").append(uri).append("

"); + response.append(quotedCode).append(""); + response.append("

").append(quotedCode).append("You should be redirected to ").append(HTMLEncode(uri)).append("

"); response.append("This page is a result of the request:
");
-   response.append(request).append("
"); + response.append(HTMLEncode(request)).append(""); addDataHeaders(headers, response); std::string location("Location: "); if (strncmp(uri.c_str(), "http://", 7) != 0 && strncmp(uri.c_str(), "https://", 8) != 0) @@ -380,13 +397,14 @@ static void sendDirectoryListing(std::ostream &log, int const client, std::strin } std::ostringstream listing; - listing << "Index of " << dir << "" + std::string const quotedDir = HTMLEncode(dir); + listing << "Index of " << quotedDir << "" << "" << "" << std::endl - << "

Index of " << dir << "

" << std::endl + << "

Index of " << quotedDir << "

" << std::endl << "" << std::endl; if (dir != "./") listing << ""; @@ -395,19 +413,13 @@ static void sendDirectoryListing(std::ostream &log, int const client, std::strin std::string filename(dir); filename.append("/").append(namelist[i]->d_name); stat(filename.c_str(), &fs); - if (S_ISDIR(fs.st_mode)) - { - listing << "" - << "" - << ""; - } - else - { - listing << "" - << "" - << ""; - } - listing << "" << std::endl; + std::string const quotedHref = QuoteString(namelist[i]->d_name, "\"\\/#?"); + std::string const quotedName = HTMLEncode(namelist[i]->d_name); + bool const isDir = S_ISDIR(fs.st_mode); + listing << "" + << "" + << "" + << "\n"; } listing << "
#NameSizeLast-Modified
dParent Directory--
dd_name << "/\">" << namelist[i]->d_name << "-
fd_name << "\">" << namelist[i]->d_name << "" << SizeToStr(fs.st_size) << "B" << TimeRFC1123(fs.st_mtime, true) << "
" << (isDir ? 'd' : 'f') << "" << quotedName << "" << (isDir ? "-" : SizeToStr(fs.st_size).append("B")) << "" << TimeRFC1123(fs.st_mtime, true) << "
" << std::endl; -- cgit v1.2.3-70-g09d2