Skip to content

Commit fd6359e

Browse files
integrated filename* from OWASP
1 parent 7db0379 commit fd6359e

File tree

3 files changed

+68
-4
lines changed

3 files changed

+68
-4
lines changed

apache2/apache2.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@
2727
#if (!defined(NO_MODSEC_API))
2828
/* Optional functions. */
2929

30+
typedef int (*fn_op_param_init_t)(msre_rule* rule, char** error_msg);
31+
typedef int (*fn_op_execute_t)(modsec_rec* msr, msre_rule* rule, msre_var* var, char** error_msg);
3032
APR_DECLARE_OPTIONAL_FN(void, modsec_register_tfn, (const char *name, void *fn));
31-
APR_DECLARE_OPTIONAL_FN(void, modsec_register_operator, (const char *name, void *fn_init, void *fn_exec));
33+
APR_DECLARE_OPTIONAL_FN(void, modsec_register_operator, (const char *name, fn_op_param_init_t fn_init, fn_op_execute_t fn_exec));
3234
APR_DECLARE_OPTIONAL_FN(void, modsec_register_variable,
3335
(const char *name, unsigned int type,
3436
unsigned int argc_min, unsigned int argc_max,

apache2/mod_security2.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,9 +1406,9 @@ static void modsec_register_tfn(const char *name, void *fn) {
14061406
* This function is exported for other Apache modules to
14071407
* register new operators.
14081408
*/
1409-
static void modsec_register_operator(const char *name, void *fn_init, void *fn_exec) {
1409+
static void modsec_register_operator(const char* name, fn_op_param_init_t fn_init, fn_op_execute_t fn_exec) {
14101410
if (modsecurity != NULL) {
1411-
msre_engine_op_register(modsecurity->msre, name, (fn_op_param_init_t)fn_init, (fn_op_execute_t)fn_exec);
1411+
msre_engine_op_register(modsecurity->msre, name, fn_init, fn_exec);
14121412
}
14131413
}
14141414

apache2/msc_multipart.c

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
#include "msc_util.h"
2121
#include "msc_parsers.h"
2222

23+
static const char* mime_charset_special = "!#$&+-^_`~%{}";
24+
static const char* attr_char_special = "!#$&+-^_`~.";
25+
2326
void validate_quotes(modsec_rec *msr, char *data, char quote) {
2427
assert(msr != NULL);
2528
int i, len;
@@ -85,7 +88,8 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
8588
assert(msr != NULL);
8689
assert(c_d_value != NULL);
8790
char *p = NULL, *t = NULL;
88-
91+
char* filenameStar = NULL;
92+
8993
/* accept only what we understand */
9094
if (strncmp(c_d_value, "form-data", 9) != 0) {
9195
return -1;
@@ -223,6 +227,64 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
223227
msr_log(msr, 9, "Multipart: Content-Disposition filename: %s",
224228
log_escape_nq(msr->mp, value));
225229
}
230+
else if (strcmp(name, "filename*") == 0) {
231+
/* old restrictive code
232+
if (strncasecmp(value, "UTF-8''", 7) && strncasecmp(value, "ISO-8859-1''", 12)) {
233+
msr_log(msr, 4, "Multipart: filename* must contain encoding: %s", log_escape_nq(msr->mp, value));
234+
msr->mpd->flag_error = 1;
235+
return -16;
236+
}
237+
//msr_log(msr, 4, "Multipart: Warning: Content-Disposition filename* is obsolete (ignore it)");
238+
*/
239+
240+
/* filename*=charset'[optional-language]'filename */
241+
/* Read beyond the charset and the optional language*/
242+
const char* start_of_charset = p;
243+
/*
244+
if (strncasecmp(value, "UTF-8''", 7) == 0) p += 7;
245+
else if (strncasecmp(value, "ISO-8859-1''", 12) == 0) p += 12;
246+
*/
247+
while ((*p != '\0') && (isalnum(*p) || strchr(mime_charset_special, *p) )) {
248+
p++;
249+
}
250+
if ((*p != '\'') || (p == start_of_charset)) {
251+
return -16; // Must be at least one legit char before ' for start of language
252+
}
253+
p++;
254+
while (isalnum(*p) || *p == '-') p++;
255+
if (*p != '\'') {
256+
return -17; // Single quote for end-of-language not found
257+
}
258+
p++;
259+
260+
/* Now read what should be the actual filename */
261+
const char* start_of_filename = p;
262+
while ((*p != '\0') && (*p != ';')) {
263+
if (*p == '%') {
264+
if ((!isxdigit(*(p + 1))) || (!isxdigit(*(p + 2)))) {
265+
return -18;
266+
}
267+
p += 3;
268+
}
269+
else if ((*p != '\0') && (isalnum(*p) || strchr(mime_charset_special, *p))) {
270+
p++;
271+
}
272+
else {
273+
return -19;
274+
}
275+
}
276+
value = apr_pmemdup(msr->mp, start_of_filename, p - start_of_filename);
277+
if (filenameStar != NULL) {
278+
msr_log(msr, 4,
279+
"Multipart: Warning: Duplicate Content-Disposition filename*: %s.", log_escape_nq(msr->mp, value));
280+
return -20;
281+
}
282+
filenameStar = apr_pstrdup(msr->mp, value);
283+
if (msr->txcfg->debuglog_level >= 9) {
284+
msr_log(msr, 9, "Multipart: Content-Disposition filename*: %s.",
285+
log_escape_nq(msr->mp, value));
286+
}
287+
}
226288
}
227289
else return -11;
228290

0 commit comments

Comments
 (0)