Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix vulnerabilities #317

Merged
merged 2 commits into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/crow/http_response.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ namespace crow
///Return a static file as the response body
void set_static_file_info(std::string path)
{
utility::sanitize_filename(path);
file_info.path = path;
file_info.statResult = stat(file_info.path.c_str(), &file_info.statbuf);
#ifdef CROW_ENABLE_COMPRESSION
Expand Down
8 changes: 7 additions & 1 deletion include/crow/mustache.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <functional>
#include "crow/json.h"
#include "crow/logging.h"
#include "crow/utility.h"

namespace crow
{
namespace mustache
Expand Down Expand Up @@ -144,6 +146,8 @@ namespace crow
case '"': out += "&quot;"; break;
case '\'': out += "&#39;"; break;
case '/': out += "&#x2F;"; break;
case '`': out += "&#x60"; break;
case '=': out += "&#x3D"; break;
default: out += *it; break;
}
}
Expand Down Expand Up @@ -633,7 +637,9 @@ namespace crow

inline template_t load(const std::string& filename)
{
return compile(detail::get_loader_ref()(filename));
std::string filename_sanitized(filename);
utility::sanitize_filename(filename_sanitized);
return compile(detail::get_loader_ref()(filename_sanitized));
}
} // namespace mustache
} // namespace crow
128 changes: 128 additions & 0 deletions include/crow/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@
#include <string>
#include <unordered_map>

#include <boost/algorithm/string.hpp>

#include "crow/settings.h"

namespace crow
{
namespace black_magic
{
#ifndef CROW_MSVC_WORKAROUND
/// Out of Range Exception for const_str
struct OutOfRange
{
OutOfRange(unsigned /*pos*/, unsigned /*length*/) {}
};
/// Helper function to throw an exception if i is larger than len
constexpr unsigned requires_in_range(unsigned i, unsigned len)
{
return i >= len ? throw OutOfRange(i, len) : i;
Expand Down Expand Up @@ -62,6 +66,7 @@ namespace crow
return s[p] == '>' ? p : find_closing_tag(s, p + 1);
}

/// Check that the CROW_ROUTE string is valid
constexpr bool is_valid(const_str s, unsigned i = 0, int f = 0)
{
return i == s.size() ? f == 0 :
Expand Down Expand Up @@ -613,5 +618,128 @@ namespace crow
return base64decode(data.c_str(), size, urlsafe);
}

inline static void sanitize_filename(std::string& data, char replacement = '_')
{
unsigned char i = 0, length_limit;

length_limit = data.length() < 255 ? data.length() : 255;
data = data.substr(0, length_limit);

for (; i < length_limit; i++)
{
switch ((unsigned char)data[i])
{
// WARNING While I can't see how using '\' or '/' would cause a problem, it still warrants an investigation
//case '/':
case '?':
case '<':
case '>':
//case '\\':
case ':':
case '*':
case '|':
case '\"':

case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
case 0x18:
case 0x19:
case 0x1a:
case 0x1b:
case 0x1c:
case 0x1d:
case 0x1e:
case 0x1f:

case 0x80:
case 0x81:
case 0x82:
case 0x83:
case 0x84:
case 0x85:
case 0x86:
case 0x87:
case 0x88:
case 0x89:
case 0x8a:
case 0x8b:
case 0x8c:
case 0x8d:
case 0x8e:
case 0x8f:
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
case 0x98:
case 0x99:
case 0x9a:
case 0x9b:
case 0x9c:
case 0x9d:
case 0x9e:
case 0x9f:

data[i] = replacement;
break;

default:
break;
}
}
std::string str_replacement(1, replacement);

boost::ireplace_all(data, "..", str_replacement);

boost::ireplace_all(data, "CON", str_replacement);
boost::ireplace_all(data, "PRN", str_replacement);
boost::ireplace_all(data, "AUX", str_replacement);
boost::ireplace_all(data, "NUL", str_replacement);
boost::ireplace_all(data, "COM1", str_replacement);
boost::ireplace_all(data, "COM2", str_replacement);
boost::ireplace_all(data, "COM3", str_replacement);
boost::ireplace_all(data, "COM4", str_replacement);
boost::ireplace_all(data, "COM5", str_replacement);
boost::ireplace_all(data, "COM6", str_replacement);
boost::ireplace_all(data, "COM7", str_replacement);
boost::ireplace_all(data, "COM8", str_replacement);
boost::ireplace_all(data, "COM9", str_replacement);
boost::ireplace_all(data, "LPT1", str_replacement);
boost::ireplace_all(data, "LPT2", str_replacement);
boost::ireplace_all(data, "LPT3", str_replacement);
boost::ireplace_all(data, "LPT4", str_replacement);
boost::ireplace_all(data, "LPT5", str_replacement);
boost::ireplace_all(data, "LPT6", str_replacement);
boost::ireplace_all(data, "LPT7", str_replacement);
boost::ireplace_all(data, "LPT8", str_replacement);
boost::ireplace_all(data, "LPT9", str_replacement);
}

} // namespace utility
} // namespace crow