From bab97237db2bee7362d6e3fa2cb60bb92af491fa Mon Sep 17 00:00:00 2001 From: marshal09 Date: Tue, 25 Aug 2020 05:21:16 -0400 Subject: [PATCH] Add new transformation call phpArgsNames --- Makefile.am | 1 + src/Makefile.am | 1 + src/actions/transformations/php_args_names.cc | 98 +++++++++++++++++++ src/actions/transformations/php_args_names.h | 46 +++++++++ src/actions/transformations/transformation.cc | 2 + src/parser/seclang-parser.yy | 6 ++ src/parser/seclang-scanner.ll | 2 + .../regression/transformations.json | 59 +++++++++++ 8 files changed, 215 insertions(+) create mode 100644 src/actions/transformations/php_args_names.cc create mode 100644 src/actions/transformations/php_args_names.h diff --git a/Makefile.am b/Makefile.am index 734b6f3597..7bb26c0d5a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -314,6 +314,7 @@ TESTS+=test/test-cases/secrules-language-tests/transformations/htmlEntityDecode. TESTS+=test/test-cases/secrules-language-tests/transformations/jsDecode.json TESTS+=test/test-cases/secrules-language-tests/transformations/length.json TESTS+=test/test-cases/secrules-language-tests/transformations/lowercase.json +TESTS+=test/test-cases/secrules-language-tests/transformations/phpArgsNames.json TESTS+=test/test-cases/secrules-language-tests/transformations/md5.json TESTS+=test/test-cases/secrules-language-tests/transformations/normalisePath.json TESTS+=test/test-cases/secrules-language-tests/transformations/normalisePathWin.json diff --git a/src/Makefile.am b/src/Makefile.am index e6496ccc40..9c4f181da0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -166,6 +166,7 @@ ACTIONS = \ actions/transformations/js_decode.cc \ actions/transformations/length.cc \ actions/transformations/lower_case.cc \ + actions/transformations/php_args_names.cc \ actions/transformations/md5.cc \ actions/transformations/none.cc \ actions/transformations/normalise_path.cc \ diff --git a/src/actions/transformations/php_args_names.cc b/src/actions/transformations/php_args_names.cc new file mode 100644 index 0000000000..251c879d19 --- /dev/null +++ b/src/actions/transformations/php_args_names.cc @@ -0,0 +1,98 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 - 2020 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 "src/actions/transformations/php_args_names.h" + +#include +#include +#include + +#include "modsecurity/transaction.h" +#include "src/actions/transformations/transformation.h" +#include "modsecurity/actions/action.h" + +namespace modsecurity { +namespace actions { +namespace transformations { + + +PhpArgsNames::PhpArgsNames(const std::string &a) + : Transformation(a) { +} + +std::string PhpArgsNames::evaluate(const std::string &val, + Transaction *transaction) { + //Took the logic from php src code: + //https://github.com/php/php-src/blob/master/main/php_variables.c + //Function call PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *track_vars_array) + std::locale loc; + std::string value(val); + std::string ret = ""; + if(value[0] == '[' || value[0] == '=') { + return ret; + } + std::string::size_type i = 0; + while(value[i] == ' ') { + i++; + } + std::string::size_type val_size = value.length(); + bool is_array = false; + bool is_open_sq_bracket = false; + for (; i < val_size; ++i) { + if(value[i] == '[' && !is_open_sq_bracket) { + if(strchr(&value[i], ']') != NULL) { + is_array = true; + break; + } + + ret += '_'; + is_open_sq_bracket = true; + } + else if( !is_open_sq_bracket && (value[i] == ' ' || value[i] == '.') ) { + ret += '_'; + } + else { + ret += value[i]; + } + } + + if(is_array) { + char* start = &value[0]; + while(true) { + char *tmp = &value[i]; + char *close_bra = strchr(tmp, ']'); + if(close_bra == NULL) { + return ret; + } + int array_size = (int)(close_bra - start) + 1; + if(array_size - i == 3 && value[i+1] == ' ') { + ret += '['; + i+=2; + } + for(;i < array_size; ++i) { + ret += value[i]; + } + if(i >= val_size || value[i] != '[') { + return ret; + } + } + } + return ret; + +} + +} // namespace transformations +} // namespace actions +} // namespace modsecurity diff --git a/src/actions/transformations/php_args_names.h b/src/actions/transformations/php_args_names.h new file mode 100644 index 0000000000..a286b8a1cb --- /dev/null +++ b/src/actions/transformations/php_args_names.h @@ -0,0 +1,46 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 - 2020 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 + +#include "modsecurity/actions/action.h" +#include "src/actions/transformations/transformation.h" + +#ifndef SRC_ACTIONS_TRANSFORMATIONS_PHP_ARGS_NAMES_H_ +#define SRC_ACTIONS_TRANSFORMATIONS_PHP_ARGS_NAMES_H_ + +#ifdef __cplusplus + +namespace modsecurity { +class Transaction; +namespace actions { +namespace transformations { + + +class PhpArgsNames : public Transformation { + public: + explicit PhpArgsNames(const std::string &action); + std::string evaluate(const std::string &exp, + Transaction *transaction) override; +}; + +} // namespace transformations +} // namespace actions +} // namespace modsecurity + +#endif + +#endif // SRC_ACTIONS_TRANSFORMATIONS_PHP_ARGS_NAMES_H_ diff --git a/src/actions/transformations/transformation.cc b/src/actions/transformations/transformation.cc index fae80ee62d..12c016ff89 100644 --- a/src/actions/transformations/transformation.cc +++ b/src/actions/transformations/transformation.cc @@ -35,6 +35,7 @@ #include "src/actions/transformations/js_decode.h" #include "src/actions/transformations/length.h" #include "src/actions/transformations/lower_case.h" +#include "src/actions/transformations/php_args_names.h" #include "src/actions/transformations/md5.h" #include "src/actions/transformations/none.h" #include "src/actions/transformations/normalise_path.h" @@ -88,6 +89,7 @@ Transformation* Transformation::instantiate(std::string a) { IF_MATCH(jsDecode) { return new JsDecode(a); } IF_MATCH(length) { return new Length(a); } IF_MATCH(lowercase) { return new LowerCase(a); } + IF_MATCH(phpArgsNames) { return new PhpArgsNames(a); } IF_MATCH(md5) { return new Md5(a); } IF_MATCH(none) { return new None(a); } IF_MATCH(normalizePathWin) { return new NormalisePathWin(a); } diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index 02e8e9eab9..9e5247c450 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -77,6 +77,7 @@ class Driver; #include "src/actions/transformations/none.h" #include "src/actions/transformations/url_decode.h" #include "src/actions/transformations/lower_case.h" +#include "src/actions/transformations/php_args_names.h" #include "src/actions/transformations/upper_case.h" #include "src/actions/transformations/hex_decode.h" #include "src/actions/transformations/url_encode.h" @@ -544,6 +545,7 @@ using namespace modsecurity::operators; ACTION_TRANSFORMATION_JS_DECODE "ACTION_TRANSFORMATION_JS_DECODE" ACTION_TRANSFORMATION_LENGTH "ACTION_TRANSFORMATION_LENGTH" ACTION_TRANSFORMATION_LOWERCASE "ACTION_TRANSFORMATION_LOWERCASE" + ACTION_TRANSFORMATION_PHP_ARGS_NAMES "ACTION_TRANSFORMATION_PHP_ARGS_NAMES" ACTION_TRANSFORMATION_MD5 "ACTION_TRANSFORMATION_MD5" ACTION_TRANSFORMATION_NONE "ACTION_TRANSFORMATION_NONE" ACTION_TRANSFORMATION_NORMALISE_PATH "ACTION_TRANSFORMATION_NORMALISE_PATH" @@ -2897,6 +2899,10 @@ act: { ACTION_CONTAINER($$, new actions::transformations::LowerCase($1)); } + | ACTION_TRANSFORMATION_PHP_ARGS_NAMES + { + ACTION_CONTAINER($$, new actions::transformations::PhpArgsNames($1)); + } | ACTION_TRANSFORMATION_UPPERCASE { ACTION_CONTAINER($$, new actions::transformations::UpperCase($1)); diff --git a/src/parser/seclang-scanner.ll b/src/parser/seclang-scanner.ll index 05794a32a3..735c758680 100755 --- a/src/parser/seclang-scanner.ll +++ b/src/parser/seclang-scanner.ll @@ -148,6 +148,7 @@ ACTION_TRANSFORMATION_HTML_ENTITY_DECODE (?i:t:htmlEntityDecode) ACTION_TRANSFORMATION_JS_DECODE (?i:t:jsDecode) ACTION_TRANSFORMATION_LENGTH (?i:t:length) ACTION_TRANSFORMATION_LOWERCASE (?i:t:lowercase) +ACTION_TRANSFORMATION_PHP_ARGS_NAMES (?i:t:phpArgsNames) ACTION_TRANSFORMATION_MD5 (?i:t:md5) ACTION_TRANSFORMATION_NONE (?i:t:none) ACTION_TRANSFORMATION_NORMALISE_PATH (?i:t:(normalisePath|normalizePath)) @@ -584,6 +585,7 @@ EQUALS_MINUS (?i:=\-) {ACTION_TRANSFORMATION_HEX_ENCODE} { return p::make_ACTION_TRANSFORMATION_HEX_ENCODE(yytext, *driver.loc.back()); } {ACTION_TRANSFORMATION_HEX_DECODE} { return p::make_ACTION_TRANSFORMATION_HEX_DECODE(yytext, *driver.loc.back()); } {ACTION_TRANSFORMATION_LOWERCASE} { return p::make_ACTION_TRANSFORMATION_LOWERCASE(yytext, *driver.loc.back()); } +{ACTION_TRANSFORMATION_PHP_ARGS_NAMES} { return p::make_ACTION_TRANSFORMATION_PHP_ARGS_NAMES(yytext, *driver.loc.back()); } {ACTION_TRANSFORMATION_UPPERCASE} { return p::make_ACTION_TRANSFORMATION_UPPERCASE(yytext, *driver.loc.back()); } {ACTION_TRANSFORMATION_URL_ENCODE} { return p::make_ACTION_TRANSFORMATION_URL_ENCODE(yytext, *driver.loc.back()); } {ACTION_TRANSFORMATION_URL_DECODE_UNI} { return p::make_ACTION_TRANSFORMATION_URL_DECODE_UNI(yytext, *driver.loc.back()); } diff --git a/test/test-cases/regression/transformations.json b/test/test-cases/regression/transformations.json index dcb328f16c..049ee6b9fe 100644 --- a/test/test-cases/regression/transformations.json +++ b/test/test-cases/regression/transformations.json @@ -114,5 +114,64 @@ "SecRuleEngine On", "SecRule ARGS \"@contains test \" \"id:1,pass,t:trim,t:lowercase\"" ] + }, + { + "enabled": 1, + "version_min": 300000, + "version_max": 0, + "title": "Testing transformations :: block,t:none,t:phpArgsNames", + "client": { + "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { + "headers": { + "Host": "net.tutsplus.com", + "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", + "Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8", + "Accept-Language": "en-us,en;q=0.5", + "Accept-Encoding": "gzip,deflate", + "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", + "Keep-Alive": "300", + "Connection": "keep-alive", + "Cookie": "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120", + "Pragma": "no-cache", + "Cache-Control": "no-cache" + }, + "uri": "\/test.pl?param1=fdsfsd&s%252bc%20r.%2b+ipt._[a[_xss]]iaaa=1", + "method": "GET", + "http_version": 1.1, + "body": "" + }, + "response": { + "headers": { + "Content-Type": "text\/xml; charset=utf-8\n\r", + "Content-Length": "length\n\r" + }, + "body": [ + "\n\r", + "\n\r", + " \n\r", + " \n\r", + " string<\/EnlightenResult>\n\r", + " <\/EnlightenResponse>\n\r", + " <\/soap:Body>\n\r", + "<\/soap:Envelope>\n\r" + ] + }, + "expected": { + "audit_log": "", + "debug_log": "phpArgsNames: \"s%2bc_r_[+]_ipt__[a[_xss]", + "error_log": "", + "http_code": 403 + }, + "rules": [ + "SecRuleEngine On", + "SecRule ARGS_NAMES \"@streq s%2bc_r_+_ipt__[a[_xss]\" \"id:1,phase:2,deny,status:403,t:none,t:phpArgsNames\"" + ] } ]