diff --git a/Makefile.am b/Makefile.am index be32f7bef7..b6a22ac66a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -176,6 +176,7 @@ TESTS+=test/test-cases/regression/request-body-parser-xml-validade-dtd.json TESTS+=test/test-cases/regression/rule-920120.json TESTS+=test/test-cases/regression/rule-920200.json TESTS+=test/test-cases/regression/rule-920274.json +TESTS+=test/test-cases/regression/rule-942480.json TESTS+=test/test-cases/regression/secaction.json TESTS+=test/test-cases/regression/sec_component_signature.json TESTS+=test/test-cases/regression/secmarker.json diff --git a/src/transaction.cc b/src/transaction.cc index be50538a5f..acea6bbd15 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -556,21 +556,45 @@ int Transaction::addRequestHeader(const std::string& key, if (keyl == "cookie") { size_t localOffset = m_variableOffset; + size_t pos1, pos2; std::vector cookies = utils::string::ssplit(value, ';'); for (const std::string &c : cookies) { - std::vector s = utils::string::split(c, - '='); - if (s.size() > 1) { - if (s[0].at(0) == ' ') { - s[0].erase(0, 1); - } - m_variableRequestCookiesNames.set(s[0], - s[0], localOffset); + pos1 = c.find_first_of("=", 0); + std::string ckey = ""; + std::string cval = ""; + + // if the cookie doesn't contains '=', its just a key + if (pos1 == std::string::npos) { + ckey = c; + } + // else split to two substrings + else { + ckey = c.substr(0, pos1); + cval = c.substr(pos1+1, c.length()); + } - localOffset = localOffset + s[0].size() + 1; - m_variableRequestCookies.set(s[0], s[1], localOffset); - localOffset = localOffset + s[1].size() + 2; + // remove leading spaces from key + while (ckey.at(0) == ' ') { + ckey.erase(0, 1); + localOffset++; + } + // replace remained spaces with underscore in key + pos2 = 0; + while(pos2 < ckey.length()) { + if (ckey.at(pos2) == ' ') { + ckey.replace(pos2, 1, "_"); + } + pos2++; + } + if (ckey.length() > 0) { + // set cookie name + m_variableRequestCookiesNames.set(ckey, + ckey, localOffset); + localOffset = localOffset + ckey.length() + 1; + // set cookie value + m_variableRequestCookies.set(ckey, cval, localOffset); } + localOffset = localOffset + cval.length() + 1; } } /** diff --git a/test/test-cases/regression/rule-942480.json b/test/test-cases/regression/rule-942480.json new file mode 100644 index 0000000000..dc588a8be6 --- /dev/null +++ b/test/test-cases/regression/rule-942480.json @@ -0,0 +1,42 @@ +[ + { + "enabled":1, + "version_min":300000, + "title":"Testing cookie parser :: OWASP CRS id:942480", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "Cookie": "'msdasql'; key1=val1; key2=val2=val2a; key3 = val3 " + }, + "uri":"/", + "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":{ + "http_code":400, + "debug_log":"'msdasql' with value: 'msdasql'" + }, + "rules":[ + "SecRuleEngine On", + "SecDefaultAction \"phase:2,deny,block,status:400,log\"", + "SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|!REQUEST_COOKIES:/_pk_ref/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* \"@rx (?i:(?:\\b(?:(?:s(?:elect\\b.{1,100}?\\b(?:(?:(?:length|count)\\b.{1,100}?|.*?\\bdump\\b.*)\\bfrom|to(?:p\\b.{1,100}?\\bfrom|_(?:numbe|cha)r)|(?:from\\b.{1,100}?\\bwher|data_typ)e|instr)|ys_context)|in(?:to\\b\\W*?\\b(?:dump|out)file|sert\\b\\W*?\\binto|ner\\b\\W*?\\bjoin)|u(?:nion\\b.{1,100}?\\bselect|tl_inaddr)|group\\b.*?\\bby\\b.{1,100}?\\bhaving|d(?:elete\\b\\W*?\\bfrom|bms_\\w+\\.)|load\\b\\W*?\\bdata\\b.*?\\binfile)\\b|print\\b\\W*?\\@\\@)|(?:;\\W*?\\b(?:shutdown|drop)|collation\\W*?\\(a|\\@\\@version)\\b|'(?:s(?:qloledb|a)|msdasql|dbo)'))\" \"id:942480,phase:2,block,capture,t:none,t:urlDecodeUni,msg:'SQL Injection Attack',logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',ctl:auditLogParts=+E,ver:'OWASP_CRS/3.1.0',severity:'CRITICAL',setvar:'tx.msg=%{rule.msg}',setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}', setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}',setvar:'tx.%{rule.id}-OWASP_CRS/WEB_ATTACK/SQL_INJECTION-%{MATCHED_VAR_NAME}=%{tx.0}'\"" + ] + } +]