Skip to content

Commit e0a6a9e

Browse files
committed
StrictHttpFirewall allows CJKV characters
Issue gh-11264
1 parent 5155719 commit e0a6a9e

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,18 @@ public class StrictHttpFirewall implements HttpFirewall {
107107

108108
private static final List<String> FORBIDDEN_NULL = Collections.unmodifiableList(Arrays.asList("\0", "%00"));
109109

110+
private static final List<String> FORBIDDEN_LF = Collections
111+
.unmodifiableList(Arrays.asList("\r", "%0a", "%0A"));
112+
113+
private static final List<String> FORBIDDEN_CR = Collections
114+
.unmodifiableList(Arrays.asList("\n", "%0d", "%0D"));
115+
116+
private static final List<String> FORBIDDEN_LINE_SEPARATOR = Collections
117+
.unmodifiableList(Arrays.asList("\u2028"));
118+
119+
private static final List<String> FORBIDDEN_PARAGRAPH_SEPARATOR = Collections
120+
.unmodifiableList(Arrays.asList("\u2029"));
121+
110122
private Set<String> encodedUrlBlocklist = new HashSet<>();
111123

112124
private Set<String> decodedUrlBlocklist = new HashSet<>();
@@ -135,10 +147,14 @@ public StrictHttpFirewall() {
135147
urlBlocklistsAddAll(FORBIDDEN_DOUBLE_FORWARDSLASH);
136148
urlBlocklistsAddAll(FORBIDDEN_BACKSLASH);
137149
urlBlocklistsAddAll(FORBIDDEN_NULL);
150+
urlBlocklistsAddAll(FORBIDDEN_LF);
151+
urlBlocklistsAddAll(FORBIDDEN_CR);
138152

139153
this.encodedUrlBlocklist.add(ENCODED_PERCENT);
140154
this.encodedUrlBlocklist.addAll(FORBIDDEN_ENCODED_PERIOD);
141155
this.decodedUrlBlocklist.add(PERCENT);
156+
this.decodedUrlBlocklist.addAll(FORBIDDEN_LINE_SEPARATOR);
157+
this.decodedUrlBlocklist.addAll(FORBIDDEN_PARAGRAPH_SEPARATOR);
142158
}
143159

144160
/**
@@ -432,9 +448,6 @@ public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws
432448
throw new RequestRejectedException("The request was rejected because the URL was not normalized.");
433449
}
434450
rejectNonPrintableAsciiCharactersInFieldName(request.getRequestURI(), "requestURI");
435-
rejectNonPrintableAsciiCharactersInFieldName(request.getServletPath(), "servletPath");
436-
rejectNonPrintableAsciiCharactersInFieldName(request.getPathInfo(), "pathInfo");
437-
rejectNonPrintableAsciiCharactersInFieldName(request.getContextPath(), "contextPath");
438451
return new StrictFirewalledRequest(request);
439452
}
440453

web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,12 @@ public void getFirewalledRequestWhenContainsUpperboundAsciiThenNoException() {
343343
this.firewall.getFirewalledRequest(this.request);
344344
}
345345

346+
@Test
347+
public void getFirewalledRequestWhenJapaneseCharacterThenNoException() {
348+
this.request.setServletPath("/\u3042");
349+
this.firewall.getFirewalledRequest(this.request);
350+
}
351+
346352
@Test
347353
public void getFirewalledRequestWhenExceedsUpperboundAsciiThenException() {
348354
this.request.setRequestURI("/\u007f");
@@ -364,6 +370,20 @@ public void getFirewalledRequestWhenContainsEncodedNullThenException() {
364370
.isThrownBy(() -> this.firewall.getFirewalledRequest(this.request));
365371
}
366372

373+
@Test
374+
public void getFirewalledRequestWhenContainsLowercaseEncodedLineFeedThenException() {
375+
this.request.setRequestURI("/something%0a/");
376+
assertThatExceptionOfType(RequestRejectedException.class)
377+
.isThrownBy(() -> this.firewall.getFirewalledRequest(this.request));
378+
}
379+
380+
@Test
381+
public void getFirewalledRequestWhenContainsUppercaseEncodedLineFeedThenException() {
382+
this.request.setRequestURI("/something%0A/");
383+
assertThatExceptionOfType(RequestRejectedException.class)
384+
.isThrownBy(() -> this.firewall.getFirewalledRequest(this.request));
385+
}
386+
367387
@Test
368388
public void getFirewalledRequestWhenContainsLineFeedThenException() {
369389
this.request.setRequestURI("/something\n/");
@@ -378,6 +398,20 @@ public void getFirewalledRequestWhenServletPathContainsLineFeedThenException() {
378398
.isThrownBy(() -> this.firewall.getFirewalledRequest(this.request));
379399
}
380400

401+
@Test
402+
public void getFirewalledRequestWhenContainsLowercaseEncodedCarriageReturnThenException() {
403+
this.request.setRequestURI("/something%0d/");
404+
assertThatExceptionOfType(RequestRejectedException.class)
405+
.isThrownBy(() -> this.firewall.getFirewalledRequest(this.request));
406+
}
407+
408+
@Test
409+
public void getFirewalledRequestWhenContainsUppercaseEncodedCarriageReturnThenException() {
410+
this.request.setRequestURI("/something%0D/");
411+
assertThatExceptionOfType(RequestRejectedException.class)
412+
.isThrownBy(() -> this.firewall.getFirewalledRequest(this.request));
413+
}
414+
381415
@Test
382416
public void getFirewalledRequestWhenContainsCarriageReturnThenException() {
383417
this.request.setRequestURI("/something\r/");
@@ -392,6 +426,20 @@ public void getFirewalledRequestWhenServletPathContainsCarriageReturnThenExcepti
392426
.isThrownBy(() -> this.firewall.getFirewalledRequest(this.request));
393427
}
394428

429+
@Test
430+
public void getFirewalledRequestWhenServletPathContainsLineSeparatorThenException() {
431+
this.request.setServletPath("/something\u2028/");
432+
assertThatExceptionOfType(RequestRejectedException.class)
433+
.isThrownBy(() -> this.firewall.getFirewalledRequest(this.request));
434+
}
435+
436+
@Test
437+
public void getFirewalledRequestWhenServletPathContainsParagraphSeparatorThenException() {
438+
this.request.setServletPath("/something\u2029/");
439+
assertThatExceptionOfType(RequestRejectedException.class)
440+
.isThrownBy(() -> this.firewall.getFirewalledRequest(this.request));
441+
}
442+
395443
/**
396444
* On WebSphere 8.5 a URL like /context-root/a/b;%2f1/c can bypass a rule on /a/b/c
397445
* because the pathInfo is /a/b;/1/c which ends up being /a/b/1/c while Spring MVC

0 commit comments

Comments
 (0)