Skip to content

Commit ca7b4b4

Browse files
author
Marc Stern
committed
Merge branch 'v2/master' of https://github.com/marcstern/ModSecurity into v2/master
2 parents c5a6d6b + d9016e2 commit ca7b4b4

37 files changed

+3371
-2169
lines changed

.github/security2.conf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
LoadModule security2_module /usr/lib/apache2/modules/mod_security2.so
2+
3+
<IfModule security2_module>
4+
SecDataDir /var/cache/modsecurity
5+
Include /etc/apache2/modsecurity.conf
6+
</IfModule>

.github/workflows/ci.yml

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,42 @@ jobs:
1010
strategy:
1111
matrix:
1212
os: [ubuntu-22.04]
13-
platform: [x64]
14-
compiler: [gcc]
13+
platform: [x32, x64]
14+
compiler: [gcc, clang]
1515
configure:
16-
- {label: "with pcre2", opt: "--with-pcre2" }
17-
- {label: "with lua", opt: "--with-lua" }
18-
- {label: "wo lua", opt: "--without-lua" }
16+
- {label: "with pcre, no study, no jit", opt: "--enable-pcre-study=no" }
17+
- {label: "with pcre, with study, no jit", opt: "--enable-pcre-study=yes" }
18+
- {label: "with pcre, no study, with jit", opt: "--enable-pcre-study=no --enable-pcre-jit" }
19+
- {label: "with pcre, with study, with jit", opt: "--enable-pcre-study=yes --enable-pcre-jit" }
20+
- {label: "with pcre2", opt: "--with-pcre2 --enable-pcre-study=no" }
21+
- {label: "with pcre2, with study, no jit", opt: "--with-pcre2 --enable-pcre-study=yes" }
22+
- {label: "with pcre2, no study, with jit", opt: "--with-pcre2 --enable-pcre-study=no --enable-pcre-jit" }
23+
- {label: "with pcre2, with study, with jit", opt: "--with-pcre2 --enable-pcre-study=yes --enable-pcre-jit" }
24+
- {label: "with lua", opt: "--with-lua" }
25+
- {label: "wo lua", opt: "--without-lua" }
1926
steps:
2027
- name: Setup Dependencies
2128
run: |
2229
sudo apt-get update -y -qq
23-
sudo apt-get install -y apache2-dev libxml2-dev liblua5.1-0-dev libcurl4-gnutls-dev libpcre2-dev pkg-config libyajl-dev
30+
sudo apt-get install -y apache2-dev libxml2-dev liblua5.1-0-dev libcurl4-gnutls-dev libpcre2-dev pkg-config libyajl-dev apache2 apache2-bin apache2-data
2431
- uses: actions/checkout@v2
2532
- name: autogen.sh
2633
run: ./autogen.sh
2734
- name: configure ${{ matrix.configure.label }}
28-
run: ./configure ${{ matrix.configure.opt }}
35+
run: ./configure --enable-assertions ${{ matrix.configure.opt }}
2936
- uses: ammaraskar/gcc-problem-matcher@master
3037
- name: make
3138
run: make -j `nproc`
39+
- name: install module
40+
run: sudo make install
41+
- name: prepare config
42+
run: |
43+
sudo cp .github/security2.conf /etc/apache2/mods-enabled/
44+
sudo cp modsecurity.conf-recommended /etc/apache2/modsecurity.conf
45+
sudo cp unicode.mapping /etc/apache2/
46+
sudo mkdir -p /var/cache/modsecurity
47+
sudo chown -R www-data:www-data /var/cache/modsecurity
48+
- name: start apache with module
49+
run: |
50+
sudo systemctl restart apache2.service
51+

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
DD mmm YYYY - 2.9.x (to be released)
22
-------------------
33

