Better support for multipart

ModSecurity v2.x parser was ported into 3.x branch.

All the multipart related variables should be workbale.
This commit is contained in:
Felipe Zimmerle 2016-06-08 21:48:02 -03:00
parent 9e5cf2de8e
commit 2e3da7ea24
23 changed files with 4117 additions and 596 deletions

View File

@ -60,7 +60,11 @@ class RulesProperties {
requestBodyLimitAction(ProcessPartialBodyLimitAction),
responseBodyLimit(0),
responseBodyLimitAction(ProcessPartialBodyLimitAction),
secRuleEngine(DetectionOnlyRuleEngine) { }
secRuleEngine(DetectionOnlyRuleEngine),
uploadKeepFiles(0),
uploadFileLimit(100),
uploadFileMode(0),
tmpSaveUploadedFiles(false) { }
explicit RulesProperties(DebugLog *debugLog)
: audit_log(NULL),
@ -76,8 +80,11 @@ class RulesProperties {
requestBodyLimitAction(ProcessPartialBodyLimitAction),
responseBodyLimit(0),
responseBodyLimitAction(ProcessPartialBodyLimitAction),
secRuleEngine(DetectionOnlyRuleEngine) { }
secRuleEngine(DetectionOnlyRuleEngine),
uploadKeepFiles(0),
uploadFileLimit(100),
uploadFileMode(0),
tmpSaveUploadedFiles(false) { }
/*
RulesProperties(const RulesProperties &other)
@ -219,6 +226,8 @@ class RulesProperties {
int uploadFileLimit;
int uploadFileMode;
std::string uploadDirectory;
std::string uploadTmpDirectory;
bool tmpSaveUploadedFiles;
audit_log::AuditLog *audit_log;

View File

@ -200,7 +200,6 @@ COLLECTION = \
BODY_PROCESSORS = \
request_body_processor/multipart.cc \
request_body_processor/multipart_blob.cc \
request_body_processor/xml.cc

View File

@ -211,6 +211,7 @@ using modsecurity::Variables::XML;
%token <std::string> CONFIG_DIR_AUDIT_TPE
%token <std::string> CONFIG_UPDLOAD_KEEP_FILES
%token <std::string> CONFIG_UPDLOAD_SAVE_TMP_FILES
%token <std::string> CONFIG_UPLOAD_FILE_LIMIT
%token <std::string> CONFIG_UPLOAD_FILE_MODE
%token <std::string> CONFIG_UPLOAD_DIR
@ -403,6 +404,14 @@ audit_log:
{
driver.uploadDirectory = $1;
}
| CONFIG_UPDLOAD_SAVE_TMP_FILES CONFIG_VALUE_ON
{
driver.tmpSaveUploadedFiles = true;
}
| CONFIG_UPDLOAD_SAVE_TMP_FILES CONFIG_VALUE_OFF
{
driver.tmpSaveUploadedFiles = false;
}
;
actings:

View File

@ -99,6 +99,7 @@ CONFIG_DIR_AUDIT_TPE (?i:SecAuditLogType)
CONFIG_UPLOAD_FILE_LIMIT (?i:SecUploadFileLimit)
CONFIG_UPLOAD_FILE_MODE (?i:SecUploadFileMode)
CONFIG_UPDLOAD_KEEP_FILES (?i:SecUploadKeepFiles)
CONFIG_UPDLOAD_SAVE_TMP_FILES (?i:SecTmpSaveUploadedFiles)
CONFIG_UPLOAD_DIR (?i:SecUploadDir)
@ -125,7 +126,7 @@ OPERATOR_GEOIP (?i:@geoLookup)
TRANSFORMATION t:(?i:(parityZero7bit|parityOdd7bit|parityEven7bit|sqlHexDecode|cmdLine|sha1|md5|hexEncode|lowercase|urlDecodeUni|urlDecode|none|compressWhitespace|removeWhitespace|replaceNulls|removeNulls|htmlEntityDecode|jsDecode|cssDecode|trim|normalizePathWin|normalisePathWin|normalisePath|length|utf8toUnicode|urldecode|removeCommentsChar|removeComments|replaceComments))
VARIABLE (?i:(RESOURCE|ARGS_COMBINED_SIZE|ARGS_GET_NAMES|ARGS_POST_NAMES|FILES_COMBINED_SIZE|FULL_REQUEST_LENGTH|REQUEST_BODY_LENGTH|REQUEST_URI_RAW|UNIQUE_ID|SERVER_PORT|SERVER_ADDR|REMOTE_PORT|REMOTE_HOST|PATH_INFO|MULTIPART_CRLF_LF_LINES|MATCHED_VAR_NAME|MATCHED_VAR|INBOUND_DATA_ERROR|OUTBOUND_DATA_ERROR|FULL_REQUEST|AUTH_TYPE|ARGS_NAMES|REMOTE_ADDR|REQUEST_BASENAME|REQUEST_BODY|REQUEST_FILENAME|REQUEST_HEADERS_NAMES|REQUEST_METHOD|REQUEST_PROTOCOL|REQUEST_URI|RESPONSE_BODY|RESPONSE_CONTENT_LENGTH|RESPONSE_CONTENT_TYPE|RESPONSE_HEADERS_NAMES|RESPONSE_PROTOCOL|RESPONSE_STATUS|REQBODY_PROCESSOR|USERID|SESSIONID))
VARIABLE (?i:(MULTIPART_DATA_AFTER|RESOURCE|ARGS_COMBINED_SIZE|ARGS_GET_NAMES|ARGS_POST_NAMES|FILES_TMPNAMES|FILES_COMBINED_SIZE|FULL_REQUEST_LENGTH|REQUEST_BODY_LENGTH|REQUEST_URI_RAW|UNIQUE_ID|SERVER_PORT|SERVER_ADDR|REMOTE_PORT|REMOTE_HOST|PATH_INFO|MULTIPART_CRLF_LF_LINES|MATCHED_VAR_NAME|MATCHED_VAR|INBOUND_DATA_ERROR|OUTBOUND_DATA_ERROR|FULL_REQUEST|AUTH_TYPE|ARGS_NAMES|REMOTE_ADDR|REQUEST_BASENAME|REQUEST_BODY|REQUEST_FILENAME|REQUEST_HEADERS_NAMES|REQUEST_METHOD|REQUEST_PROTOCOL|REQUEST_URI|RESPONSE_BODY|RESPONSE_CONTENT_LENGTH|RESPONSE_CONTENT_TYPE|RESPONSE_HEADERS_NAMES|RESPONSE_PROTOCOL|RESPONSE_STATUS|REQBODY_PROCESSOR|USERID|SESSIONID))
VARIABLE_COL (?i:(SESSION|GLOBAL|ARGS_POST|ARGS_GET|ARGS|FILES_SIZES|FILES_NAMES|FILES_TMP_CONTENT|MULTIPART_FILENAME|MULTIPART_NAME|MATCHED_VARS_NAMES|MATCHED_VARS|FILES|QUERY_STRING|REQUEST_COOKIES|REQUEST_HEADERS|RESPONSE_HEADERS|GEO|IP|REQUEST_COOKIES_NAMES))
VARIABLE_TX (?i:TX)
@ -148,7 +149,7 @@ RUN_TIME_VAR_TIME_WDAY (?i:TIME_WDAY)
RUN_TIME_VAR_TIME_YEAR (?i:TIME_YEAR)
RUN_TIME_VAR_XML (?i:XML)
VARIABLENOCOLON (?i:REQBODY_ERROR|REQBODY_PROCESSOR_ERROR|MULTIPART_HEADER_FOLDING|MULTIPART_INVALID_HEADER_FOLDING|MULTIPART_STRICT_ERROR|MULTIPART_UNMATCHED_BOUNDARY|REMOTE_ADDR|REQUEST_LINE)
VARIABLENOCOLON (?i:MULTIPART_FILE_LIMIT_EXCEEDED|MULTIPART_INVALID_QUOTING|REQBODY_ERROR|REQBODY_PROCESSOR_ERROR|MULTIPART_HEADER_FOLDING|MULTIPART_INVALID_HEADER_FOLDING|MULTIPART_STRICT_ERROR|MULTIPART_UNMATCHED_BOUNDARY|REMOTE_ADDR|REQUEST_LINE)
CONFIG_VALUE_ON (?i:On)
CONFIG_VALUE_OFF (?i:Off)
@ -230,6 +231,7 @@ CONFIG_DIR_UNICODE_MAP_FILE (?i:SecUnicodeMapFile)
{CONFIG_UPLOAD_FILE_LIMIT}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_UPLOAD_FILE_LIMIT(strchr(yytext, ' ') + 1, *driver.loc.back()); }
{CONFIG_UPLOAD_FILE_MODE}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_UPLOAD_FILE_MODE(strchr(yytext, ' ') + 1, *driver.loc.back()); }
{CONFIG_UPDLOAD_KEEP_FILES} { return yy::seclang_parser::make_CONFIG_UPDLOAD_KEEP_FILES(yytext, *driver.loc.back()); }
{CONFIG_UPDLOAD_SAVE_TMP_FILES} { return yy::seclang_parser::make_CONFIG_UPDLOAD_SAVE_TMP_FILES(yytext, *driver.loc.back()); }
{CONFIG_UPLOAD_DIR}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_UPLOAD_DIR(strchr(yytext, ' ') + 1, *driver.loc.back()); }
%{ /* Debug log entries */ %}

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
#include <string>
#include <iostream>
#include <list>
#ifndef SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_
#define SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_
@ -25,24 +25,153 @@
namespace modsecurity {
namespace RequestBodyProcessor {
#define MULTIPART_BUF_SIZE 4096
#define MULTIPART_FORMDATA 1
#define MULTIPART_FILE 2
struct MyHash {
size_t operator()(const std::string& Keyval) const {
size_t h = 0;
std::for_each(Keyval.begin(), Keyval.end(), [&](char c) {
h += tolower(c);
});
return h;
}
};
struct MyEqual {
bool operator()(const std::string& Left, const std::string& Right) const {
return Left.size() == Right.size()
&& std::equal(Left.begin(), Left.end(), Right.begin(),
[](char a, char b) {
return tolower(a) == tolower(b);
});
}
};
class MultipartPart {
public:
MultipartPart()
: m_type(MULTIPART_FORMDATA),
m_tmp_file_fd(0),
m_tmp_file_size(0),
m_offset(0),
m_length(0) { }
/* part type, can be MULTIPART_FORMDATA or MULTIPART_FILE */
int m_type;
/* the name */
std::string m_name;
/* variables only, variable value */
std::string m_value;
std::list<std::string> m_value_parts;
/* files only, the content type (where available) */
/* std::string m_content_type; */
/* files only, the name of the temporary file holding data */
std::string m_tmp_file_name;
int m_tmp_file_fd;
unsigned int m_tmp_file_size;
/* files only, filename as supplied by the browser */
std::string m_filename;
std::string m_last_header_name;
std::unordered_map<std::string, std::string, MyHash, MyEqual> m_headers;
unsigned int m_offset;
unsigned int m_length;
};
class Multipart {
public:
Multipart(std::string header, Transaction *transaction);
~Multipart();
bool init();
bool boundaryContainsOnlyValidCharacters();
bool conuntBoundaryParameters();
bool process(std::string data);
void checkForCrlfLf(const std::string &blob);
int boundary_characters_valid(const char *boundary);
int count_boundary_params(const std::string& str_header_value);
int is_token_char(unsigned char c);
int multipart_complete();
int parse_content_disposition(const char *c_d_value);
bool process(const std::string& data);
int process_boundary(int last_part);
int process_part_header();
int process_part_data();
int tmp_file_name(std::string *filename);
void validate_quotes(const char *data);
size_t m_reqbody_no_files_length;
std::list<MultipartPart *> m_parts;
/* Number of parts that are files */
int m_nfiles;
/* mime boundary used to detect when
* parts end and begin
*/
std::string m_boundary;
int m_boundary_count;
/* internal buffer and other variables
* used while parsing
*/
char m_buf[MULTIPART_BUF_SIZE + 2];
int m_buf_contains_line;
char *m_bufptr;
int m_bufleft;
unsigned int m_buf_offset;
/* pointer that keeps track of a part while
* it is being built
*/
MultipartPart *m_mpp;
/* part parsing state; 0 means we are reading
* headers, 1 means we are collecting data
*/
int m_mpp_state;
/* because of the way this parsing algorithm
* works we hold back the last two bytes of
* each data chunk so that we can discard it
* later if the next data chunk proves to be
* a boundary; the first byte is an indicator
* 0 - no content, 1 - two data bytes available
*/
char m_reserve[4];
int m_seen_data;
int m_is_complete;
int m_flag_error;
int m_flag_data_before;
int m_flag_data_after;
int m_flag_header_folding;
int m_flag_boundary_quoted;
int m_flag_lf_line;
int m_flag_crlf_line;
int m_flag_unmatched_boundary;
int m_flag_boundary_whitespace;
int m_flag_missing_semicolon;
int m_flag_invalid_quoting;
int m_flag_invalid_part;
int m_flag_invalid_header_folding;
int m_flag_file_limit_exceeded;
bool crlf;
bool containsDataAfter;
bool containsDataBefore;
bool lf;
bool boundaryStartsWithWhiteSpace;
bool boundaryIsQuoted;
bool missingSemicolon;
bool invalidQuote;
#ifndef NO_LOGS
void debug(int a, std::string str) {
m_transaction->debug(a, str);
@ -50,11 +179,11 @@ class Multipart {
#endif
private:
std::string m_boundary;
std::string m_header;
Transaction *m_transaction;
};
} // namespace RequestBodyProcessor
} // namespace modsecurity

View File

@ -1,142 +0,0 @@
/*
* 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 "request_body_processor/multipart_blob.h"
#include <list>
#include <iostream>
#include <string>
namespace modsecurity {
namespace RequestBodyProcessor {
MultipartBlob::MultipartBlob(const std::string &blob, Multipart *parent)
: m_blob(blob),
invalidQuote(false),
m_parent(parent) {
processContent();
}
bool MultipartBlob::processContent() {
size_t end = 0;
size_t offset = 0;
end = m_blob.find("\n", offset);
if (end == std::string::npos) {
#ifndef NO_LOGS
debug(4, "Missing end of line");
#endif
return false;
}
std::string firstLine = std::string(m_blob, offset, end);
offset = end + 1;
end = m_blob.find("\n", offset);
if (end == std::string::npos) {
#ifndef NO_LOGS
debug(4, "Missing end of line");
#endif
return false;
}
std::string secondLine = std::string(m_blob, offset, end - offset);
bool dispositionLine = processContentDispositionLine(firstLine);
if (dispositionLine == false) {
return false;
}
bool contentTypeLine = processContentTypeLine(secondLine);
if (contentTypeLine == false) {
return false;
}
offset = end + 1;
if (contentType.empty() == false) {
end = m_blob.find_first_of("\n", offset);
if (end == std::string::npos) {
#ifndef NO_LOGS
debug(4, "Missing end of line");
#endif
return false;
}
offset = end + 1;
}
content = std::string(m_blob, offset, m_blob.length() - offset + 1);
return true;
}
bool MultipartBlob::processContentTypeLine(
const std::string &contentTypeLine) {
size_t contentTypeKeyLength = 14;
if (contentTypeLine.length() <= contentTypeKeyLength) {
return true;
}
contentType = std::string(contentTypeLine, contentTypeKeyLength,
contentTypeLine.length() - contentTypeKeyLength);
return true;
}
bool MultipartBlob::processContentDispositionLine(
const std::string &dispositionLine) {
size_t offset;
if (dispositionLine.size() < 30 ||
dispositionLine.compare(21, 9, "form-data") != 0) {
#ifndef NO_LOGS
debug(4, "Multipart: Content-Disposition is unknown");
#endif
return false;
}
// Find name=
offset = dispositionLine.find("name=");
if (offset != std::string::npos) {
size_t invalidQuote = dispositionLine.find("\'", offset);
if (invalidQuote != std::string::npos) {
this->invalidQuote = true;
}
offset = offset + 5 /* name= */ + 1 /* " */;
size_t end = dispositionLine.find("\"", offset);
if (end != std::string::npos) {
name = std::string(dispositionLine, offset, end - offset);
}
}
// Find filename=
offset = dispositionLine.find("filename=");
if (offset != std::string::npos) {
size_t invalidQuote = dispositionLine.find("\'", offset);
if (invalidQuote != std::string::npos) {
this->invalidQuote = true;
}
offset = offset + 9 /* filename= */ + 1 /* " */;
size_t end = dispositionLine.find("\"", offset);
if (end != std::string::npos) {
filename = std::string(dispositionLine, offset, end - offset);
}
}
return true;
}
} // namespace RequestBodyProcessor
} // namespace modsecurity

