Skip to content

Commit 7f0221b

Browse files
committed
Limit CGI command line arguments
Limit the decoded form of individual command line arguments. This is to work various issues passing command line arguments from Java to the OS on Windows. This restriction may be overridden by the new initialisation parameter cmdLineArgumentsDecoded. This is the fix for CVE-2019-0232. # Conflicts: # java/org/apache/catalina/servlets/CGIServlet.java
1 parent 6664438 commit 7f0221b

File tree

6 files changed

+80
-2
lines changed

6 files changed

+80
-2
lines changed

conf/web.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,20 @@
330330
<!-- If not set, then webAppRootDir is used. -->
331331
<!-- Recommended value: WEB-INF/cgi -->
332332
<!-- -->
333+
<!-- cmdLineArgumentsDecoded -->
334+
<!-- Only used when enableCmdLineArguments is -->
335+
<!-- true. The pattern that individual decoded -->
336+
<!-- command line arguments must match else the -->
337+
<!-- request will be rejected. This is to -->
338+
<!-- work-around various issues when Java passes -->
339+
<!-- the arguments to the OS. See the CGI How-To -->
340+
<!-- for more details. The default varies by -->
341+
<!-- platform. -->
342+
<!-- Windows: [[a-zA-Z0-9\Q-_.\\/:\E]+] -->
343+
<!-- Others: [.*] -->
344+
<!-- Note that internally the CGI Servlet treats -->
345+
<!-- [.*] as a special case to improve performance -->
346+
<!-- -->
333347
<!-- cmdLineArgumentsEncoded -->
334348
<!-- Only used when enableCmdLineArguments is -->
335349
<!-- true. The pattern that individual encoded -->

java/org/apache/catalina/servlets/CGIServlet.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import org.apache.catalina.util.IOTools;
5454
import org.apache.juli.logging.Log;
5555
import org.apache.juli.logging.LogFactory;
56+
import org.apache.naming.resources.JrePlatform;
5657
import org.apache.tomcat.util.res.StringManager;
5758

5859