4+
* Fix possible segfault in collection_unpack
5+
[Issue #3072 - @twouters]
46
* Set the minimum security protocol version for SecRemoteRules
57
[Issue security/code-scanning/2 - @airween]
68
* Allow lua version 5.4

apache2/apache2_config.c

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@
3030
APLOG_USE_MODULE(security2);
3131
#endif
3232

33+
// Returns the rule id if existing, otherwise the file name & line number
34+
const char* id_log(msre_rule* rule) {
35+
assert(rule != NULL);
36+
assert(rule->actionset != NULL);
37+
const char* id = rule->actionset->id;
38+
if (!id || !*id || id == NOT_SET_P) id = apr_psprintf(rule->ruleset->mp, "%s (%d)", rule->filename, rule->line_num);
39+
return id;
40+
}
41+
3342
/* -- Directory context creation and initialisation -- */
3443

3544
/**
@@ -239,19 +248,19 @@ static void copy_rules_phase(apr_pool_t *mp,
239248

240249
if (copy > 0) {
241250
#ifdef DEBUG_CONF
242-
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, mp, "Copy rule %pp [id \"%s\"]", rule, rule->actionset->id);
251+
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, mp, "Copy rule %pp [id \"%s\"]", rule, id_log(rule));
243252
#endif
244253

245254
/* Copy the rule. */
246255
*(msre_rule **)apr_array_push(child_phase_arr) = rule;
247-
if (rule->actionset && rule->actionset->is_chained) mode = 2;
256+
if (rule->actionset->is_chained) mode = 2;
248257
} else {
249-
if (rule->actionset && rule->actionset->is_chained) mode = 1;
258+
if (rule->actionset->is_chained) mode = 1;
250259
}
251260
} else {
252261
if (mode == 2) {
253262
#ifdef DEBUG_CONF
254-
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, mp, "Copy chain %pp for rule %pp [id \"%s\"]", rule, rule->chain_starter, rule->chain_starter->actionset->id);
263+
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, mp, "Copy chain %pp for rule %pp [id \"%s\"]", rule, rule->chain_starter, id_log(rule->chain_starter));
255264
#endif
256265