View File

@ -1,54 +0,0 @@
/*
* 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 <string>
#include <iostream>
#include "request_body_processor/multipart.h"
#ifndef SRC_REQUEST_BODY_PROCESSOR_MULTIPART_BLOB_H_
#define SRC_REQUEST_BODY_PROCESSOR_MULTIPART_BLOB_H_
namespace modsecurity {
namespace RequestBodyProcessor {
class MultipartBlob {
public:
explicit MultipartBlob(const std::string &blob, Multipart *parent);
bool processContent();
bool processContentDispositionLine(const std::string &dispositionLine);
bool processContentTypeLine(const std::string &contentTypeLine);
bool invalidQuote;
std::string name;
std::string filename;
std::string contentType;
std::string content;
#ifndef NO_LOGS
void debug(int a, std::string str) {
m_parent->debug(a, str);
}
#endif
private:
const std::string m_blob;
Multipart *m_parent;
};
} // namespace RequestBodyProcessor
} // namespace modsecurity
#endif // SRC_REQUEST_BODY_PROCESSOR_MULTIPART_BLOB_H_

View File

@ -222,6 +222,12 @@ int Rules::merge(Driver *from) {
this->requestBodyLimitAction = from->requestBodyLimitAction;
this->responseBodyLimitAction = from->responseBodyLimitAction;
this->uploadKeepFiles = from->uploadKeepFiles;
this->uploadFileLimit = from->uploadFileLimit;
this->uploadFileMode = from->uploadFileMode;
this->uploadDirectory = from->uploadDirectory;
this->tmpSaveUploadedFiles = from->tmpSaveUploadedFiles;
for (std::set<std::string>::iterator
it = from->m_responseBodyTypeToBeInspected.begin();
it != from->m_responseBodyTypeToBeInspected.end(); ++it) {
@ -278,6 +284,12 @@ int Rules::merge(Rules *from) {
this->requestBodyLimitAction = from->requestBodyLimitAction;
this->responseBodyLimitAction = from->responseBodyLimitAction;
this->uploadKeepFiles = from->uploadKeepFiles;
this->uploadFileLimit = from->uploadFileLimit;
this->uploadFileMode = from->uploadFileMode;
this->uploadDirectory = from->uploadDirectory;
this->tmpSaveUploadedFiles = from->tmpSaveUploadedFiles;
if (from->m_debugLog && this->m_debugLog &&
from->m_debugLog->isLogFileSet()) {
this->m_debugLog->setDebugLogFile(from->m_debugLog->getDebugLogFile());

View File

@ -606,72 +606,8 @@ int Transaction::processRequestBody() {
if (m.init() == true) {
m.process(m_requestBody.str());
if (m.crlf && m.lf) {
m_collections.store("MULTIPART_CRLF_LF_LINES", "1");
} else {
m_collections.store("MULTIPART_CRLF_LF_LINES", "0");
}
if (m.boundaryStartsWithWhiteSpace) {
#ifndef NO_LOGS
debug(9, "Multipart: Boundary starts with white space, " \
"setting MULTIPART_STRICT_ERROR to 1");
#endif
m_collections.storeOrUpdateFirst(
"MULTIPART_STRICT_ERROR", "1");
}
if (m.boundaryIsQuoted) {
#ifndef NO_LOGS
debug(9, "Multipart: Boundary is quoted, " \
"setting MULTIPART_STRICT_ERROR to 1");
#endif
m_collections.storeOrUpdateFirst(
"MULTIPART_STRICT_ERROR", "1");
}
if (m.containsDataAfter) {
#ifndef NO_LOGS
debug(9, "Multipart: There is data after the boundary, " \
"setting MULTIPART_STRICT_ERROR to 1");
#endif
m_collections.storeOrUpdateFirst(
"MULTIPART_STRICT_ERROR", "1");
m_collections.store("MULTIPART_UNMATCHED_BOUNDARY", "1");
} else {
m_collections.store("MULTIPART_UNMATCHED_BOUNDARY", "0");
}
if (m.containsDataBefore) {
#ifndef NO_LOGS
debug(9, "Multipart: There is data before the boundary, " \
"setting MULTIPART_STRICT_ERROR to 1");
#endif
m_collections.storeOrUpdateFirst(
"MULTIPART_STRICT_ERROR", "1");
}
if (m.lf) {
#ifndef NO_LOGS
debug(9, "Multipart: Lines are LF-terminated, " \
"setting MULTIPART_STRICT_ERROR to 1");
#endif
m_collections.storeOrUpdateFirst(
"MULTIPART_STRICT_ERROR", "1");
}
if (m.missingSemicolon) {
#ifndef NO_LOGS
debug(9, "Multipart: Boundary missing semicolon, " \
"setting MULTIPART_STRICT_ERROR to 1");
#endif
m_collections.storeOrUpdateFirst(
"MULTIPART_STRICT_ERROR", "1");
}
if (m.invalidQuote) {
#ifndef NO_LOGS
debug(9, "Multipart: Invalid quote, " \
"setting MULTIPART_STRICT_ERROR to 1");
#endif
m_collections.storeOrUpdateFirst(
"MULTIPART_STRICT_ERROR", "1");
}
}
m.multipart_complete();
}
}

View File

@ -117,7 +117,7 @@ std::string ascTime(time_t *t) {
void chomp(std::string *str) {
std::string::size_type pos = str->find_last_not_of("\n\t");
std::string::size_type pos = str->find_last_not_of("\n\r");
if (pos != std::string::npos) {
str->erase(pos+1, str->length()-pos-1);
}

View File

@ -0,0 +1,67 @@
[
{
"enabled":1,
"version_min":300000,
"title":"multipart parser (final CRLF)",
"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":"*/*",
"Content-Length":"330",
"Content-Type":"multipart/form-data; boundary=---------------------------69343412719991675451336310646",
"Expect":"100-continue"
},
"uri":"/",
"method":"POST",
"body":[
"-----------------------------69343412719991675451336310646",
"Content-Disposition: form-data; name=\"a\"\r",
"\r",
"1\r",
"1.1\r",
"1.2\r",
"1.3\r",
"-----------------------------69343412719991675451336310646",
"Content-Disposition: form-data; name=\"b\"\r",
"\r",
"2\r",
"2.1\r",
"2.2\r",
"2.3\r",
"-----------------------------69343412719991675451336310646--"
]
},
"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":"Target value: \"Adding request argument (BODY): name \"b\", value \"22\.12\.22\.3\""
},
"rules":[
"SecRuleEngine On",
"SecRequestBodyAccess On",
"SecRule MULTIPART_STRICT_ERROR \"@eq 1\" \"phase:2,deny,id:500055\"",
"SecRule MULTIPART_UNMATCHED_BOUNDARY \"@eq 1\" \"phase:2,deny,id:500056\"",
"SecRule REQBODY_PROCESSOR_ERROR \"@eq 1\" \"phase:2,deny,id:500057\"",
"SecRule ARGS_POST \"@eq 1231\" \"phase:2,deny,id:500067\""
]
}
]

