Skip to content

Commit 1d0ccc9

Browse files
authored
Merge pull request #2660 from martinhsv/v2/master
Multipart names may include single quote if double-quote enclosed
2 parents 4fc4ba5 + 065dbe7 commit 1d0ccc9

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

Diff for: CHANGES

+2
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+
* Multipart names/filenames may include single quote if double-quote enclosed
5+
[Issue #2352 @martinhsv]
46
* Add SecRequestBodyJsonDepthLimit to modsecurity.conf-recommended
57
[Issue #2647 @theMiddleBlue, @airween, @877509395 ,@martinhsv]
68
* IIS: Update dependencies for Windows build as of v2.9.5

Diff for: apache2/msc_multipart.c

+11-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "msc_util.h"
2121
#include "msc_parsers.h"
2222

23-
void validate_quotes(modsec_rec *msr, char *data) {
23+
void validate_quotes(modsec_rec *msr, char *data, char quote) {
2424
int i, len;
2525

2626
if(msr == NULL)
@@ -32,6 +32,12 @@ void validate_quotes(modsec_rec *msr, char *data) {
3232
if(data == NULL)
3333
return;
3434

35+
// if the value was enclosed in double quotes, then we don't care about
36+
// a single quote character within the name.
37+
if (quote == '"') {
38+
return;
39+
}
40+
3541
len = strlen(data);
3642

3743
for(i = 0; i < len; i++) {
@@ -123,9 +129,10 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
123129
* set so the user can deal with it in the rules if they so wish.
124130
*/
125131

132+
char quote = '\0';
126133
if ((*p == '"') || (*p == '\'')) {
127134
/* quoted */
128-
char quote = *p;
135+
quote = *p; // remember which quote character was used for the value
129136

130137
if (quote == '\'') {
131138
msr->mpd->flag_invalid_quoting = 1;
@@ -182,7 +189,7 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
182189

183190
if (strcmp(name, "name") == 0) {
184191

185-
validate_quotes(msr, value);
192+
validate_quotes(msr, value, quote);
186193

187194
msr->multipart_name = apr_pstrdup(msr->mp, value);
188195

@@ -201,7 +208,7 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
201208
else
202209
if (strcmp(name, "filename") == 0) {
203210

204-
validate_quotes(msr, value);
211+
validate_quotes(msr, value, quote);
205212

206213
msr->multipart_filename = apr_pstrdup(msr->mp, value);
207214

Diff for: tests/regression/misc/00-multipart-parser.t

+39
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,45 @@
736736
),
737737
},
738738
739+
# Single quote within double quotes is ok
740+
{
741+
type => "misc",
742+
comment => "multipart parser (C-D uses single quote within double quotes)",
743+
conf => qq(
744+
SecRuleEngine On
745+
SecDebugLog $ENV{DEBUG_LOG}
746+
SecDebugLogLevel 9
747+
SecRequestBodyAccess On
748+
SecRule MULTIPART_INVALID_QUOTING "!\@eq 0" "phase:2,deny,id:500169"
749+
),
750+
match_log => {
751+
debug => [ qr/Adding request argument \(BODY\): name "a'b/s, 1 ],
752+
-debug => [ qr/Adding request argument \(BODY\): name "b/s, 1 ],
753+
},
754+
match_response => {
755+
status => qr/^200$/,
756+
},
757+
request => new HTTP::Request(
758+
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
759+
[
760+
"Content-Type" => "multipart/form-data; boundary=---------------------------69343412719991675451336310646",
761+
],
762+
normalize_raw_request_data(
763+
q(
764+
-----------------------------69343412719991675451336310646
765+
Content-Disposition: form-data; name="a'b"
766+
767+
1
768+
-----------------------------69343412719991675451336310646
769+
Content-Disposition: form-data; name="aaa"; filename="d'ummy"
770+
771+
2
772+
-----------------------------69343412719991675451336310646--
773+
),
774+
),
775+
),
776+
},
777+
739778
# Invalid boundary separators
740779
{
741780
type => "misc",

0 commit comments

Comments
 (0)