@@ -248,10 +249,21 @@ public final class CGIServlet extends HttpServlet {
248249
private static final long serialVersionUID = 1L;
249250

250251
private static final Set<String> DEFAULT_SUPER_METHODS = new HashSet<String>();
252+
private static final Pattern DEFAULT_CMD_LINE_ARGUMENTS_DECODED_PATTERN;
253+
private static final String ALLOW_ANY_PATTERN = ".*";
254+
251255
static {
252256
DEFAULT_SUPER_METHODS.add("HEAD");
253257
DEFAULT_SUPER_METHODS.add("OPTIONS");
254258
DEFAULT_SUPER_METHODS.add("TRACE");
259+
260+
if (JrePlatform.IS_WINDOWS) {
261+
DEFAULT_CMD_LINE_ARGUMENTS_DECODED_PATTERN = Pattern.compile("[a-zA-Z0-9\\Q-_.\\/:\\E]+");
262+
} else {
263+
// No restrictions
264+
DEFAULT_CMD_LINE_ARGUMENTS_DECODED_PATTERN = null;
265+
}
266+
255267
}
256268

257269

@@ -317,6 +329,14 @@ public final class CGIServlet extends HttpServlet {
317329
private Pattern cmdLineArgumentsEncodedPattern =
318330
Pattern.compile("[a-zA-Z0-9\\Q%;/?:@&,$-_.!~*'()\\E]+");
319331

332+
/**
333+
* Limits the decoded form of individual command line arguments. Default
334+
* varies by platform.
335+
*/
336+
private Pattern cmdLineArgumentsDecodedPattern = DEFAULT_CMD_LINE_ARGUMENTS_DECODED_PATTERN;
337+
338+
339+
320340
/**
321341
* Sets instance variables.
322342
* <P>
@@ -414,6 +434,14 @@ public void init(ServletConfig config) throws ServletException {
414434
cmdLineArgumentsEncodedPattern =
415435
Pattern.compile(getServletConfig().getInitParameter("cmdLineArgumentsEncoded"));
416436
}
437+
438+
String value = getServletConfig().getInitParameter("cmdLineArgumentsDecoded");
439+
if (ALLOW_ANY_PATTERN.equals(value)) {
440+
// Optimisation for case where anything is allowed
441+
cmdLineArgumentsDecodedPattern = null;
442+
} else if (value != null) {
443+
cmdLineArgumentsDecodedPattern = Pattern.compile(value);
444+
}
417445
}
418446

419447

@@ -817,7 +845,17 @@ protected boolean setupFromRequest(HttpServletRequest req)
817845
}
818846
return false;
819847
}
848+
820849
String decodedArgument = URLDecoder.decode(encodedArgument, parameterEncoding);
850+
if (cmdLineArgumentsDecodedPattern != null &&
851+
!cmdLineArgumentsDecodedPattern.matcher(decodedArgument).matches()) {
852+
if (log.isDebugEnabled()) {
853+
log.debug(sm.getString("cgiServlet.invalidArgumentDecoded",
854+
decodedArgument, cmdLineArgumentsDecodedPattern.toString()));
855+
}
856+
return false;
857+
}
858+
821859
cmdLineParameters.add(decodedArgument);
822860
}
823861
}
@@ -1126,7 +1164,6 @@ protected boolean setCGIEnvironment(HttpServletRequest req) throws IOException {
11261164
this.env = envp;
11271165

11281166
return true;
1129-
11301167
}
11311168

11321169
/**

java/org/apache/catalina/servlets/LocalStrings.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ cgiServlet.expandOk=Expanded script at path [{0}] to [{1}]
2424
cgiServlet.find.found=Found CGI: name [{0}], path [{1}], script name [{2}] and CGI name [{3}]
2525
cgiServlet.find.location=Looking for a file at [{0}]
2626
cgiServlet.find.path=CGI script requested at path [{0}] relative to CGI location [{1}]
27+
cgiServlet.invalidArgumentDecoded=The decoded command line argument [{0}] did not match the configured cmdLineArgumentsDecoded pattern [{1}]
2728
cgiServlet.invalidArgumentEncoded=The encoded command line argument [{0}] did not match the configured cmdLineArgumentsEncoded pattern [{1}]
2829
cgiServlet.runBadHeader=Bad header line [{0}]
2930
cgiServlet.runFail=I/O problems processing CGI

webapps/docs/cgi-howto.xml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,22 @@ the web application root directory + File.separator + this prefix.
102102
By default there is no value, which results in the web application root
103103
directory being used as the search path. The recommended value is
104104
<code>WEB-INF/cgi</code></li>
105+
<li><strong>cmdLineArgumentsDecoded</strong> - If command line argumemnts
106+
are enabled (via <strong>enableCmdLineArguments</strong>) and Tomcat is running
107+
on Windows then each individual decoded command line argument must match this
108+
pattern else the request will be rejected. This is to protect against known
109+
issues passing command line arguments from Java to Windows. These issues can
110+
lead to remote code execution. For more information on these issues see
111+
<a href="https://codewhitesec.blogspot.com/2016/02/java-and-command-line-injections-in-windows.html">Markus
112+
Wulftange&apos;s blog</a> and this archived
113+
<a href="https://web.archive.org/web/20161228144344/https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/">blog
114+
by Daniel Colascione</a>.</li>
105115
<li><strong>cmdLineArgumentsEncoded</strong> - If command line argumemnts
106116
are enabled (via <strong>enableCmdLineArguments</strong>) individual encoded
107117
command line argument must match this pattern else the request will be rejected.
108118
The default matches the allowed values defined by RFC3875 and is
109119
<code>[a-zA-Z0-9\Q%;/?:@&amp;,$-_.!~*'()\E]+</code></li>
110-
<li><strong>enableCmdLineArguments</strong> - Are command line parameters
120+
<li><strong>enableCmdLineArguments</strong> - Are command line arguments
111121
generated from the query string as per section 4.4 of 3875 RFC? The default is
112122
<code>true</code>.</li>
113123
<li><strong>environment-variable-</strong> - An environment to be set for the

webapps/docs/changelog.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,14 @@
144144
3875. This restriction may be relaxed by the use of the new
145145
initialisation parameter <code>cmdLineArgumentsEncoded</code>. (markt)
146146
</add>
147+
<add>
148+
When the CGI Servlet is configured with
149+
<code>enableCmdLineArguments</code> set to true, limit the decoded form
150+
of the individual command line arguments to known safe values when
151+
running on Windows. This restriction may be relaxed by the use of the
152+
new initialisation parameter <code>cmdLineArgumentsDecoded</code>. This
153+
is the fix for CVE-2019-0232. (markt)
154+
</add>
147155
</changelog>
148156
</subsection>
149157
<subsection name="Coyote">

webapps/docs/security-howto.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,14 @@ server.info=Apache Tomcat/7.0.x
503503
initialisation parameter should not be set to <code>10</code> or higher on a
504504
production system because the debug page is not secure.</p>
505505

506+
<p>When using the CGI Servlet on Windows with
507+
<code>enableCmdLineArguments</code> enabled, review the setting of
508+
<code>cmdLineArgumentsDecoded</code> carefully and ensure that it is
509+
appropriate for your environment. The default value is secure. Insecure
510+
configurations may expose the server to remote code execution. Further
511+
information on the potential risks and mitigations may be found by
512+
following the links in the <a href="cgi-howto.html">CGI How To</a>.</p>
513+
506514
<p><a href="config/filter.html">FailedRequestFilter</a>
507515
can be configured and used to reject requests that had errors during
508516
request parameter parsing. Without the filter the default behaviour is

0 commit comments

Comments
 (0)