File diff suppressed because it is too large Load Diff

View File

@ -23,21 +23,21 @@
"uri":"/",
"method":"POST",
"body":[
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"name\"",
"",
"test",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is a very small test file..",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is another very small test file..",
"--------------------------756b6d74fa1a8ee2--"
"----------------------------756b6d74fa1a8ee2--"
]
},
"response":{

View File

@ -23,21 +23,21 @@
"uri":"/",
"method":"POST",
"body":[
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"name\"",
"",
"test",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is a very small test file..",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is another very small test file..",
"--------------------------756b6d74fa1a8ee2--"
"----------------------------756b6d74fa1a8ee2--"
]
},
"response":{
@ -51,13 +51,13 @@
]
},
"expected":{
"debug_log":"Target value: \"74.000000\" \\(Variable: FILES_COMBINED_SIZE\\)"
"debug_log":"Target value: \"70\" \\(Variable: FILES_COMBINED_SIZE\\)"
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRule FILES_COMBINED_SIZE \"@gt 74.000000\" \"id:1,phase:3,pass,t:trim\""
"SecRule FILES_COMBINED_SIZE \"@gt 70\" \"id:1,phase:3,pass,t:trim\""
]
}
]

View File

@ -23,21 +23,21 @@
"uri":"/",
"method":"POST",
"body":[
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"name\"",
"",
"test",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is a very small test file..",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is another very small test file..",
"--------------------------756b6d74fa1a8ee2--"
"----------------------------756b6d74fa1a8ee2--"
]
},
"response":{

View File

@ -23,21 +23,21 @@
"uri":"/",
"method":"POST",
"body":[
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"name\"",
"",
"test",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is a very small test file..",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is another very small test file..",
"--------------------------756b6d74fa1a8ee2--"
"----------------------------756b6d74fa1a8ee2--"
]
},
"response":{

View File

@ -1,63 +0,0 @@
[
{
"enabled":1,
"version_min":300000,
"title":"Testing Variables :: FILES_NAMES (1/1)",
"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":"*/*",
"Content-Length":"330",
"Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2",
"Expect":"100-continue"
},
"uri":"/",
"method":"POST",
"body":[
"--------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"name\"",
"",
"test",
"--------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is a very small test file..",
"--------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is another very small test file..",
"--------------------------756b6d74fa1a8ee2--"
]
},
"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":"trim: \"This is another very small test file.."
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRule FILES_TMP_CONTENT \"@contains small_text_file.txt\" \"id:1,phase:3,pass,t:trim\""
]
}
]

