DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT <http://nagoya.apache.org/bugzilla/show_bug.cgi?id=6324>. ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND INSERTED IN THE BUG DATABASE.
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=6324 Invalid POST requests through ajp13 cause 'garbage' characters on the ServletInputStream Summary: Invalid POST requests through ajp13 cause 'garbage' characters on the ServletInputStream Product: Tomcat 3 Version: 3.2.3 Final Platform: PC OS/Version: Windows NT/2K Status: NEW Severity: Normal Priority: Other Component: Connectors AssignedTo: [EMAIL PROTECTED] ReportedBy: [EMAIL PROTECTED] If a client makes a POST request through Apache mod_jk and ajp13, submits the headers but aborts the connection before sending the number of characters specified by the Content-Length header, a POST request with garbage characters as input will be passed to the target servlet on the input stream. This can be seen by calling the getInputStream() method of HttpRequest. The garbage characters appear to come from the headers of the request (see below for an example). This bug affects Tomcat versions 3.2.3 and 3.2.4, running on Windows and Linux. The bug only affects ajp13 with mod_jk. It does not affect ajp12 or Tomcat's HTTP connector. The bug can be reproduced with the following servlet (downloadable from http://sonic.rsuk.com/~psr/tomcatbug/Servlet1.java): ------ package testwebapp; import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; public class Servlet1 extends HttpServlet { private static final String CONTENT_TYPE = "text/html"; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter(); out.println("<html><body>Test</body></html>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("Begin Post Request: " + request.getRemoteAddr() + " " + request.getRequestURI()); response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter(); ServletInputStream is = request.getInputStream(); byte[] buffer = new byte[64000]; int res; StringBuffer sb = new StringBuffer(); while ((res = is.readLine(buffer, 0, buffer.length)) > 0) { String s = new String(buffer, 0, res, "ISO8859-1"); sb.append(s); } out.print(sb.toString()); System.out.println(sb.toString()); System.out.println("End Post Request"); } } ------ On receiving a POST request, this servlet reads from the ServletInputStream and outputs the characters read to both the ServletOutputStream and System.out. To test, Servlet1 can be deployed as part of a webapp (I deployed with the url pattern /servlet 1 in a webapp called testapp). An already built webapp containing Servlet1 can be downloaded from http://sonic.rsuk.com/~psr/tomcatbug/testapp.war. To test, Tomcat 3.2.3 or 3.2.4 needs to be setup with the ajp13 connection handler and then Apache (I used version 1.3.20 on Windows and 1.3.23 on Linux) needs to be setup with mod_jk. I used the version of mod_jk that came with Tomcat 3.2.3 and 3.2.4 for tests with the respective Tomcat versions. I used the following Apache configuration: LoadModule jk_module modules/mod_jk.dll AddModule mod_jk.c JkWorkersFile c:/apache/conf/workers.properties JkLogFile logs/jk.log JkLogLevel error JkMount /testapp/* ajp13 With Tomcat and Apache started, the standard UNIX telnet program can be used to show the error. Telnet into the Apache web server port, and make a post request like the following, making sure you enter at least one carriage return after the last line of the post request: POST /testapp/servlet1 HTTP/1.1 Cookie: JSESSIONID=ldh3f9z3s1 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, */* Cache-Control: no-cache Accept-Language: en-gb User-Agent: Test Content-type: application/x-www-form-urlencoded Content-length: 221 Host: localhost The key to causing the error seems to be making the Content-length header larger than the actual length of posted data. After entering the post headers and moving to the start of a new blank row, press Ctrl+] and type quit to close the connection. The test servlet will print output like the following on standard output: Begin Post Request: xxx.xxx.xxx.xxx /testapp/servlet1 HTTP/1.1 ◄/testapp/servlet1 ♫62.254.201.100 localhost Qá☺ Limage/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, */* ♦ ♣en-gb cache-control no-cache ♥221 á !application/x-www-form-u End Post Request The text printed between the begin and end post request lines is what was read from the ServletInputStream. When making the request using the ajp12 connector, the request is not forwarded to the servlet. When making the request through Tomcat's HTTP connector, Tomcat shows an IOException on the console and does not forward the request to the servlet. If a non-empty, but under-length request is made, the valid part of the request can be read from the input stream, followed by garbage data. The behaviour of Tomcat 3.3a is similar to 3.2.3 and 3.2.4. Tomcat's ajp12 and HTTP connectors behave the same – ignoring invalid POST requests. Tomcat 3.3a's ajp13 connector places all input sent on the ServletInputStream. -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>