Skip to content

Commit 0e9aa2e

Browse files
authored
fix#1165: sanitize header values to prevent injection and add helloworld_inject example (#1167)
1 parent 7e3ed0b commit 0e9aa2e

4 files changed

Lines changed: 36 additions & 0 deletions

File tree

examples/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ add_executable(helloworld helloworld.cpp)
77
add_warnings_optimizations(helloworld)
88
target_link_libraries(helloworld PUBLIC Crow::Crow)
99

10+
add_executable(helloworld_inject helloworld_inject.cpp)
11+
add_warnings_optimizations(helloworld_inject)
12+
target_link_libraries(helloworld_inject PUBLIC Crow::Crow)
13+
1014
# If compression is enabled, the example will be built
1115
if("compression" IN_LIST CROW_FEATURES)
1216
add_executable(example_compression example_compression.cpp)

examples/helloworld_inject.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include "crow.h"
2+
3+
int main()
4+
{
5+
crow::SimpleApp app;
6+
7+
CROW_ROUTE(app, "/")
8+
([](const crow::request &req, crow::response& res) {
9+
res.write("Hello, world!");
10+
res.set_header("X-Custom", "safe\r\nInjected: yes");
11+
res.end();
12+
//return "Hello, world!";
13+
});
14+
15+
app.port(18080).run();
16+
}

include/crow/http_request.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <asio.hpp>
1010
#endif
1111

12+
#include <algorithm>
13+
1214
#include "crow/common.h"
1315
#include "crow/ci_map.h"
1416
#include "crow/query_string.h"
@@ -19,6 +21,14 @@ namespace crow // NOTE: Already documented in "crow/app.h"
1921
namespace asio = boost::asio;
2022
#endif
2123

24+
/// Remove CR (\r) and LF (\n) characters from a header name or value to prevent header injection.
25+
inline void sanitize_header_value(std::string& s)
26+
{
27+
s.erase(std::remove_if(s.begin(), s.end(),
28+
[](char c) { return c == '\r' || c == '\n'; }),
29+
s.end());
30+
}
31+
2232
/// Find and return the value associated with the key. (returns an empty string if nothing is found)
2333
inline const std::string& get_header_value(const ci_map& headers, const std::string& key)
2434
{
@@ -63,6 +73,8 @@ namespace crow // NOTE: Already documented in "crow/app.h"
6373

6474
void add_header(std::string key, std::string value)
6575
{
76+
sanitize_header_value(key);
77+
sanitize_header_value(value);
6678
headers.emplace(std::move(key), std::move(value));
6779
}
6880

include/crow/http_response.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,17 @@ namespace crow
5959
/// Set the value of an existing header in the response.
6060
void set_header(std::string key, std::string value)
6161
{
62+
sanitize_header_value(key);
63+
sanitize_header_value(value);
6264
headers.erase(key);
6365
headers.emplace(std::move(key), std::move(value));
6466
}
6567

6668
/// Add a new header to the response.
6769
void add_header(std::string key, std::string value)
6870
{
71+
sanitize_header_value(key);
72+
sanitize_header_value(value);
6973
headers.emplace(std::move(key), std::move(value));
7074
}
7175

0 commit comments

Comments
 (0)