View File

@ -23,21 +23,21 @@
"uri":"/",
"method":"POST",
"body":[
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"name\"",
"",
"test",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is a very small test file..",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is another very small test file..",
"--------------------------756b6d74fa1a8ee2--"
"----------------------------756b6d74fa1a8ee2--"
]
},
"response":{
@ -84,21 +84,21 @@
"uri":"/",
"method":"POST",
"body":[
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"name\"",
"",
"test",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is a very small test file..",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"\r",
"Content-Type: text/plain\r",
"\r",
"This is another very small test file..\r",
"--------------------------756b6d74fa1a8ee2--\r"
"----------------------------756b6d74fa1a8ee2--\r"
]
},
"response":{

View File

@ -23,21 +23,21 @@
"uri":"/",
"method":"POST",
"body":[
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"name\"",
"",
"test",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is a very small test file..",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is another very small test file..",
"--------------------------756b6d74fa1a8ee2--"
"----------------------------756b6d74fa1a8ee2--"
]
},
"response":{
@ -84,21 +84,21 @@
"uri":"/",
"method":"POST",
"body":[
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"name\"",
"",
"test",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is a very small test file..",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file2.txt\"\r",
"Content-Type: text/plain\r",
"\r",
"This is another very small test file..\r",
"--------------------------756b6d74fa1a8ee2--\r"
"----------------------------756b6d74fa1a8ee2--\r"
]
},
"response":{

View File

@ -0,0 +1,61 @@
[
{
"enabled":1,
"version_min":300000,
"title":"Testing Variables :: MULTIPART_INVALID_HEADER_FOLDING",
"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":"*/*",
"Content-Length":"330",
"Content-Type":"multipart/form-data; boundary=-----------------------------69343412719991675451336310646",
"Expect":"100-continue"
},
"uri":"/",
"method":"POST",
"body":[
"-------------------------------69343412719991675451336310646",
"Content-Disposition: form-data;",
" name=\"a\"",
"",
"1",
"-------------------------------69343412719991675451336310646",
"Content-Disposition: form-data;",
" name=\"b\"",
"",
"2",
"-------------------------------69343412719991675451336310646--"
]
},
"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":"ARGS:a"
},
"rules":[
"SecRule MULTIPART_STRICT_ERROR \"!@eq 1\" \"phase:2,deny,status:403,id:500074\"",
"SecRule MULTIPART_HEADER_FOLDING \"!@eq 1\" \"phase:2,deny,status:403,id:500075\"",
"SecRule MULTIPART_INVALID_HEADER_FOLDING \"!@eq 0\" \"phase:2,deny,status:403,id:500076\"",
"SecRule REQBODY_PROCESSOR_ERROR \"@eq 1\" \"phase:2,deny,status:403,id:500077\"",
"SecRule ARGS \"@eq 1\" \"phase:2,deny,status:403,id:5000277\""
]
}
]

