Compare commits
10 Commits
5e57174ecc
...
355f4cd417
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
355f4cd417 | ||
|
|
498cf8cbca | ||
|
|
874053013c | ||
|
|
c27ee70936 | ||
|
|
ee260ce51a | ||
|
|
b495b0af90 | ||
|
|
f7bedeb457 | ||
|
|
83f233a3b7 | ||
|
|
2499f5930f | ||
|
|
790462571f |
5
10-mod_security.conf
Normal file
5
10-mod_security.conf
Normal file
@ -0,0 +1,5 @@
|
||||
LoadModule security2_module modules/mod_security2.so
|
||||
|
||||
<IfModule !mod_unique_id.c>
|
||||
LoadModule unique_id_module modules/mod_unique_id.so
|
||||
</IfModule>
|
||||
405
CVE-2022-48279.patch
Normal file
405
CVE-2022-48279.patch
Normal file
@ -0,0 +1,405 @@
|
||||
From 7a489bd07c66d3df19a320b4306e00c49716dbb0 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Vierula <martin.vierula@trustwave.com>
|
||||
Date: Wed, 7 Sep 2022 11:09:47 -0700
|
||||
Subject: [PATCH] Multipart parsing fixes and new MULTIPART_PART_HEADERS
|
||||
collection
|
||||
|
||||
---
|
||||
CHANGES | 2 +
|
||||
apache2/msc_multipart.c | 148 ++++++++++++++------
|
||||
apache2/msc_multipart.h | 19 +++
|
||||
apache2/re_variables.c | 57 ++++++++
|
||||
tests/regression/misc/00-multipart-parser.t | 45 ++++++
|
||||
5 files changed, 230 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/apache2/msc_multipart.c b/apache2/msc_multipart.c
|
||||
index d087c863e..4128ab17e 100644
|
||||
--- a/apache2/msc_multipart.c
|
||||
+++ b/apache2/msc_multipart.c
|
||||
@@ -325,7 +325,14 @@ static int multipart_process_part_header(modsec_rec *msr, char **error_msg) {
|
||||
}
|
||||
|
||||
msr->mpd->mpp_state = 1;
|
||||
+ msr->mpd->mpp_substate_part_data_read = 0;
|
||||
msr->mpd->mpp->last_header_name = NULL;
|
||||
+
|
||||
+ /* Record the last part header line in the collection */
|
||||
+ if (msr->mpd->mpp->last_header_line != NULL) {
|
||||
+ *(char **)apr_array_push(msr->mpd->mpp->header_lines) = msr->mpd->mpp->last_header_line;
|
||||
+ msr_log(msr, 9, "Multipart: Added part header line \"%s\"", msr->mpd->mpp->last_header_line);
|
||||
+ }
|
||||
} else {
|
||||
/* Header line. */
|
||||
|
||||
@@ -379,12 +386,28 @@ static int multipart_process_part_header(modsec_rec *msr, char **error_msg) {
|
||||
*error_msg = apr_psprintf(msr->mp, "Multipart: Part header too long.");
|
||||
return -1;
|
||||
}
|
||||
+ if ((msr->mpd->mpp->last_header_line != NULL) && (msr->mpd->mpp->last_header_name != NULL)
|
||||
+ && (new_value != NULL)) {
|
||||
+ msr->mpd->mpp->last_header_line = apr_psprintf(msr->mp,
|
||||
+ "%s: %s", msr->mpd->mpp->last_header_name, new_value);
|
||||
+ }
|
||||
+
|
||||
} else {
|
||||
char *header_name, *header_value, *data;
|
||||
|
||||
/* new header */
|
||||
|
||||
+ /* Record the most recently-seen part header line in the collection */
|
||||
+ if (msr->mpd->mpp->last_header_line != NULL) {
|
||||
+ *(char **)apr_array_push(msr->mpd->mpp->header_lines) = msr->mpd->mpp->last_header_line;
|
||||
+ msr_log(msr, 9, "Multipart: Added part header line \"%s\"", msr->mpd->mpp->last_header_line);
|
||||
+ }
|
||||
+
|
||||
data = msr->mpd->buf;
|
||||
+
|
||||
+ msr->mpd->mpp->last_header_line = apr_pstrdup(msr->mp, data);
|
||||
+ remove_lf_crlf_inplace(msr->mpd->mpp->last_header_line);
|
||||
+
|
||||
while((*data != ':') && (*data != '\0')) data++;
|
||||
if (*data == '\0') {
|
||||
*error_msg = apr_psprintf(msr->mp, "Multipart: Invalid part header (colon missing): %s.",
|
||||
@@ -438,6 +461,8 @@ static int multipart_process_part_data(modsec_rec *msr, char **error_msg) {
|
||||
if (error_msg == NULL) return -1;
|
||||
*error_msg = NULL;
|
||||
|
||||
+ msr->mpd->mpp_substate_part_data_read = 1;
|
||||
+
|
||||
/* Preserve some bytes for later. */
|
||||
if ( ((MULTIPART_BUF_SIZE - msr->mpd->bufleft) >= 1)
|
||||
&& (*(p - 1) == '\n') )
|
||||
@@ -680,10 +705,14 @@ static int multipart_process_boundary(modsec_rec *msr, int last_part, char **err
|
||||
if (msr->mpd->mpp == NULL) return -1;
|
||||
msr->mpd->mpp->type = MULTIPART_FORMDATA;
|
||||
msr->mpd->mpp_state = 0;
|
||||
+ msr->mpd->mpp_substate_part_data_read = 0;
|
||||
|
||||
msr->mpd->mpp->headers = apr_table_make(msr->mp, 10);
|
||||
if (msr->mpd->mpp->headers == NULL) return -1;
|
||||
msr->mpd->mpp->last_header_name = NULL;
|
||||
+ msr->mpd->mpp->last_header_line = NULL;
|
||||
+ msr->mpd->mpp->header_lines = apr_array_make(msr->mp, 2, sizeof(char *));
|
||||
+ if (msr->mpd->mpp->header_lines == NULL) return -1;
|
||||
|
||||
msr->mpd->reserve[0] = 0;
|
||||
msr->mpd->reserve[1] = 0;
|
||||
@@ -983,6 +1012,19 @@ int multipart_complete(modsec_rec *msr, char **error_msg) {
|
||||
&& (*(msr->mpd->buf + 2 + strlen(msr->mpd->boundary)) == '-')
|
||||
&& (*(msr->mpd->buf + 2 + strlen(msr->mpd->boundary) + 1) == '-') )
|
||||
{
|
||||
+ if ((msr->mpd->crlf_state_buf_end == 2) && (msr->mpd->flag_lf_line != 1)) {
|
||||
+ msr->mpd->flag_lf_line = 1;
|
||||
+ if (msr->mpd->flag_crlf_line) {
|
||||
+ msr_log(msr, 4, "Multipart: Warning: mixed line endings used (CRLF/LF).");
|
||||
+ } else {
|
||||
+ msr_log(msr, 4, "Multipart: Warning: incorrect line endings used (LF).");
|
||||
+ }
|
||||
+ }
|
||||
+ if (msr->mpd->mpp_substate_part_data_read == 0) {
|
||||
+ /* it looks like the final boundary, but it's where part data should begin */
|
||||
+ msr->mpd->flag_invalid_part = 1;
|
||||
+ msr_log(msr, 4, "Multipart: Warning: Invalid part (data contains final boundary)");
|
||||
+ }
|
||||
/* Looks like the final boundary - process it. */
|
||||
if (multipart_process_boundary(msr, 1 /* final */, error_msg) < 0) {
|
||||
msr->mpd->flag_error = 1;
|
||||
@@ -1075,54 +1117,63 @@ int multipart_process_chunk(modsec_rec *msr, const char *buf,
|
||||
if ( (strlen(msr->mpd->buf) >= strlen(msr->mpd->boundary) + 2)
|
||||
&& (strncmp(msr->mpd->buf + 2, msr->mpd->boundary, strlen(msr->mpd->boundary)) == 0) )
|
||||
{
|
||||
- char *boundary_end = msr->mpd->buf + 2 + strlen(msr->mpd->boundary);
|
||||
- int is_final = 0;
|
||||
+ if (msr->mpd->crlf_state_buf_end == 2) {
|
||||
+ msr->mpd->flag_lf_line = 1;
|
||||
+ }
|
||||
+ if ((msr->mpd->mpp_substate_part_data_read == 0) && (msr->mpd->boundary_count > 0)) {
|
||||
+ /* string matches our boundary, but it's where part data should begin */
|
||||
+ msr->mpd->flag_invalid_part = 1;
|
||||
+ msr_log(msr, 4, "Multipart: Warning: Invalid part (data contains boundary)");
|
||||
+ } else {
|
||||
+ char *boundary_end = msr->mpd->buf + 2 + strlen(msr->mpd->boundary);
|
||||
+ int is_final = 0;
|
||||
+
|
||||
+ /* Is this the final boundary? */
|
||||
+ if ((*boundary_end == '-') && (*(boundary_end + 1)== '-')) {
|
||||
+ is_final = 1;
|
||||
+ boundary_end += 2;
|
||||
+
|
||||
+ if (msr->mpd->is_complete != 0) {
|
||||
+ msr->mpd->flag_error = 1;
|
||||
+ *error_msg = apr_psprintf(msr->mp,
|
||||
+ "Multipart: Invalid boundary (final duplicate).");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- /* Is this the final boundary? */
|
||||
- if ((*boundary_end == '-') && (*(boundary_end + 1)== '-')) {
|
||||
- is_final = 1;
|
||||
- boundary_end += 2;
|
||||
+ /* Allow for CRLF and LF line endings. */
|
||||
+ if ( ( (*boundary_end == '\r')
|
||||
+ && (*(boundary_end + 1) == '\n')
|
||||
+ && (*(boundary_end + 2) == '\0') )
|
||||
+ || ( (*boundary_end == '\n')
|
||||
+ && (*(boundary_end + 1) == '\0') ) )
|
||||
+ {
|
||||
+ if (*boundary_end == '\n') {
|
||||
+ msr->mpd->flag_lf_line = 1;
|
||||
+ } else {
|
||||
+ msr->mpd->flag_crlf_line = 1;
|
||||
+ }
|
||||
|
||||
- if (msr->mpd->is_complete != 0) {
|
||||
- msr->mpd->flag_error = 1;
|
||||
- *error_msg = apr_psprintf(msr->mp,
|
||||
- "Multipart: Invalid boundary (final duplicate).");
|
||||
- return -1;
|
||||
- }
|
||||
- }
|
||||
+ if (multipart_process_boundary(msr, (is_final ? 1 : 0), error_msg) < 0) {
|
||||
+ msr->mpd->flag_error = 1;
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
- /* Allow for CRLF and LF line endings. */
|
||||
- if ( ( (*boundary_end == '\r')
|
||||
- && (*(boundary_end + 1) == '\n')
|
||||
- && (*(boundary_end + 2) == '\0') )
|
||||
- || ( (*boundary_end == '\n')
|
||||
- && (*(boundary_end + 1) == '\0') ) )
|
||||
- {
|
||||
- if (*boundary_end == '\n') {
|
||||
- msr->mpd->flag_lf_line = 1;
|
||||
- } else {
|
||||
- msr->mpd->flag_crlf_line = 1;
|
||||
- }
|
||||
+ if (is_final) {
|
||||
+ msr->mpd->is_complete = 1;
|
||||
+ }
|
||||
|
||||
- if (multipart_process_boundary(msr, (is_final ? 1 : 0), error_msg) < 0) {
|
||||
+ processed_as_boundary = 1;
|
||||
+ msr->mpd->boundary_count++;
|
||||
+ }
|
||||
+ else {
|
||||
+ /* error */
|
||||
msr->mpd->flag_error = 1;
|
||||
+ *error_msg = apr_psprintf(msr->mp,
|
||||
+ "Multipart: Invalid boundary: %s",
|
||||
+ log_escape_nq(msr->mp, msr->mpd->buf));
|
||||
return -1;
|
||||
}
|
||||
-
|
||||
- if (is_final) {
|
||||
- msr->mpd->is_complete = 1;
|
||||
- }
|
||||
-
|
||||
- processed_as_boundary = 1;
|
||||
- msr->mpd->boundary_count++;
|
||||
- }
|
||||
- else {
|
||||
- /* error */
|
||||
- msr->mpd->flag_error = 1;
|
||||
- *error_msg = apr_psprintf(msr->mp,
|
||||
- "Multipart: Invalid boundary: %s",
|
||||
- log_escape_nq(msr->mp, msr->mpd->buf));
|
||||
- return -1;
|
||||
}
|
||||
} else { /* It looks like a boundary but we couldn't match it. */
|
||||
char *p = NULL;
|
||||
@@ -1221,6 +1272,21 @@ int multipart_process_chunk(modsec_rec *msr, const char *buf,
|
||||
msr->mpd->bufptr = msr->mpd->buf;
|
||||
msr->mpd->bufleft = MULTIPART_BUF_SIZE;
|
||||
msr->mpd->buf_contains_line = (c == 0x0a) ? 1 : 0;
|
||||
+
|
||||
+ if (c == 0x0a) {
|
||||
+ if (msr->mpd->crlf_state == 1) {
|
||||
+ msr->mpd->crlf_state = 3;
|
||||
+ } else {
|
||||
+ msr->mpd->crlf_state = 2;
|
||||
+ }
|
||||
+ }
|
||||
+ msr->mpd->crlf_state_buf_end = msr->mpd->crlf_state;
|
||||
+ }
|
||||
+
|
||||
+ if (c == 0x0d) {
|
||||
+ msr->mpd->crlf_state = 1;
|
||||
+ } else if (c != 0x0a) {
|
||||
+ msr->mpd->crlf_state = 0;
|
||||
}
|
||||
|
||||
if ((msr->mpd->is_complete) && (inleft != 0)) {
|
||||
diff --git a/apache2/msc_multipart.h b/apache2/msc_multipart.h
|
||||
index a0f6a08dd..13db0658f 100644
|
||||
--- a/apache2/msc_multipart.h
|
||||
+++ b/apache2/msc_multipart.h
|
||||
@@ -55,6 +55,8 @@ struct multipart_part {
|
||||
|
||||
char *last_header_name;
|
||||
apr_table_t *headers;
|
||||
+ char *last_header_line;
|
||||
+ apr_array_header_t *header_lines;
|
||||
|
||||
unsigned int offset;
|
||||
unsigned int length;
|
||||
@@ -81,6 +83,15 @@ struct multipart_data {
|
||||
char *bufptr;
|
||||
int bufleft;
|
||||
|
||||
+ /* line ending status seen immediately before current position.
|
||||
+ * 0 = neither LF nor CR; 1 = prev char CR; 2 = prev char LF alone;
|
||||
+ * 3 = prev two chars were CRLF
|
||||
+ */
|
||||
+ int crlf_state;
|
||||
+
|
||||
+ /* crlf_state at end of previous buffer */
|
||||
+ int crlf_state_buf_end;
|
||||
+
|
||||
unsigned int buf_offset;
|
||||
|
||||
/* pointer that keeps track of a part while
|
||||
@@ -94,6 +105,14 @@ struct multipart_data {
|
||||
*/
|
||||
int mpp_state;
|
||||
|
||||
+ /* part parsing substate; if mpp_state is 1 (collecting
|
||||
+ * data), then for this variable:
|
||||
+ * 0 means we have not yet read any data between the
|
||||
+ * post-headers blank line and the next boundary
|
||||
+ * 1 means we have read at some data after that blank line
|
||||
+ */
|
||||
+ int mpp_substate_part_data_read;
|
||||
+
|
||||
/* 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
|
||||
diff --git a/apache2/re_variables.c b/apache2/re_variables.c
|
||||
index 400738615..f3015acd9 100644
|
||||
--- a/apache2/re_variables.c
|
||||
+++ b/apache2/re_variables.c
|
||||
@@ -1394,6 +1394,52 @@ static int var_files_combined_size_generate(modsec_rec *msr, msre_var *var, msre
|
||||
return 1;
|
||||
}
|
||||
|
||||
+/* MULTIPART_PART_HEADERS */
|
||||
+
|
||||
+static int var_multipart_part_headers_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
|
||||
+ apr_table_t *vartab, apr_pool_t *mptmp)
|
||||
+{
|
||||
+ multipart_part **parts = NULL;
|
||||
+ int i, j, count = 0;
|
||||
+
|
||||
+ if (msr->mpd == NULL) return 0;
|
||||
+
|
||||
+ parts = (multipart_part **)msr->mpd->parts->elts;
|
||||
+ for(i = 0; i < msr->mpd->parts->nelts; i++) {
|
||||
+ int match = 0;
|
||||
+
|
||||
+ /* Figure out if we want to include this variable. */
|
||||
+ if (var->param == NULL) match = 1;
|
||||
+ else {
|
||||
+ if (var->param_data != NULL) { /* Regex. */
|
||||
+ char *my_error_msg = NULL;
|
||||
+ if (!(msc_regexec((msc_regex_t *)var->param_data, parts[i]->name,
|
||||
+ strlen(parts[i]->name), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1;
|
||||
+ } else { /* Simple comparison. */
|
||||
+ if (strcasecmp(parts[i]->name, var->param) == 0) match = 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If we had a match add this argument to the collection. */
|
||||
+ if (match) {
|
||||
+ for (j = 0; j < parts[i]->header_lines->nelts; j++) {
|
||||
+ char *header_line = ((char **)parts[i]->header_lines->elts)[j];
|
||||
+ msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var));
|
||||
+
|
||||
+ rvar->value = header_line;
|
||||
+ rvar->value_len = strlen(rvar->value);
|
||||
+ rvar->name = apr_psprintf(mptmp, "MULTIPART_PART_HEADERS:%s",
|
||||
+ log_escape_nq(mptmp, parts[i]->name));
|
||||
+ apr_table_addn(vartab, rvar->name, (void *)rvar);
|
||||
+
|
||||
+ count++;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
/* MODSEC_BUILD */
|
||||
|
||||
static int var_modsec_build_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
|
||||
@@ -2966,6 +3012,17 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
||||
PHASE_REQUEST_BODY
|
||||
);
|
||||
|
||||
+ /* MULTIPART_PART_HEADERS */
|
||||
+ msre_engine_variable_register(engine,
|
||||
+ "MULTIPART_PART_HEADERS",
|
||||
+ VAR_LIST,
|
||||
+ 0, 1,
|
||||
+ var_generic_list_validate,
|
||||
+ var_multipart_part_headers_generate,
|
||||
+ VAR_CACHE,
|
||||
+ PHASE_REQUEST_BODY
|
||||
+ );
|
||||
+
|
||||
/* GEO */
|
||||
msre_engine_variable_register(engine,
|
||||
"GEO",
|
||||
diff --git a/tests/regression/misc/00-multipart-parser.t b/tests/regression/misc/00-multipart-parser.t
|
||||
index 3c1f41b7d..e5ee4c13c 100644
|
||||
--- a/tests/regression/misc/00-multipart-parser.t
|
||||
+++ b/tests/regression/misc/00-multipart-parser.t
|
||||
@@ -1849,3 +1849,48 @@
|
||||
),
|
||||
},
|
||||
|
||||
+# part headers
|
||||
+{
|
||||
+ type => "misc",
|
||||
+ comment => "multipart parser (part headers)",
|
||||
+ conf => qq(
|
||||
+ SecRuleEngine On
|
||||
+ SecDebugLog $ENV{DEBUG_LOG}
|
||||
+ SecDebugLogLevel 9
|
||||
+ SecRequestBodyAccess On
|
||||
+ SecRule MULTIPART_STRICT_ERROR "\@eq 1" "phase:2,deny,status:400,id:500168"
|
||||
+ SecRule REQBODY_PROCESSOR_ERROR "\@eq 1" "phase:2,deny,status:400,id:500169"
|
||||
+ SecRule MULTIPART_PART_HEADERS:image "\@rx content-type:.*jpeg" "phase:2,deny,status:403,id:500170,t:lowercase"
|
||||
+ ),
|
||||
+ match_log => {
|
||||
+ debug => [ qr/500170.*against MULTIPART_PART_HEADERS:image.*Rule returned 1./s, 1 ],
|
||||
+ },
|
||||
+ match_response => {
|
||||
+ status => qr/^403$/,
|
||||
+ },
|
||||
+ request => new HTTP::Request(
|
||||
+ POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||
+ [
|
||||
+ "Content-Type" => q(multipart/form-data; boundary=0000),
|
||||
+ ],
|
||||
+ normalize_raw_request_data(
|
||||
+ q(
|
||||
+ --0000
|
||||
+ Content-Disposition: form-data; name="username"
|
||||
+
|
||||
+ Bill
|
||||
+ --0000
|
||||
+ Content-Disposition: form-data; name="email"
|
||||
+
|
||||
+ bill@fakesite.com
|
||||
+ --0000
|
||||
+ Content-Disposition: form-data; name="image"; filename="image.jpg"
|
||||
+ Content-Type: image/jpeg
|
||||
+
|
||||
+ BINARYDATA
|
||||
+ --0000--
|
||||
+ ),
|
||||
+ ),
|
||||
+ ),
|
||||
+},
|
||||
+
|
||||
36
README.en.md
36
README.en.md
@ -1,36 +0,0 @@
|
||||
# mod_security
|
||||
|
||||
#### Description
|
||||
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
|
||||
|
||||
#### Gitee Feature
|
||||
|
||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
39
README.md
39
README.md
@ -1,39 +0,0 @@
|
||||
# mod_security
|
||||
|
||||
#### 介绍
|
||||
{**以下是码云平台说明,您可以替换此简介**
|
||||
码云是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
|
||||
无论是个人、团队、或是企业,都能够用码云实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
|
||||
|
||||
#### 软件架构
|
||||
软件架构说明
|
||||
|
||||
|
||||
#### 安装教程
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 使用说明
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
|
||||
|
||||
#### 码云特技
|
||||
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||
2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目
|
||||
4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目
|
||||
5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||
6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
226
mod_security.conf
Normal file
226
mod_security.conf
Normal file
@ -0,0 +1,226 @@
|
||||
# -- Rule engine initialization ----------------------------------------------
|
||||
|
||||
# Enable ModSecurity, attaching it to every transaction. Use detection
|
||||
# only to start with, because that minimises the chances of post-installation
|
||||
# disruption.
|
||||
#
|
||||
SecRuleEngine DetectionOnly
|
||||
|
||||
|
||||
# -- Request body handling ---------------------------------------------------
|
||||
|
||||
# Allow ModSecurity to access request bodies. If you don't, ModSecurity
|
||||
# won't be able to see any POST parameters, which opens a large security
|
||||
# hole for attackers to exploit.
|
||||
#
|
||||
SecRequestBodyAccess On
|
||||
|
||||
|
||||
# Enable XML request body parser.
|
||||
# Initiate XML Processor in case of xml content-type
|
||||
#
|
||||
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
|
||||
"id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
|
||||
|
||||
# Enable JSON request body parser.
|
||||
# Initiate JSON Processor in case of JSON content-type; change accordingly
|
||||
# if your application does not use 'application/json'
|
||||
#
|
||||
SecRule REQUEST_HEADERS:Content-Type "application/json" \
|
||||
"id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
|
||||
|
||||
# Maximum request body size we will accept for buffering. If you support
|
||||
# file uploads then the value given on the first line has to be as large
|
||||
# as the largest file you are willing to accept. The second value refers
|
||||
# to the size of data, with files excluded. You want to keep that value as
|
||||
# low as practical.
|
||||
#
|
||||
SecRequestBodyLimit 13107200
|
||||
SecRequestBodyNoFilesLimit 131072
|
||||
|
||||
# Store up to 128 KB of request body data in memory. When the multipart
|
||||
# parser reachers this limit, it will start using your hard disk for
|
||||
# storage. That is slow, but unavoidable.
|
||||
#
|
||||
SecRequestBodyInMemoryLimit 131072
|
||||
|
||||
# What do do if the request body size is above our configured limit.
|
||||
# Keep in mind that this setting will automatically be set to ProcessPartial
|
||||
# when SecRuleEngine is set to DetectionOnly mode in order to minimize
|
||||
# disruptions when initially deploying ModSecurity.
|
||||
#
|
||||
SecRequestBodyLimitAction Reject
|
||||
|
||||
# Verify that we've correctly processed the request body.
|
||||
# As a rule of thumb, when failing to process a request body
|
||||
# you should reject the request (when deployed in blocking mode)
|
||||
# or log a high-severity alert (when deployed in detection-only mode).
|
||||
#
|
||||
SecRule REQBODY_ERROR "!@eq 0" \
|
||||
"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
|
||||
|
||||
# By default be strict with what we accept in the multipart/form-data
|
||||
# request body. If the rule below proves to be too strict for your
|
||||
# environment consider changing it to detection-only. You are encouraged
|
||||
# _not_ to remove it altogether.
|
||||
#
|
||||
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
|
||||
"id:'200003',phase:2,t:none,log,deny,status:400, \
|
||||
msg:'Multipart request body failed strict validation: \
|
||||
PE %{REQBODY_PROCESSOR_ERROR}, \
|
||||
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
|
||||
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
|
||||
DB %{MULTIPART_DATA_BEFORE}, \
|
||||
DA %{MULTIPART_DATA_AFTER}, \
|
||||
HF %{MULTIPART_HEADER_FOLDING}, \
|
||||
LF %{MULTIPART_LF_LINE}, \
|
||||
SM %{MULTIPART_MISSING_SEMICOLON}, \
|
||||
IQ %{MULTIPART_INVALID_QUOTING}, \
|
||||
IP %{MULTIPART_INVALID_PART}, \
|
||||
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
|
||||
FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
|
||||
|
||||
# Did we see anything that might be a boundary?
|
||||
#
|
||||
SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \
|
||||
"id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
|
||||
|
||||
# PCRE Tuning
|
||||
# We want to avoid a potential RegEx DoS condition
|
||||
#
|
||||
SecPcreMatchLimit 1000
|
||||
SecPcreMatchLimitRecursion 1000
|
||||
|
||||
# Some internal errors will set flags in TX and we will need to look for these.
|
||||
# All of these are prefixed with "MSC_". The following flags currently exist:
|
||||
#
|
||||
# MSC_PCRE_LIMITS_EXCEEDED: PCRE match limits were exceeded.
|
||||
#
|
||||
SecRule TX:/^MSC_/ "!@streq 0" \
|
||||
"id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"
|
||||
|
||||
|
||||
# -- Response body handling --------------------------------------------------
|
||||
|
||||
# Allow ModSecurity to access response bodies.
|
||||
# You should have this directive enabled in order to identify errors
|
||||
# and data leakage issues.
|
||||
#
|
||||
# Do keep in mind that enabling this directive does increases both
|
||||
# memory consumption and response latency.
|
||||
#
|
||||
SecResponseBodyAccess On
|
||||
|
||||
# Which response MIME types do you want to inspect? You should adjust the
|
||||
# configuration below to catch documents but avoid static files
|
||||
# (e.g., images and archives).
|
||||
#
|
||||
SecResponseBodyMimeType text/plain text/html text/xml
|
||||
|
||||
# Buffer response bodies of up to 512 KB in length.
|
||||
SecResponseBodyLimit 524288
|
||||
|
||||
# What happens when we encounter a response body larger than the configured
|
||||
# limit? By default, we process what we have and let the rest through.
|
||||
# That's somewhat less secure, but does not break any legitimate pages.
|
||||
#
|
||||
SecResponseBodyLimitAction ProcessPartial
|
||||
|
||||
|
||||
# -- Filesystem configuration ------------------------------------------------
|
||||
|
||||
# The location where ModSecurity stores temporary files (for example, when
|
||||
# it needs to handle a file upload that is larger than the configured limit).
|
||||
#
|
||||
# This default setting is chosen due to all systems have /tmp available however,
|
||||
# this is less than ideal. It is recommended that you specify a location that's private.
|
||||
#
|
||||
SecTmpDir /tmp/
|
||||
|
||||
# The location where ModSecurity will keep its persistent data. This default setting
|
||||
# is chosen due to all systems have /tmp available however, it
|
||||
# too should be updated to a place that other users can't access.
|
||||
#
|
||||
SecDataDir /tmp/
|
||||
|
||||
|
||||
# -- File uploads handling configuration -------------------------------------
|
||||
|
||||
# The location where ModSecurity stores intercepted uploaded files. This
|
||||
# location must be private to ModSecurity. You don't want other users on
|
||||
# the server to access the files, do you?
|
||||
#
|
||||
#SecUploadDir /opt/modsecurity/var/upload/
|
||||
|
||||
# By default, only keep the files that were determined to be unusual
|
||||
# in some way (by an external inspection script). For this to work you
|
||||
# will also need at least one file inspection rule.
|
||||
#
|
||||
#SecUploadKeepFiles RelevantOnly
|
||||
|
||||
# Uploaded files are by default created with permissions that do not allow
|
||||
# any other user to access them. You may need to relax that if you want to
|
||||
# interface ModSecurity to an external program (e.g., an anti-virus).
|
||||
#
|
||||
#SecUploadFileMode 0600
|
||||
|
||||
|
||||
# -- Debug log configuration -------------------------------------------------
|
||||
|
||||
# The default debug log configuration is to duplicate the error, warning
|
||||
# and notice messages from the error log.
|
||||
#
|
||||
#SecDebugLog /opt/modsecurity/var/log/debug.log
|
||||
#SecDebugLogLevel 3
|
||||
|
||||
|
||||
# -- Audit log configuration -------------------------------------------------
|
||||
|
||||
# Log the transactions that are marked by a rule, as well as those that
|
||||
# trigger a server error (determined by a 5xx or 4xx, excluding 404,
|
||||
# level response status codes).
|
||||
#
|
||||
SecAuditEngine RelevantOnly
|
||||
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
|
||||
|
||||
# Log everything we know about a transaction.
|
||||
SecAuditLogParts ABIJDEFHZ
|
||||
|
||||
# Use a single file for logging. This is much easier to look at, but
|
||||
# assumes that you will use the audit log only ocassionally.
|
||||
#
|
||||
SecAuditLogType Serial
|
||||
SecAuditLog /var/log/modsec_audit.log
|
||||
|
||||
# Specify the path for concurrent audit logging.
|
||||
#SecAuditLogStorageDir /opt/modsecurity/var/audit/
|
||||
|
||||
|
||||
# -- Miscellaneous -----------------------------------------------------------
|
||||
|
||||
# Use the most commonly used application/x-www-form-urlencoded parameter
|
||||
# separator. There's probably only one application somewhere that uses
|
||||
# something else so don't expect to change this value.
|
||||
#
|
||||
SecArgumentSeparator &
|
||||
|
||||
# Settle on version 0 (zero) cookies, as that is what most applications
|
||||
# use. Using an incorrect cookie version may open your installation to
|
||||
# evasion attacks (against the rules that examine named cookies).
|
||||
#
|
||||
SecCookieFormat 0
|
||||
|
||||
# Specify your Unicode Code Point.
|
||||
# This mapping is used by the t:urlDecodeUni transformation function
|
||||
# to properly map encoded data to your language. Properly setting
|
||||
# these directives helps to reduce false positives and negatives.
|
||||
#
|
||||
#SecUnicodeMapFile unicode.mapping 20127
|
||||
|
||||
# Improve the quality of ModSecurity by sharing information about your
|
||||
# current ModSecurity version and dependencies versions.
|
||||
# The following information will be shared: ModSecurity version,
|
||||
# Web Server version, APR version, PCRE version, Lua version, Libxml2
|
||||
# version, Anonymous unique id for host.
|
||||
SecStatusEngine On
|
||||
|
||||
116
mod_security.spec
Normal file
116
mod_security.spec
Normal file
@ -0,0 +1,116 @@
|
||||
%{!?_httpd_apxs: %{expand: %%global _httpd_apxs %%{_sbindir}/apxs}}
|
||||
%{!?_httpd_mmn: %{expand: %%global _httpd_mmn %%(cat %{_includedir}/httpd/.mmn || echo 0-0)}}
|
||||
%{!?_httpd_modconfdir: %{expand: %%global _httpd_modconfdir %%{_sysconfdir}/httpd/conf.d}}
|
||||
%{!?_httpd_confdir: %{expand: %%global _httpd_confdir %%{_sysconfdir}/httpd/conf.d}}
|
||||
%{!?_httpd_moddir: %{expand: %%global _httpd_moddir %%{_libdir}/httpd/modules}}
|
||||
%global mod_audit_log_collector 0
|
||||
|
||||
Name: mod_security
|
||||
Version: 2.9.5
|
||||
Release: 3
|
||||
Summary: Security module for the Apache HTTP Server
|
||||
License: ASL 2.0
|
||||
URL: http://www.modsecurity.org/
|
||||
Source: https://github.com/SpiderLabs/ModSecurity/releases/download/v%{version}/modsecurity-%{version}.tar.gz
|
||||
Source1: mod_security.conf
|
||||
Source2: 10-mod_security.conf
|
||||
Source3: modsecurity_localrules.conf
|
||||
# https://github.com/SpiderLabs/ModSecurity/commit/51a30d7b406af95c4143560d9753cf0b6d2151f5
|
||||
Patch0: CVE-2022-48279.patch
|
||||
|
||||
Requires: httpd httpd-mmn = %{_httpd_mmn}
|
||||
BuildRequires: gcc make perl-generators httpd-devel yajl yajl-devel
|
||||
BuildRequires: pkgconfig(lua) pkgconfig(libcurl) pkgconfig(libxml-2.0) pkgconfig(libpcre)
|
||||
|
||||
%description
|
||||
This software is also called Modsec,it is an open-source web application firewall.
|
||||
It is designed for Apache HTTP Server.ModSecurity is commonly deployed to provide
|
||||
protections against generic classed of vulnerabilities.The install of this package
|
||||
is easy and you can read the README.TXT for more information.
|
||||
|
||||
%if %mod_audit_log_collector
|
||||
%package -n mlogc
|
||||
Summary: Collect mod_security audit log
|
||||
Requires: mod_security
|
||||
|
||||
%description -n mlogc
|
||||
This package collects mod_security audit log.
|
||||
%endif
|
||||
|
||||
%prep
|
||||
%autosetup -p1 -n modsecurity-%{version}
|
||||
|
||||
%build
|
||||
%configure --with-yajl --with-apxs=%{_httpd_apxs} --enable-pcre-match-limit-recursion=1000000 --enable-pcre-match-limit=1000000
|
||||
sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool
|
||||
sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
|
||||
make %{_smp_mflags}
|
||||
|
||||
%install
|
||||
install -d %{buildroot}%{_bindir}
|
||||
install -d %{buildroot}%{_sbindir}
|
||||
install -d %{buildroot}%{_httpd_moddir}
|
||||
install -m0755 apache2/.libs/mod_security2.so %{buildroot}%{_httpd_moddir}/mod_security2.so
|
||||
install -d %{buildroot}%{_sysconfdir}/httpd/modsecurity.d/
|
||||
install -d %{buildroot}%{_sysconfdir}/httpd/modsecurity.d/local_rules
|
||||
install -d %{buildroot}%{_sysconfdir}/httpd/modsecurity.d/activated_rules
|
||||
install -m 700 -d $RPM_BUILD_ROOT%{_localstatedir}/lib/%{name}
|
||||
install -Dp -m0644 %{SOURCE3} %{buildroot}%{_sysconfdir}/httpd/modsecurity.d/local_rules/
|
||||
%if "%{_httpd_modconfdir}" != "%{_httpd_confdir}"
|
||||
install -Dp -m0644 %{SOURCE1} %{buildroot}%{_httpd_confdir}/mod_security.conf
|
||||
sed -i 's/Include/IncludeOptional/' %{buildroot}%{_httpd_confdir}/mod_security.conf
|
||||
install -Dp -m0644 %{SOURCE2} %{buildroot}%{_httpd_modconfdir}/10-mod_security.conf
|
||||
%else
|
||||
install -d -m0755 %{buildroot}%{_httpd_confdir}
|
||||
cat %{SOURCE2} %{SOURCE1} > %{buildroot}%{_httpd_confdir}/mod_security.conf
|
||||
%endif
|
||||
|
||||
%if %mod_audit_log_collector
|
||||
install -d %{buildroot}%{_localstatedir}/log/mlogc
|
||||
install -d %{buildroot}%{_localstatedir}/log/mlogc/data
|
||||
install -m0644 mlogc/mlogc-default.conf %{buildroot}%{_sysconfdir}/mlogc.conf
|
||||
install -m0755 mlogc/mlogc %{buildroot}%{_bindir}/mlogc
|
||||
install -m0755 mlogc/mlogc-batch-load.pl %{buildroot}%{_bindir}/mlogc-batch-load
|
||||
%endif
|
||||
|
||||
%files
|
||||
%doc README.* NOTICE LICENSE CHANGES
|
||||
%{_httpd_moddir}/mod_security2.so
|
||||
%config(noreplace) %{_httpd_confdir}/*.conf
|
||||
%if "%{_httpd_modconfdir}" != "%{_httpd_confdir}"
|
||||
%config(noreplace) %{_httpd_modconfdir}/*.conf
|
||||
%endif
|
||||
%dir %{_sysconfdir}/httpd/modsecurity.d
|
||||
%dir %{_sysconfdir}/httpd/modsecurity.d/local_rules
|
||||
%dir %{_sysconfdir}/httpd/modsecurity.d/activated_rules
|
||||
%attr(770,apache,root) %dir %{_localstatedir}/lib/%{name}
|
||||
%config(noreplace) %{_sysconfdir}/httpd/modsecurity.d/local_rules/*.conf
|
||||
|
||||
%if %mod_audit_log_collector
|
||||
%files -n mlogc
|
||||
%doc mlogc/INSTALL
|
||||
%attr(0755,root,root) %dir %{_localstatedir}/log/mlogc
|
||||
%attr(0770,root,apache) %dir %{_localstatedir}/log/mlogc/data
|
||||
%attr(0640,root,apache) %config(noreplace) %{_sysconfdir}/mlogc.conf
|
||||
%attr(0755,root,root) %{_bindir}/mlogc-batch-load
|
||||
%attr(0755,root,root) %{_bindir}/mlogc
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Mon May 06 2024 yaoxin <yao_xin001@hoperun.com> - 2.9.5-3
|
||||
- Fix HTTP service startup failure
|
||||
|
||||
* Tue Mar 26 2024 yaoxin <yao_xin001@hoperun.com> - 2.9.5-2
|
||||
- Fix CVE-2022-48279
|
||||
|
||||
* Tue Dec 14 2021 yaoxin <yaoxin30@huawei.com> - 2.9.5-1
|
||||
- Upgrade mod_security to 2.9.5 for fix CVE-2021-42717
|
||||
|
||||
* Mon May 18 2020 wangchen <wangchen137@huawei.com> - 2.9.2-8
|
||||
- rebuild for mod_security
|
||||
|
||||
* Wed Nov 20 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.9.2-7
|
||||
- Type:enhancement
|
||||
- Id:NA
|
||||
- SUG:NA
|
||||
- DESC:modify the spec
|
||||
BIN
modsecurity-2.9.5.tar.gz
Normal file
BIN
modsecurity-2.9.5.tar.gz
Normal file
Binary file not shown.
7
modsecurity_localrules.conf
Normal file
7
modsecurity_localrules.conf
Normal file
@ -0,0 +1,7 @@
|
||||
# You can use this file/directory to drop your local rules or
|
||||
# to remove some rules provided by mod_security_crs package with SecRuleRemoveById
|
||||
#
|
||||
# You can also disable mod_security for some incompatible web applications (eg. phpMyAdmin).
|
||||
#
|
||||
#
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user