mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-13 13:26:01 +03:00
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:
parent
9e5cf2de8e
commit
2e3da7ea24
@ -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;
|
||||
|
||||
|
@ -200,7 +200,6 @@ COLLECTION = \
|
||||
|
||||
BODY_PROCESSORS = \
|
||||
request_body_processor/multipart.cc \
|
||||
request_body_processor/multipart_blob.cc \
|
||||
request_body_processor/xml.cc
|
||||
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
@ -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
|
||||
|
||||
|
@ -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
|
@ -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_
|
12
src/rules.cc
12
src/rules.cc
@ -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());
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
2453
test/test-cases/regression/request-body-parser-multipart.json
Normal file
2453
test/test-cases/regression/request-body-parser-multipart.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -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":{
|
||||
|
@ -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\""
|
||||
]
|
||||
}
|
||||
]
|
@ -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":{
|
||||
|
@ -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":{
|
||||
|
@ -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\""
|
||||
]
|
||||
}
|
||||
]
|
@ -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":{
|
||||
|
@ -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":{
|
||||
|
@ -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\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -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":{
|
||||
|
@ -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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user