View File

@ -23,21 +23,21 @@
"uri":"/",
"method":"POST",
"body":[
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"name\"",
"",
"test",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is a very small test file..",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is another very small test file..",
"--------------------------756b6d74fa1a8ee2--"
"----------------------------756b6d74fa1a8ee2--"
]
},
"response":{
@ -84,21 +84,21 @@
"uri":"/",
"method":"POST",
"body":[
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"name\"",
"",
"test",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is a very small test file..",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata2\"; filename=\"small_text_file2.txt\"\r",
"Content-Type: text/plain\r",
"\r",
"This is another very small test file..\r",
"--------------------------756b6d74fa1a8ee2--\r"
"----------------------------756b6d74fa1a8ee2--\r"
]
},
"response":{

View File

@ -267,21 +267,21 @@
"uri":"/",
"method":"POST",
"body":[
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"name\"",
"",
"test",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is a very small test file..",
"--------------------------756b6d74fa1a8ee2",
"----------------------------756b6d74fa1a8ee2",
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
"Content-Type: text/plain",
"",
"This is another very small test file..",
"--------------------------756b6d74fa1a8ee2--"
"----------------------------756b6d74fa1a8ee2--"
]
},
"response":{
@ -295,7 +295,7 @@
]
},
"expected":{
"debug_log":"Boundary missing semicolon, setting MULTIPART_STRICT_ERROR to 1"
"debug_log":"Warning: incorrect line endings used \(LF\)"
},
"rules":[
"SecRuleEngine On",
@ -356,7 +356,7 @@
]
},
"expected":{
"debug_log":"Multipart: Invalid quote, setting MULTIPART_STRICT_ERROR to 1"
"debug_log":"Multipart: Warning: seen data before first boundary"
},
"rules":[
"SecRuleEngine On",