From 6a7b970fe39db2b6a49109d322add550e75fef91 Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Wed, 18 May 2016 10:29:37 -0300 Subject: [PATCH] Adds support to ctl:requestBodyProcessor=XML --- headers/modsecurity/transaction.h | 5 + src/Makefile.am | 1 + src/actions/ctl_request_body_processor_xml.cc | 34 ++++ src/actions/ctl_request_body_processor_xml.h | 39 ++++ src/parser/seclang-parser.yy | 5 +- src/transaction.cc | 16 +- .../action-ctl_request_body_processor.json | 175 ++++++++++++++++++ 7 files changed, 263 insertions(+), 12 deletions(-) create mode 100644 src/actions/ctl_request_body_processor_xml.cc create mode 100644 src/actions/ctl_request_body_processor_xml.h create mode 100644 test/test-cases/regression/action-ctl_request_body_processor.json diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index a79891dc..9383f2d5 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -252,6 +252,11 @@ class Transaction { */ RequestBodyType m_requestBodyType; + /** + * Holds the request body "processor" + */ + RequestBodyType m_requestBodyProcessor; + /** * Rules object utilized during this specific transaction. */ diff --git a/src/Makefile.am b/src/Makefile.am index 9d4d90da..0a468a23 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -68,6 +68,7 @@ ACTIONS = \ actions/capture.cc \ actions/chain.cc \ actions/ctl_audit_log_parts.cc \ + actions/ctl_request_body_processor_xml.cc \ actions/init_col.cc \ actions/deny.cc \ actions/log_data.cc \ diff --git a/src/actions/ctl_request_body_processor_xml.cc b/src/actions/ctl_request_body_processor_xml.cc new file mode 100644 index 00000000..66b4a8ae --- /dev/null +++ b/src/actions/ctl_request_body_processor_xml.cc @@ -0,0 +1,34 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include "actions/ctl_request_body_processor_xml.h" + +#include +#include + +#include "modsecurity/transaction.h" + +namespace modsecurity { +namespace actions { + + +bool CtlRequestBodyProcessorXML::evaluate(Rule *rule, Transaction *transaction) { + transaction->m_requestBodyProcessor = modsecurity::Transaction::XMLRequestBody; + return true; +} + + +} // namespace actions +} // namespace modsecurity diff --git a/src/actions/ctl_request_body_processor_xml.h b/src/actions/ctl_request_body_processor_xml.h new file mode 100644 index 00000000..eaf7f480 --- /dev/null +++ b/src/actions/ctl_request_body_processor_xml.h @@ -0,0 +1,39 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include + +#include "actions/action.h" +#include "modsecurity/transaction.h" + +#ifndef SRC_ACTIONS_CTL_REQUEST_BODY_PROCESSOR_XML_H_ +#define SRC_ACTIONS_CTL_REQUEST_BODY_PROCESSOR_XML_H_ + +namespace modsecurity { +namespace actions { + + +class CtlRequestBodyProcessorXML : public Action { + public: + explicit CtlRequestBodyProcessorXML(std::string action) + : Action(action, RunTimeOnlyIfMatchKind) { } + + bool evaluate(Rule *rule, Transaction *transaction) override; +}; + +} // namespace actions +} // namespace modsecurity + +#endif // SRC_ACTIONS_CTL_REQUEST_BODY_PROCESSOR_XML_H_ diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index 1706be2d..5d65b10c 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -23,6 +23,7 @@ class Driver; #include "actions/action.h" #include "actions/audit_log.h" #include "actions/ctl_audit_log_parts.h" +#include "actions/ctl_request_body_processor_xml.h" #include "actions/init_col.h" #include "actions/set_sid.h" #include "actions/set_uid.h" @@ -69,6 +70,7 @@ using modsecurity::ModSecurity; using modsecurity::actions::Accuracy; using modsecurity::actions::Action; using modsecurity::actions::CtlAuditLogParts; +using modsecurity::actions::CtlRequestBodyProcessorXML; using modsecurity::actions::InitCol; using modsecurity::actions::SetSID; using modsecurity::actions::SetUID; @@ -1094,8 +1096,7 @@ act: } | ACTION_CTL_BDY_XML { - /* not ready yet. */ - $$ = Action::instantiate($1); + $$ = new modsecurity::actions::CtlRequestBodyProcessorXML($1); } | ACTION_CTL_BDY_JSON { diff --git a/src/transaction.cc b/src/transaction.cc index 3535b908..5dcbc999 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -107,6 +107,7 @@ Transaction::Transaction(ModSecurity *ms, Rules *rules, void *logCbData) m_namesArgsPost(NULL), m_namesArgsGet(NULL), m_requestBodyType(UnknownFormat), + m_requestBodyProcessor(UnknownFormat), m_requestHeadersNames(NULL), m_responseHeadersNames(NULL), m_responseContentType(NULL), @@ -475,7 +476,6 @@ int Transaction::addRequestHeader(const std::string& key, if (keyl == "content-type") { std::string multipart("multipart/form-data"); std::string l = tolower(value); - if (l.compare(0, multipart.length(), multipart) == 0) { this->m_requestBodyType = MultiPartRequestBody; } @@ -590,15 +590,11 @@ int Transaction::processRequestBody() { * */ - if (m_requestBodyType == XMLRequestBody) { - std::string *a = m_collections.resolveFirst( - "REQUEST_HEADERS:Content-Type"); - if (a != NULL) { - if (m_xml->init() == true) { - m_xml->processChunk(m_requestBody.str().c_str(), - m_requestBody.str().size()); - m_xml->complete(); - } + if (m_requestBodyProcessor == XMLRequestBody) { + if (m_xml->init() == true) { + m_xml->processChunk(m_requestBody.str().c_str(), + m_requestBody.str().size()); + m_xml->complete(); } } diff --git a/test/test-cases/regression/action-ctl_request_body_processor.json b/test/test-cases/regression/action-ctl_request_body_processor.json new file mode 100644 index 00000000..085e8f5b --- /dev/null +++ b/test/test-cases/regression/action-ctl_request_body_processor.json @@ -0,0 +1,175 @@ +[ + { + "enabled":1, + "version_min":300000, + "title":"Testing CtlRequestBodyProcessor=XML (1)", + "expected":{ + "debug_log": "Registered XML namespace href \"http://schemas.xmlsoap.org/soap/envelope/\" prefix \"soap\"" + }, + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Content-Type": "text/xml" + }, + "uri":"/?key=value&key=other_value", + "method":"POST", + "body": [ + "", + "", + "", + "Everyday Italian", + "Giada De Laurentiis", + "2005", + "30.00", + "", + + "", + "Harry Potter", + "J K. Rowling", + "2005", + "29.99", + "", + + "", + "XQuery Kick Start", + "James McGovern", + "Per Bothner", + "Kurt Cagle", + "James Linn", + "Vaidyanathan Nagarajan", + "2003", + "49.99", + "", + + "", + "Learning XML", + "Erik T. Ray", + "2003", + "39.95", + "", + "" + ] + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "rules":[ + "SecRuleEngine On", + "SecRequestBodyAccess On", + "SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500005,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"", + "SecRule XML:/bookstore/book/price[text()] \"Fred\" \"phase:3,id:123,xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing CtlRequestBodyProcessor=XML (2)", + "expected":{ + "debug_log": "XML: No XML document found, returning" + }, + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Content-Type": "text/xml" + }, + "uri":"/?key=value&key=other_value", + "method":"POST", + "body": [ + "", + "", + "", + "Everyday Italian", + "Giada De Laurentiis", + "2005", + "30.00", + "", + + "", + "Harry Potter", + "J K. Rowling", + "2005", + "29.99", + "", + + "", + "XQuery Kick Start", + "James McGovern", + "Per Bothner", + "Kurt Cagle", + "James Linn", + "Vaidyanathan Nagarajan", + "2003", + "49.99", + "", + + "", + "Learning XML", + "Erik T. Ray", + "2003", + "39.95", + "", + "" + ] + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "rules":[ + "SecRuleEngine On", + "SecRequestBodyAccess On", + "SecRule XML:/bookstore/book/price[text()] \"Fred\" \"phase:3,id:123,xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing CtlRequestBodyProcessor=XML (3)", + "expected":{ + "debug_log": "XML: Failed parsing document." + }, + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Content-Type": "text/xml" + }, + "uri":"/?key=value&key=other_value", + "method":"POST", + "body": [ + "not a xml" + ] + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "rules":[ + "SecRuleEngine On", + "SecRequestBodyAccess On", + "SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500005,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"", + "SecRule XML:/bookstore/book/price[text()] \"Fred\" \"phase:3,id:123,xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'\"" + ] + } +] \ No newline at end of file