mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-13 21:36:00 +03:00
Fix: Only delete Multipart tmp files after rules have run
This commit is contained in:
parent
1b7aa42c77
commit
d72be1c470
2
CHANGES
2
CHANGES
@ -1,6 +1,8 @@
|
|||||||
v3.x.y - YYYY-MMM-DD (to be released)
|
v3.x.y - YYYY-MMM-DD (to be released)
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
- Fix: Only delete Multipart tmp files after rules have run
|
||||||
|
[Issue #2427 - @martinhsv]
|
||||||
- Fixed MatchedVar on chained rules
|
- Fixed MatchedVar on chained rules
|
||||||
[Issue #2423, #2435, #2436 - @michaelgranzow-avi]
|
[Issue #2423, #2435, #2436 - @michaelgranzow-avi]
|
||||||
- Add support for new operator rxGlobal
|
- Add support for new operator rxGlobal
|
||||||
|
@ -159,6 +159,7 @@ TESTS+=test/test-cases/regression/issue-2000.json
|
|||||||
TESTS+=test/test-cases/regression/issue-2111.json
|
TESTS+=test/test-cases/regression/issue-2111.json
|
||||||
TESTS+=test/test-cases/regression/issue-2196.json
|
TESTS+=test/test-cases/regression/issue-2196.json
|
||||||
TESTS+=test/test-cases/regression/issue-2423-msg-in-chain.json
|
TESTS+=test/test-cases/regression/issue-2423-msg-in-chain.json
|
||||||
|
TESTS+=test/test-cases/regression/issue-2427.json
|
||||||
TESTS+=test/test-cases/regression/issue-394.json
|
TESTS+=test/test-cases/regression/issue-394.json
|
||||||
TESTS+=test/test-cases/regression/issue-849.json
|
TESTS+=test/test-cases/regression/issue-849.json
|
||||||
TESTS+=test/test-cases/regression/issue-960.json
|
TESTS+=test/test-cases/regression/issue-960.json
|
||||||
|
@ -111,6 +111,7 @@ enum AllowType : int;
|
|||||||
namespace RequestBodyProcessor {
|
namespace RequestBodyProcessor {
|
||||||
class XML;
|
class XML;
|
||||||
class JSON;
|
class JSON;
|
||||||
|
class MultipartPartTmpFile;
|
||||||
}
|
}
|
||||||
namespace operators {
|
namespace operators {
|
||||||
class Operator;
|
class Operator;
|
||||||
@ -612,6 +613,8 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa
|
|||||||
std::string m_variableTimeWDay;
|
std::string m_variableTimeWDay;
|
||||||
std::string m_variableTimeYear;
|
std::string m_variableTimeYear;
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<RequestBodyProcessor::MultipartPartTmpFile>> m_multipartPartTmpFiles;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Pointer to the callback function that will be called to fill
|
* Pointer to the callback function that will be called to fill
|
||||||
|
@ -38,6 +38,61 @@ namespace RequestBodyProcessor {
|
|||||||
static const char* mime_charset_special = "!#$%&+-^_`{}~";
|
static const char* mime_charset_special = "!#$%&+-^_`{}~";
|
||||||
static const char* attr_char_special = "!#$&+-.^_`~";
|
static const char* attr_char_special = "!#$&+-.^_`~";
|
||||||
|
|
||||||
|
MultipartPartTmpFile::~MultipartPartTmpFile() {
|
||||||
|
if (!m_tmp_file_name.empty() && m_delete) {
|
||||||
|
/* make sure it is closed first */
|
||||||
|
if (m_tmp_file_fd > 0) {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
const int unlink_rc = unlink(m_tmp_file_name.c_str());
|
||||||
|
if (unlink_rc < 0) {
|
||||||
|
ms_dbg_a(m_transaction, 1, "Multipart: Failed to delete file (part) \"" \
|
||||||
|
+ m_tmp_file_name + "\" because " \
|
||||||
|
+ std::to_string(errno) + "(" \
|
||||||
|
+ strerror(errno) + ")");
|
||||||
|
} else {
|
||||||
|
ms_dbg_a(m_transaction, 4, "Multipart: file deleted successfully (part) \"" \
|
||||||
|
+ m_tmp_file_name + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultipartPartTmpFile::Open() {
|
||||||
|
struct tm timeinfo;
|
||||||
|
char tstr[300];
|
||||||
|
time_t tt = time(NULL);
|
||||||
|
|
||||||
|
localtime_r(&tt, &timeinfo);
|
||||||
|
|
||||||
|
memset(tstr, '\0', 300);
|
||||||
|
strftime(tstr, 299, "/%Y%m%d-%H%M%S", &timeinfo);
|
||||||
|
|
||||||
|
std::string path = m_transaction->m_rules->m_uploadDirectory.m_value;
|
||||||
|
path = path + tstr + "-" + *m_transaction->m_id.get();
|
||||||
|
path += "-file-XXXXXX";
|
||||||
|
|
||||||
|
char* tmp = strdup(path.c_str());
|
||||||
|
m_tmp_file_fd = mkstemp(tmp);
|
||||||
|
m_tmp_file_name.assign(tmp);
|
||||||
|
free(tmp);
|
||||||
|
ms_dbg_a(m_transaction, 4, "MultipartPartTmpFile: Create filename= " + m_tmp_file_name);
|
||||||
|
|
||||||
|
int mode = m_transaction->m_rules->m_uploadFileMode.m_value;
|
||||||
|
if ((m_tmp_file_fd != -1) && (mode != 0)) {
|
||||||
|
if (fchmod(m_tmp_file_fd, mode) == -1) {
|
||||||
|
m_tmp_file_fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultipartPartTmpFile::Close() {
|
||||||
|
close(m_tmp_file_fd);
|
||||||
|
m_tmp_file_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Multipart::Multipart(const std::string &header, Transaction *transaction)
|
Multipart::Multipart(const std::string &header, Transaction *transaction)
|
||||||
: m_reqbody_no_files_length(0),
|
: m_reqbody_no_files_length(0),
|
||||||
m_nfiles(0),
|
m_nfiles(0),
|
||||||
@ -80,32 +135,16 @@ Multipart::~Multipart() {
|
|||||||
if (m_transaction->m_rules->m_uploadKeepFiles
|
if (m_transaction->m_rules->m_uploadKeepFiles
|
||||||
!= RulesSetProperties::TrueConfigBoolean) {
|
!= RulesSetProperties::TrueConfigBoolean) {
|
||||||
for (MultipartPart *m : m_parts) {
|
for (MultipartPart *m : m_parts) {
|
||||||
if (m->m_type == MULTIPART_FILE) {
|
if ((m->m_type == MULTIPART_FILE) && (m->m_tmp_file)) {
|
||||||
if (!m->m_tmp_file_name.empty()) {
|
// only mark for deletion for now; the file should stay on disk until
|
||||||
/* make sure it is closed first */
|
// the transaction is complete
|
||||||
if (m->m_tmp_file_fd > 0) {
|
ms_dbg_a(m_transaction, 9, "Multipart: Marking temporary file for deletion: " \
|
||||||
close(m->m_tmp_file_fd);
|
+ m->m_tmp_file->getFilename());
|
||||||
m->m_tmp_file_fd = -1;
|
m->m_tmp_file->setDelete();
|
||||||
}
|
|
||||||
const int unlink_rc =
|
|
||||||
unlink(m->m_tmp_file_name.c_str());
|
|
||||||
|
|
||||||
if (unlink_rc < 0) {
|
|
||||||
ms_dbg_a(m_transaction, 1,
|
|
||||||
"Multipart: Failed to delete file (part) \"" \
|
|
||||||
+ m->m_tmp_file_name + "\" because " \
|
|
||||||
+ std::to_string(errno) + "(" \
|
|
||||||
+ strerror(errno) + ")");
|
|
||||||
} else {
|
|
||||||
ms_dbg_a(m_transaction, 4,
|
|
||||||
"Multipart: file deleted successfully (part) \"" \
|
|
||||||
+ m->m_tmp_file_name + "\"");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (m_parts.empty() == false) {
|
while (m_parts.empty() == false) {
|
||||||
auto *a = m_parts.back();
|
auto *a = m_parts.back();
|
||||||
@ -432,7 +471,7 @@ int Multipart::parse_content_disposition(const char *c_d_value, int offset) {
|
|||||||
+ std::to_string(strlen(p)) + " bytes");
|
+ std::to_string(strlen(p)) + " bytes");
|
||||||
m_flag_invalid_quoting = 1;
|
m_flag_invalid_quoting = 1;
|
||||||
}
|
}
|
||||||
p++;
|
/* p++; */
|
||||||
return -12;
|
return -12;
|
||||||
}
|
}
|
||||||
p++; /* move over the semi-colon */
|
p++; /* move over the semi-colon */
|
||||||
@ -453,40 +492,6 @@ int Multipart::parse_content_disposition(const char *c_d_value, int offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Multipart::tmp_file_name(std::string *filename) const {
|
|
||||||
std::string path;
|
|
||||||
struct tm timeinfo;
|
|
||||||
char tstr[300];
|
|
||||||
char *tmp;
|
|
||||||
int fd;
|
|
||||||
int mode;
|
|
||||||
time_t tt = time(NULL);
|
|
||||||
|
|
||||||
localtime_r(&tt, &timeinfo);
|
|
||||||
|
|
||||||
path = m_transaction->m_rules->m_uploadDirectory.m_value;
|
|
||||||
mode = m_transaction->m_rules->m_uploadFileMode.m_value;
|
|
||||||
|
|
||||||
memset(tstr, '\0', 300);
|
|
||||||
strftime(tstr, 299, "/%Y%m%d-%H%M%S", &timeinfo);
|
|
||||||
path = path + tstr + "-" + *m_transaction->m_id.get();
|
|
||||||
path = path + "-file-XXXXXX";
|
|
||||||
|
|
||||||
tmp = strdup(path.c_str());
|
|
||||||
|
|
||||||
fd = mkstemp(tmp);
|
|
||||||
filename->assign(tmp);
|
|
||||||
free(tmp);
|
|
||||||
if ((fd != -1) && (mode != 0)) {
|
|
||||||
if (fchmod(fd, mode) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int Multipart::process_part_data(std::string *error, size_t offset) {
|
int Multipart::process_part_data(std::string *error, size_t offset) {
|
||||||
char *p = m_buf + (MULTIPART_BUF_SIZE - m_bufleft);
|
char *p = m_buf + (MULTIPART_BUF_SIZE - m_bufleft);
|
||||||
char localreserve[2] = { '\0', '\0' }; /* initialized to quiet warning */
|
char localreserve[2] = { '\0', '\0' }; /* initialized to quiet warning */
|
||||||
@ -546,20 +551,18 @@ int Multipart::process_part_data(std::string *error, size_t offset) {
|
|||||||
*/
|
*/
|
||||||
if (extract) {
|
if (extract) {
|
||||||
/* first create a temporary file if we don't have it already */
|
/* first create a temporary file if we don't have it already */
|
||||||
if (m_mpp->m_tmp_file_fd == 0) {
|
if (!m_mpp->m_tmp_file || !m_mpp->m_tmp_file->isValid()) {
|
||||||
std::string path;
|
m_mpp->m_tmp_file = std::make_shared<RequestBodyProcessor::MultipartPartTmpFile>(m_transaction);
|
||||||
m_mpp->m_tmp_file_fd = tmp_file_name(&path);
|
m_transaction->m_multipartPartTmpFiles.push_back(m_mpp->m_tmp_file);
|
||||||
|
m_mpp->m_tmp_file->Open();
|
||||||
/* construct temporary file name */
|
|
||||||
m_mpp->m_tmp_file_name = path;
|
|
||||||
|
|
||||||
/* do we have an opened file? */
|
/* do we have an opened file? */
|
||||||
if (m_mpp->m_tmp_file_fd < 0) {
|
if (!m_mpp->m_tmp_file || m_mpp->m_tmp_file->getFd() < 0) {
|
||||||
ms_dbg_a(m_transaction, 1,
|
ms_dbg_a(m_transaction, 1,
|
||||||
"Multipart: Failed to create file: " \
|
"Multipart: Failed to create file: " \
|
||||||
+ m_mpp->m_tmp_file_name);
|
+ m_mpp->m_tmp_file->getFilename());
|
||||||
error->assign("Multipart: Failed to create file: " \
|
error->assign("Multipart: Failed to create file: " \
|
||||||
+ m_mpp->m_tmp_file_name);
|
+ m_mpp->m_tmp_file->getFilename());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* keep track of the files count */
|
/* keep track of the files count */
|
||||||
@ -569,18 +572,18 @@ int Multipart::process_part_data(std::string *error, size_t offset) {
|
|||||||
ms_dbg_a(m_transaction, 4,
|
ms_dbg_a(m_transaction, 4,
|
||||||
"Multipart: Created temporary file " \
|
"Multipart: Created temporary file " \
|
||||||
+ std::to_string(m_nfiles) + " (mode o" + std::to_string(m_transaction->m_rules->m_uploadFileMode.m_value) + "): " \
|
+ std::to_string(m_nfiles) + " (mode o" + std::to_string(m_transaction->m_rules->m_uploadFileMode.m_value) + "): " \
|
||||||
+ m_mpp->m_tmp_file_name);
|
+ m_mpp->m_tmp_file->getFilename());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write the reserve first */
|
/* write the reserve first */
|
||||||
if (m_reserve[0] != 0) {
|
if (m_reserve[0] != 0) {
|
||||||
if (write(m_mpp->m_tmp_file_fd, &m_reserve[1], m_reserve[0])
|
if (write(m_mpp->m_tmp_file->getFd(), &m_reserve[1], m_reserve[0])
|
||||||
!= m_reserve[0]) {
|
!= m_reserve[0]) {
|
||||||
ms_dbg_a(m_transaction, 1,
|
ms_dbg_a(m_transaction, 1,
|
||||||
"Multipart: writing to \"" \
|
"Multipart: writing to \"" \
|
||||||
+ m_mpp->m_tmp_file_name + "\" failed");
|
+ m_mpp->m_tmp_file->getFilename() + "\" failed");
|
||||||
error->assign("Multipart: writing to \"" \
|
error->assign("Multipart: writing to \"" \
|
||||||
+ m_mpp->m_tmp_file_name + "\" failed");
|
+ m_mpp->m_tmp_file->getFilename() + "\" failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,14 +597,14 @@ int Multipart::process_part_data(std::string *error, size_t offset) {
|
|||||||
|
|
||||||
/* write data to the file */
|
/* write data to the file */
|
||||||
|
|
||||||
if (write(m_mpp->m_tmp_file_fd, m_buf,
|
if (write(m_mpp->m_tmp_file->getFd(), m_buf,
|
||||||
MULTIPART_BUF_SIZE - m_bufleft)
|
MULTIPART_BUF_SIZE - m_bufleft)
|
||||||
!= (MULTIPART_BUF_SIZE - m_bufleft)) {
|
!= (MULTIPART_BUF_SIZE - m_bufleft)) {
|
||||||
ms_dbg_a(m_transaction, 1,
|
ms_dbg_a(m_transaction, 1,
|
||||||
"Multipart: writing to \"" \
|
"Multipart: writing to \"" \
|
||||||
+ m_mpp->m_tmp_file_name + "\" failed");
|
+ m_mpp->m_tmp_file->getFilename() + "\" failed");
|
||||||
error->assign("Multipart: writing to \"" \
|
error->assign("Multipart: writing to \"" \
|
||||||
+ m_mpp->m_tmp_file_name + "\" failed");
|
+ m_mpp->m_tmp_file->getFilename() + "\" failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,11 +914,9 @@ int Multipart::process_boundary(int last_part) {
|
|||||||
/* if there was a part being built finish it */
|
/* if there was a part being built finish it */
|
||||||
if (m_mpp != NULL) {
|
if (m_mpp != NULL) {
|
||||||
/* close the temp file */
|
/* close the temp file */
|
||||||
if ((m_mpp->m_type == MULTIPART_FILE)
|
if ((m_mpp->m_type == MULTIPART_FILE) && (m_mpp->m_tmp_file)
|
||||||
&& (!m_mpp->m_tmp_file_name.empty())
|
&& (m_mpp->m_tmp_file->isValid())) {
|
||||||
&& (m_mpp->m_tmp_file_fd != 0)) {
|
m_mpp->m_tmp_file->Close();
|
||||||
close(m_mpp->m_tmp_file_fd);
|
|
||||||
m_mpp->m_tmp_file_fd = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_mpp->m_type != MULTIPART_FILE) {
|
if (m_mpp->m_type != MULTIPART_FILE) {
|
||||||
@ -1128,8 +1129,10 @@ int Multipart::multipart_complete(std::string *error) {
|
|||||||
if (m->m_type == MULTIPART_FILE) {
|
if (m->m_type == MULTIPART_FILE) {
|
||||||
std::string tmp_name;
|
std::string tmp_name;
|
||||||
std::string name;
|
std::string name;
|
||||||
if (!m->m_tmp_file_name.empty()) {
|
if (m->m_tmp_file && !m->m_tmp_file->getFilename().empty()) {
|
||||||
tmp_name.assign(m->m_tmp_file_name);
|
tmp_name.assign(m->m_tmp_file->getFilename());
|
||||||
|
m_transaction->m_variableFilesTmpNames.set(m->m_tmp_file->getFilename(),
|
||||||
|
m->m_tmp_file->getFilename(), m->m_filenameOffset);
|
||||||
}
|
}
|
||||||
if (!m->m_filename.empty()) {
|
if (!m->m_filename.empty()) {
|
||||||
name.assign(m->m_filename);
|
name.assign(m->m_filename);
|
||||||
@ -1149,9 +1152,6 @@ int Multipart::multipart_complete(std::string *error) {
|
|||||||
m_transaction->m_variableFilesTmpContent.set(m->m_filename,
|
m_transaction->m_variableFilesTmpContent.set(m->m_filename,
|
||||||
m->m_value, m->m_valueOffset);
|
m->m_value, m->m_valueOffset);
|
||||||
|
|
||||||
m_transaction->m_variableFilesTmpNames.set(m->m_tmp_file_name,
|
|
||||||
m->m_tmp_file_name, m->m_filenameOffset);
|
|
||||||
|
|
||||||
file_combined_size = file_combined_size + m->m_tmp_file_size.first;
|
file_combined_size = file_combined_size + m->m_tmp_file_size.first;
|
||||||
|
|
||||||
m_transaction->m_variableFilesCombinedSize.set(
|
m_transaction->m_variableFilesCombinedSize.set(
|
||||||
|
@ -54,6 +54,38 @@ struct MyEqual {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MultipartPartTmpFile {
|
||||||
|
public:
|
||||||
|
explicit MultipartPartTmpFile(Transaction *transaction)
|
||||||
|
: m_transaction(transaction),
|
||||||
|
m_tmp_file_fd(0),
|
||||||
|
m_delete(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~MultipartPartTmpFile();
|
||||||
|
|
||||||
|
// forbid copying
|
||||||
|
MultipartPartTmpFile(const MultipartPartTmpFile&) = delete;
|
||||||
|
MultipartPartTmpFile& operator=(const MultipartPartTmpFile&) = delete;
|
||||||
|
|
||||||
|
int getFd() const {return m_tmp_file_fd;}
|
||||||
|
void setFd(int fd) {m_tmp_file_fd = fd;}
|
||||||
|
const std::string& getFilename() const {return m_tmp_file_name;}
|
||||||
|
void setDelete() {m_delete = true;}
|
||||||
|
|
||||||
|
bool isValid() const {return ((m_tmp_file_fd != 0) && (!m_tmp_file_name.empty()));}
|
||||||
|
|
||||||
|
void Open();
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Transaction *m_transaction;
|
||||||
|
int m_tmp_file_fd;
|
||||||
|
std::string m_tmp_file_name;
|
||||||
|
bool m_delete; // whether to delete when transaction is done
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class MultipartPart {
|
class MultipartPart {
|
||||||
public:
|
public:
|
||||||
MultipartPart()
|
MultipartPart()
|
||||||
@ -63,8 +95,6 @@ class MultipartPart {
|
|||||||
m_value(""),
|
m_value(""),
|
||||||
m_valueOffset(0),
|
m_valueOffset(0),
|
||||||
m_value_parts(),
|
m_value_parts(),
|
||||||
m_tmp_file_name(""),
|
|
||||||
m_tmp_file_fd(0),
|
|
||||||
m_tmp_file_size(),
|
m_tmp_file_size(),
|
||||||
m_filename(""),
|
m_filename(""),
|
||||||
m_filenameOffset(0),
|
m_filenameOffset(0),
|
||||||
@ -98,8 +128,7 @@ class MultipartPart {
|
|||||||
/* std::string m_content_type; */
|
/* std::string m_content_type; */
|
||||||
|
|
||||||
/* files only, the name of the temporary file holding data */
|
/* files only, the name of the temporary file holding data */
|
||||||
std::string m_tmp_file_name;
|
std::shared_ptr<RequestBodyProcessor::MultipartPartTmpFile> m_tmp_file;
|
||||||
int m_tmp_file_fd;
|
|
||||||
std::pair<size_t, size_t> m_tmp_file_size;
|
std::pair<size_t, size_t> m_tmp_file_size;
|
||||||
|
|
||||||
/* files only, filename as supplied by the browser */
|
/* files only, filename as supplied by the browser */
|
||||||
@ -133,8 +162,6 @@ class Multipart {
|
|||||||
int process_part_header(std::string *error, int offset);
|
int process_part_header(std::string *error, int offset);
|
||||||
int process_part_data(std::string *error, size_t offset);
|
int process_part_data(std::string *error, size_t offset);
|
||||||
|
|
||||||
int tmp_file_name(std::string *filename) const;
|
|
||||||
|
|
||||||
void validate_quotes(const char *data);
|
void validate_quotes(const char *data);
|
||||||
|
|
||||||
size_t m_reqbody_no_files_length;
|
size_t m_reqbody_no_files_length;
|
||||||
|
@ -35,7 +35,7 @@ invalidScanfArgType_int:src/rules_set_properties.cc:102
|
|||||||
unmatchedSuppression:src/utils/geo_lookup.cc:82
|
unmatchedSuppression:src/utils/geo_lookup.cc:82
|
||||||
useInitializationList:src/utils/shared_files.h:87
|
useInitializationList:src/utils/shared_files.h:87
|
||||||
unmatchedSuppression:src/utils/msc_tree.cc
|
unmatchedSuppression:src/utils/msc_tree.cc
|
||||||
functionStatic:headers/modsecurity/transaction.h:404
|
functionStatic:headers/modsecurity/transaction.h:405
|
||||||
duplicateBranch:src/audit_log/audit_log.cc:223
|
duplicateBranch:src/audit_log/audit_log.cc:223
|
||||||
unreadVariable:src/request_body_processor/multipart.cc:435
|
unreadVariable:src/request_body_processor/multipart.cc:435
|
||||||
stlcstrParam:src/audit_log/writer/parallel.cc:145
|
stlcstrParam:src/audit_log/writer/parallel.cc:145
|
||||||
|
10
test/test-cases/data/inspectFile-abcdef.lua
Normal file
10
test/test-cases/data/inspectFile-abcdef.lua
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/lua
|
||||||
|
|
||||||
|
function main(filename)
|
||||||
|
local file = io.open(filename, 'r')
|
||||||
|
local chunk = file:read(1024)
|
||||||
|
local ret = string.match(chunk, 'abcdef')
|
||||||
|
io.close(file)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
121
test/test-cases/regression/issue-2427.json
Normal file
121
test/test-cases/regression/issue-2427.json
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"Tmp file retained for @inspectFile (1/2)",
|
||||||
|
"resource":"lua",
|
||||||
|
"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":"/wheee/f%20i%20l%20e%20",
|
||||||
|
"method":"POST",
|
||||||
|
"body":[
|
||||||
|
"----------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; name=\"name\"",
|
||||||
|
"",
|
||||||
|
"test",
|
||||||
|
"----------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; name=\"name2\"",
|
||||||
|
"",
|
||||||
|
"test2",
|
||||||
|
"----------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"",
|
||||||
|
"Content-Type: text/plain",
|
||||||
|
"",
|
||||||
|
"This is a very small test file..",
|
||||||
|
"----------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"small2.txt\" ",
|
||||||
|
"Content-Type: text/plain",
|
||||||
|
"",
|
||||||
|
"This is another very small test file that contains the search content abcdef..",
|
||||||
|
"----------------------------756b6d74fa1a8ee2--"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"expected":{
|
||||||
|
"debug_log":"Returning from lua script: abcdef.*Rule returned 1",
|
||||||
|
"http_code":403
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecRequestBodyAccess On",
|
||||||
|
"SecTmpSaveUploadedFiles On",
|
||||||
|
"SecUploadKeepFiles Off",
|
||||||
|
"SecUploadDir /tmp",
|
||||||
|
"SecTmpDir /tmp",
|
||||||
|
"SecRule FILES_TMPNAMES \"@inspectFile test-cases/data/inspectFile-abcdef.lua\" \"id:1,phase:2,deny,status:403\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"Tmp file retained for @inspectFile (2/2)",
|
||||||
|
"resource":"lua",
|
||||||
|
"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":"/wheee/f%20i%20l%20e%20",
|
||||||
|
"method":"POST",
|
||||||
|
"body":[
|
||||||
|
"----------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; name=\"name\"",
|
||||||
|
"",
|
||||||
|
"test",
|
||||||
|
"----------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; name=\"name2\"",
|
||||||
|
"",
|
||||||
|
"test2",
|
||||||
|
"----------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"",
|
||||||
|
"Content-Type: text/plain",
|
||||||
|
"",
|
||||||
|
"This is a very small test file..",
|
||||||
|
"----------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"small2.txt\" ",
|
||||||
|
"Content-Type: text/plain",
|
||||||
|
"",
|
||||||
|
"This is another very small test file that does not contain the search content.",
|
||||||
|
"----------------------------756b6d74fa1a8ee2--"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"expected":{
|
||||||
|
"http_code":200
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecRequestBodyAccess On",
|
||||||
|
"SecTmpSaveUploadedFiles On",
|
||||||
|
"SecUploadKeepFiles Off",
|
||||||
|
"SecUploadDir /tmp",
|
||||||
|
"SecTmpDir /tmp",
|
||||||
|
"SecRule FILES_TMPNAMES \"@inspectFile test-cases/data/inspectFile-abcdef.lua\" \"id:1,phase:2,deny,status:403\""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
Loading…
x
Reference in New Issue
Block a user