257266
/* Copy the rule (it belongs to the chain we want to include. */
@@ -906,16 +915,14 @@ static const char *add_rule(cmd_parms *cmd, directory_config *dcfg, int type,
906915
*/
907916
rule->actionset = msre_actionset_merge(modsecurity->msre, cmd->pool, dcfg->tmp_default_actionset,
908917
rule->actionset, 1);
918+
if (rule->actionset == NULL) return apr_psprintf(cmd->pool, "ModSecurity: cannot merge actionset (memory full?).");
909919

910920
/* Keep track of the parent action for "block" */
911-
if (rule->actionset) {
912-
rule->actionset->parent_intercept_action_rec = dcfg->tmp_default_actionset->intercept_action_rec;
913-
rule->actionset->parent_intercept_action = dcfg->tmp_default_actionset->intercept_action;
914-
}
921+
rule->actionset->parent_intercept_action_rec = dcfg->tmp_default_actionset->intercept_action_rec;
922+
rule->actionset->parent_intercept_action = dcfg->tmp_default_actionset->intercept_action;
915923

916924
/* Must NOT specify a disruptive action in logging phase. */
917-
if ((rule->actionset != NULL)
918-
&& (rule->actionset->phase == PHASE_LOGGING)
925+
if ( (rule->actionset->phase == PHASE_LOGGING)
919926
&& (rule->actionset->intercept_action != ACTION_ALLOW)
920927
&& (rule->actionset->intercept_action != ACTION_ALLOW_REQUEST)
921928
&& (rule->actionset->intercept_action != ACTION_NONE)
@@ -926,9 +933,7 @@ static const char *add_rule(cmd_parms *cmd, directory_config *dcfg, int type,
926933

927934
if (dcfg->tmp_chain_starter != NULL) {
928935
rule->chain_starter = dcfg->tmp_chain_starter;
929-
if (rule->actionset) {
930-
rule->actionset->phase = rule->chain_starter->actionset->phase;
931-
}
936+
rule->actionset->phase = rule->chain_starter->actionset->phase;
932937
}
933938

934939
if (rule->actionset->is_chained != 1) {
@@ -967,8 +972,7 @@ static const char *add_rule(cmd_parms *cmd, directory_config *dcfg, int type,
967972

968973
#ifdef DEBUG_CONF
969974
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, cmd->pool,
970-
"Adding rule %pp phase=%d id=\"%s\".", rule, rule->actionset->phase, (rule->actionset->id == NOT_SET_P
971-
? "(none)" : rule->actionset->id));
975+
"Adding rule %pp phase=%d id=\"%s\".", rule, rule->actionset->phase, id_log(rule));
972976
#endif
973977

974978
/* Add rule to the recipe. */
@@ -1042,8 +1046,7 @@ static const char *add_marker(cmd_parms *cmd, directory_config *dcfg,
10421046
for (p = PHASE_FIRST; p <= PHASE_LAST; p++) {
10431047
#ifdef DEBUG_CONF
10441048
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, cmd->pool,
1045-
"Adding marker %pp phase=%d id=\"%s\".", rule, p, (rule->actionset->id == NOT_SET_P
1046-
? "(none)" : rule->actionset->id));
1049+
"Adding marker %pp phase=%d id=\"%s\".", rule, p, id_log(rule));
10471050
#endif
10481051

10491052
if (msre_ruleset_rule_add(dcfg->ruleset, rule, p) < 0) {
@@ -1091,11 +1094,7 @@ static const char *update_rule_action(cmd_parms *cmd, directory_config *dcfg,
10911094
return NULL;
10921095
}
10931096

1094-
/* Check the rule actionset */
1095-
/* ENH: Can this happen? */
1096-
if (rule->actionset == NULL) {
1097-
return apr_psprintf(cmd->pool, "ModSecurity: Attempt to update action for rule \"%s\" failed: Rule does not have an actionset.", p1);
1098-
}
1097+
assert(rule->actionset != NULL);
10991098

11001099
/* Create a new actionset */
11011100
new_actionset = msre_actionset_create(modsecurity->msre, cmd->pool, p2, &my_error_msg);
@@ -1117,16 +1116,15 @@ static const char *update_rule_action(cmd_parms *cmd, directory_config *dcfg,
11171116
char *actions = msre_actionset_generate_action_string(ruleset->mp, rule->actionset);
11181117
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, cmd->pool,
11191118
"Update rule %pp id=\"%s\" old action: \"%s\"",
1120-
rule,
1121-
(rule->actionset->id == NOT_SET_P ? "(none)" : rule->actionset->id),
1122-
actions);
1119+
rule, id_log(rule), actions);
11231120
}
11241121
#endif
11251122

11261123
/* Merge new actions with the rule */
11271124
/* ENH: Will this leak the old actionset? */
11281125
rule->actionset = msre_actionset_merge(modsecurity->msre, cmd->pool, rule->actionset,
11291126
new_actionset, 1);
1127+
if (rule->actionset == NULL) return apr_psprintf(cmd->pool, "ModSecurity: cannot merge actionset (memory full?).");
11301128
msre_actionset_set_defaults(rule->actionset);
11311129

11321130
/* Update the unparsed rule */
@@ -1137,9 +1135,7 @@ static const char *update_rule_action(cmd_parms *cmd, directory_config *dcfg,
11371135
char *actions = msre_actionset_generate_action_string(ruleset->mp, rule->actionset);
11381136
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, cmd->pool,
11391137
"Update rule %pp id=\"%s\" new action: \"%s\"",
1140-
rule,
1141-
(rule->actionset->id == NOT_SET_P ? "(none)" : rule->actionset->id),
1142-
actions);
1138+
rule, id_log(rule), actions);
11431139
}
11441140
#endif
11451141

@@ -1746,6 +1742,9 @@ char *parser_conn_limits_operator(apr_pool_t *mp, const char *p2,
17461742

17471743
config_orig_path = apr_pstrndup(mp, filename,
17481744
strlen(filename) - strlen(apr_filepath_name_get(filename)));
1745+
if (config_orig_path == NULL) {
1746+
return apr_psprintf(mp, "ModSecurity: failed to duplicate filename in parser_conn_limits_operator");
1747+
}
17491748

17501749
apr_filepath_merge(&file, config_orig_path, param, APR_FILEPATH_TRUENAME,
17511750
mp);
@@ -2452,8 +2451,12 @@ static const char *cmd_rule_remove_by_id(cmd_parms *cmd, void *_dcfg,
24522451
const char *p1)
24532452
{
24542453
directory_config *dcfg = (directory_config *)_dcfg;
2455-
rule_exception *re = apr_pcalloc(cmd->pool, sizeof(rule_exception));
24562454
if (dcfg == NULL) return NULL;
2455+
rule_exception* re = apr_pcalloc(cmd->pool, sizeof(rule_exception));
2456+
if (re == NULL) {
2457+
ap_log_perror(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, cmd->pool, "cmd_rule_remove_by_id: Cannot allocate memory");
2458+
return NULL;
2459+
}
24572460

24582461
re->type = RULE_EXCEPTION_REMOVE_ID;
24592462
re->param = p1;

apache2/apache2_io.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,13 @@ apr_status_t input_filter(ap_filter_t *f, apr_bucket_brigade *bb_out,
179179
* Reads request body from a client.
180180
*/
181181
apr_status_t read_request_body(modsec_rec *msr, char **error_msg) {
182+
assert(msr != NULL);
183+
assert(error_msg!= NULL);
182184
request_rec *r = msr->r;
183185
unsigned int finished_reading;
184186
apr_bucket_brigade *bb_in;
185187
apr_bucket *bucket;
186188

187-
if (error_msg == NULL) return -1;
188189
*error_msg = NULL;
189190

190191
if (msr->reqbody_should_exist != 1) {
@@ -368,6 +369,8 @@ apr_status_t read_request_body(modsec_rec *msr, char **error_msg) {
368369
* run or not.
369370
*/
370371
static int output_filter_should_run(modsec_rec *msr, request_rec *r) {
372+
assert(msr != NULL);
373+
assert(r != NULL);
371374
char *content_type = NULL;
372375

373376
/* Check configuration. */
@@ -429,10 +432,13 @@ static int output_filter_should_run(modsec_rec *msr, request_rec *r) {
429432
static apr_status_t output_filter_init(modsec_rec *msr, ap_filter_t *f,
430433
apr_bucket_brigade *bb_in)
431434
{
435+
assert(msr != NULL);
436+
assert(f != NULL);
432437
request_rec *r = f->r;
433438
const char *s_content_length = NULL;
434439
apr_status_t rc;
435440

441+
assert(msr != NULL);
436442
msr->of_brigade = apr_brigade_create(msr->mp, f->c->bucket_alloc);
437443
if (msr->of_brigade == NULL) {
438444
msr_log(msr, 1, "Output filter: Failed to create brigade.");
@@ -496,6 +502,8 @@ static apr_status_t output_filter_init(modsec_rec *msr, ap_filter_t *f,
496502
* and to the client.
497503
*/
498504
static apr_status_t send_of_brigade(modsec_rec *msr, ap_filter_t *f) {
505+
assert(msr != NULL);
506+
assert(f != NULL);
499507
apr_status_t rc;
500508

501509
rc = ap_pass_brigade(f->next, msr->of_brigade);
@@ -537,6 +545,8 @@ static apr_status_t send_of_brigade(modsec_rec *msr, ap_filter_t *f) {
537545
*
538546
*/
539547
static void inject_content_to_of_brigade(modsec_rec *msr, ap_filter_t *f) {
548+
assert(msr != NULL);
549+
assert(f != NULL);
540550
apr_bucket *b;
541551

542552
if (msr->txcfg->content_injection_enabled && msr->stream_output_data != NULL) {
@@ -563,6 +573,8 @@ static void inject_content_to_of_brigade(modsec_rec *msr, ap_filter_t *f) {
563573
*
564574
*/
565575
static void prepend_content_to_of_brigade(modsec_rec *msr, ap_filter_t *f) {
576+
assert(msr != NULL);
577+
assert(f != NULL);
566578
if ((msr->txcfg->content_injection_enabled) && (msr->content_prepend) && (!msr->of_skipping)) {
567579
apr_bucket *bucket_ci = NULL;
568580

@@ -1008,6 +1020,12 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
10081020
/* Now send data down the filter stream
10091021
* (full-buffering only).
10101022
*/
1023+
if (!eos_bucket) {
1024+
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, f->r->server,
1025+
"ModSecurity: Internal Error: eos_bucket is NULL.");
1026+
return APR_EGENERAL;
1027+
}
1028+
10111029
if ((msr->of_skipping == 0)&&(!msr->of_partial)) {
10121030
if(msr->of_stream_changed == 1) {
10131031
inject_content_to_of_brigade(msr,f);

apache2/apache2_util.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
* Sends a brigade with an error bucket down the filter chain.
2626
*/
2727
apr_status_t send_error_bucket(modsec_rec *msr, ap_filter_t *f, int status) {
28+
assert(msr != NULL);
29+
assert(f != NULL);
2830
apr_bucket_brigade *brigade = NULL;
2931
apr_bucket *bucket = NULL;
3032

@@ -61,6 +63,9 @@ apr_status_t send_error_bucket(modsec_rec *msr, ap_filter_t *f, int status) {
6163
* the "output" parameter.
6264
*/
6365
int apache2_exec(modsec_rec *msr, const char *command, const char **argv, char **output) {
66+
assert(msr != NULL);
67+
assert(command != NULL);
68+
6469
apr_procattr_t *procattr = NULL;
6570
apr_proc_t *procnew = NULL;
6671
apr_status_t rc = APR_SUCCESS;
@@ -204,6 +209,9 @@ char *get_env_var(request_rec *r, char *name) {
204209
static void internal_log_ex(request_rec *r, directory_config *dcfg, modsec_rec *msr,
205210
int level, int fixup, const char *text, va_list ap)
206211
{
212+
assert(r != NULL);
213+
assert(msr != NULL);
214+
assert(text != NULL);
207215
apr_size_t nbytes, nbytes_written;
208216
apr_file_t *debuglog_fd = NULL;
209217
int filter_debug_level = 0;
@@ -303,6 +311,8 @@ static void internal_log_ex(request_rec *r, directory_config *dcfg, modsec_rec *
303311
* Apache error log if the message is important enough.
304312
*/
305313
void msr_log(modsec_rec *msr, int level, const char *text, ...) {
314+
assert(msr != NULL);
315+
assert(text != NULL);
306316
va_list ap;
307317

308318
va_start(ap, text);
@@ -316,6 +326,8 @@ void msr_log(modsec_rec *msr, int level, const char *text, ...) {
316326
* Apache error log. This is intended for error callbacks.
317327
*/
318328
void msr_log_error(modsec_rec *msr, const char *text, ...) {
329+
assert(msr != NULL);
330+
assert(text != NULL);
319331
va_list ap;
320332

321333
va_start(ap, text);
@@ -330,6 +342,8 @@ void msr_log_error(modsec_rec *msr, const char *text, ...) {
330342
* The 'text' will first be escaped.
331343
*/
332344
void msr_log_warn(modsec_rec *msr, const char *text, ...) {
345+
assert(msr != NULL);
346+
assert(text != NULL);
333347
va_list ap;
334348

335349
va_start(ap, text);

0 commit comments

Comments
 (0)