mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 05:45:59 +03:00
Adds support to SecResponseBodyMimeType
This commit is contained in:
parent
c2d9a153cb
commit
decf04d264
@ -194,6 +194,7 @@ class Assay {
|
||||
std::string *m_namesArgsGet;
|
||||
std::string *m_requestHeadersNames;
|
||||
std::string *m_responseHeadersNames;
|
||||
std::string *m_responseContentType;
|
||||
double m_ARGScombinedSize;
|
||||
/** TODO: Support to save double in the storage. */
|
||||
std::string *m_ARGScombinedSizeStr;
|
||||
|
@ -201,6 +201,7 @@ class RulesProperties {
|
||||
std::string audit_log_path;
|
||||
std::string audit_log_parts;
|
||||
std::list<std::string> components;
|
||||
std::set<std::string> m_responseBodyTypeToBeInspected;
|
||||
|
||||
DebugLog *m_debugLog;
|
||||
|
||||
|
33
src/assay.cc
33
src/assay.cc
@ -105,6 +105,7 @@ Assay::Assay(ModSecurity *ms, Rules *rules, void *logCbData)
|
||||
m_requestBodyType(UnknownFormat),
|
||||
m_requestHeadersNames(NULL),
|
||||
m_responseHeadersNames(NULL),
|
||||
m_responseContentType(NULL),
|
||||
m_marker(""),
|
||||
start(cpu_seconds()),
|
||||
m_logCbData(logCbData),
|
||||
@ -127,6 +128,10 @@ Assay::Assay(ModSecurity *ms, Rules *rules, void *logCbData)
|
||||
m_collections.store("RESPONSE_HEADERS_NAMES", std::string(""));
|
||||
this->m_responseHeadersNames = m_collections.resolveFirst(
|
||||
"RESPONSE_HEADERS_NAMES");
|
||||
m_collections.store("RESPONSE_CONTENT_TYPE", std::string(""));
|
||||
this->m_responseContentType = m_collections.resolveFirst(
|
||||
"RESPONSE_CONTENT_TYPE");
|
||||
|
||||
|
||||
#ifndef NO_LOGS
|
||||
this->debug(4, "Initialising transaction");
|
||||
@ -860,7 +865,7 @@ int Assay::addResponseHeader(const std::string& key,
|
||||
this->m_collections.store("RESPONSE_HEADERS:" + key, value);
|
||||
|
||||
if (tolower(key) == "content-type") {
|
||||
this->m_collections.store("RESPONSE_CONTENT_TYPE", value);
|
||||
this->m_responseContentType->assign(value);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -951,6 +956,21 @@ int Assay::processResponseBody() {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::set<std::string> &bi = this->m_rules->m_responseBodyTypeToBeInspected;
|
||||
auto t = bi.find(*m_responseContentType);
|
||||
if (t == bi.end() && bi.empty() == false) {
|
||||
#ifndef NO_LOGS
|
||||
debug(5, "Response Content-Type is " + *m_responseContentType + \
|
||||
". It is not marked to be inspected.");
|
||||
std::string validContetTypes("");
|
||||
for (std::set<std::string>::iterator i = bi.begin();
|
||||
i != bi.end(); i++) {
|
||||
validContetTypes.append(*i + " ");
|
||||
}
|
||||
debug(8, "Content-Type(s) marked to be inspected: " + validContetTypes);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
if (m_collections.resolveFirst("OUTBOUND_DATA_ERROR") == NULL) {
|
||||
m_collections.store("OUTBOUND_DATA_ERROR", "0");
|
||||
}
|
||||
@ -985,6 +1005,17 @@ int Assay::processResponseBody() {
|
||||
int Assay::appendResponseBody(const unsigned char *buf, size_t len) {
|
||||
int current_size = this->m_responseBody.tellp();
|
||||
|
||||
std::set<std::string> &bi = this->m_rules->m_responseBodyTypeToBeInspected;
|
||||
auto t = bi.find(*m_responseContentType);
|
||||
if (t == bi.end() && bi.empty() == false) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Not appending response body. " \
|
||||
"Response Content-Type is " + *m_responseContentType + \
|
||||
". It is not marked to be inspected.");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef NO_LOGS
|
||||
debug(9, "Appending response body: " + std::to_string(len + current_size)
|
||||
+ " bytes. Limit set to: " +
|
||||
|
@ -8,7 +8,8 @@
|
||||
%define parse.assert
|
||||
%code requires
|
||||
{
|
||||
# include <string>
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
|
||||
namespace ModSecurity {
|
||||
namespace Parser {
|
||||
@ -601,6 +602,16 @@ expression:
|
||||
| CONFIG_DIR_PCRE_MATCH_LIMIT_RECURSION
|
||||
| CONFIG_DIR_PCRE_MATCH_LIMIT
|
||||
| CONGIG_DIR_RESPONSE_BODY_MP
|
||||
{
|
||||
std::istringstream buf($1);
|
||||
std::istream_iterator<std::string> beg(buf), end;
|
||||
std::set<std::string> tokens(beg, end);
|
||||
for (std::set<std::string>::iterator it=tokens.begin();
|
||||
it!=tokens.end(); ++it)
|
||||
{
|
||||
driver.m_responseBodyTypeToBeInspected.insert(*it);
|
||||
}
|
||||
}
|
||||
| CONGIG_DIR_SEC_TMP_DIR
|
||||
| CONGIG_DIR_SEC_DATA_DIR
|
||||
| CONGIG_DIR_SEC_ARG_SEP
|
||||
|
@ -259,7 +259,7 @@ CONFIG_DIR_UNICODE_MAP_FILE (?i:SecUnicodeMapFile)
|
||||
%{ /* Other configurations */ %}
|
||||
{CONFIG_DIR_PCRE_MATCH_LIMIT_RECURSION}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_PCRE_MATCH_LIMIT_RECURSION(strchr(yytext, ' ') + 1, *driver.loc.back()); }
|
||||
{CONFIG_DIR_PCRE_MATCH_LIMIT}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_PCRE_MATCH_LIMIT(strchr(yytext, ' ') + 1, *driver.loc.back()); }
|
||||
{CONGIG_DIR_RESPONSE_BODY_MP}[ ]{FREE_TEXT_NEW_LINE} { return yy::seclang_parser::make_CONGIG_DIR_RESPONSE_BODY_MP(yytext, *driver.loc.back()); }
|
||||
{CONGIG_DIR_RESPONSE_BODY_MP}[ ]{FREE_TEXT_NEW_LINE} { return yy::seclang_parser::make_CONGIG_DIR_RESPONSE_BODY_MP(strchr(yytext, ' ') + 1, *driver.loc.back()); }
|
||||
{CONGIG_DIR_SEC_TMP_DIR}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONGIG_DIR_SEC_TMP_DIR(strchr(yytext, ' ') + 1, *driver.loc.back()); }
|
||||
{CONGIG_DIR_SEC_DATA_DIR}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONGIG_DIR_SEC_DATA_DIR(strchr(yytext, ' ') + 1, *driver.loc.back()); }
|
||||
{CONGIG_DIR_SEC_ARG_SEP}[ ]{FREE_TEXT_NEW_LINE} { return yy::seclang_parser::make_CONGIG_DIR_SEC_ARG_SEP(yytext, *driver.loc.back()); }
|
||||
|
@ -221,6 +221,13 @@ int Rules::merge(Driver *from) {
|
||||
this->requestBodyLimitAction = from->requestBodyLimitAction;
|
||||
this->responseBodyLimitAction = from->responseBodyLimitAction;
|
||||
|
||||
for (std::set<std::string>::iterator
|
||||
it=from->m_responseBodyTypeToBeInspected.begin();
|
||||
it!=from->m_responseBodyTypeToBeInspected.end(); ++it)
|
||||
{
|
||||
m_responseBodyTypeToBeInspected.insert(*it);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* default Actions is something per configuration context, there is
|
||||
|
87
test/test-cases/regression/config-response_type.json
Normal file
87
test/test-cases/regression/config-response_type.json
Normal file
@ -0,0 +1,87 @@
|
||||
[
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"SecResponseBodyMimeType (1/x)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*"
|
||||
},
|
||||
"uri":"/?key=value&key=other_value",
|
||||
"method":"GET"
|
||||
},
|
||||
"response":{
|
||||
"headers":{
|
||||
"Date":"Mon, 13 Jul 2015 20:02:41 GMT",
|
||||
"Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT",
|
||||
"Content-Type":"text/html"
|
||||
},
|
||||
"body":[
|
||||
"no need."
|
||||
]
|
||||
},
|
||||
"expected":{
|
||||
"debug_log":"T \\(0\\) trim: \"no need.\""
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||
"SecDebugLogLevel 9",
|
||||
"SecResponseBodyMimeType text\/plain text\/html text\/xml",
|
||||
"SecRule RESPONSE_BODY \"@contains RESPONSE_CONTENT_TYPE\" \"id:9,pass,t:trim,phase:4\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"SecResponseBodyMimeType (1/x)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*"
|
||||
},
|
||||
"uri":"/?key=value&key=other_value",
|
||||
"method":"GET"
|
||||
},
|
||||
"response":{
|
||||
"headers":{
|
||||
"Date":"Mon, 13 Jul 2015 20:02:41 GMT",
|
||||
"Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT",
|
||||
"Content-Type":"text/html"
|
||||
},
|
||||
"body":[
|
||||
"no need."
|
||||
]
|
||||
},
|
||||
"expected":{
|
||||
"debug_log":"T \\(0\\) trim: \"text/html\""
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||
"SecDebugLogLevel 9",
|
||||
"SecResponseBodyMimeType application\/something",
|
||||
"SecRule RESPONSE_BODY \"@contains RESPONSE_CONTENT_TYPE\" \"id:9,pass,t:trim,phase:4\""
|
||||
]
|
||||
}
|
||||
|
||||
]
|
Loading…
x
Reference in New Issue
Block a user