468747 - XSS vulnerability in HttpSpiContextHandler
This commit is contained in:
parent
0db541889b
commit
4472b614b9
|
@ -29,6 +29,9 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
import com.sun.net.httpserver.Authenticator;
|
||||
import com.sun.net.httpserver.Authenticator.Result;
|
||||
|
@ -42,7 +45,8 @@ import com.sun.net.httpserver.HttpPrincipal;
|
|||
*/
|
||||
public class HttpSpiContextHandler extends ContextHandler
|
||||
{
|
||||
|
||||
public static final Logger LOG = Log.getLogger(HttpSpiContextHandler.class);
|
||||
|
||||
private HttpContext _httpContext;
|
||||
|
||||
private HttpHandler _httpHandler;
|
||||
|
@ -87,17 +91,21 @@ public class HttpSpiContextHandler extends ContextHandler
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.debug(ex);
|
||||
PrintWriter writer = new PrintWriter(jettyHttpExchange.getResponseBody());
|
||||
|
||||
resp.setStatus(500);
|
||||
writer.println("<h2>HTTP ERROR: 500</h2>");
|
||||
writer.println("<pre>INTERNAL_SERVER_ERROR</pre>");
|
||||
writer.println("<p>RequestURI=" + req.getRequestURI() + "</p>");
|
||||
|
||||
writer.println("<pre>");
|
||||
ex.printStackTrace(writer);
|
||||
writer.println("</pre>");
|
||||
writer.println("<p>RequestURI=" + StringUtil.sanitizeXmlString(req.getRequestURI()) + "</p>");
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
writer.println("<pre>");
|
||||
ex.printStackTrace(writer);
|
||||
writer.println("</pre>");
|
||||
}
|
||||
|
||||
writer.println("<p><i><small><a href=\"http://eclipse.org/jetty\">Powered by jetty://</a></small></i></p>");
|
||||
|
||||
writer.close();
|
||||
|
|
|
@ -602,19 +602,9 @@ public class Response implements HttpServletResponse
|
|||
setContentType(MimeTypes.Type.TEXT_HTML_8859_1.toString());
|
||||
try (ByteArrayISO8859Writer writer= new ByteArrayISO8859Writer(2048);)
|
||||
{
|
||||
if (message != null)
|
||||
{
|
||||
message= StringUtil.replace(message, "&", "&");
|
||||
message= StringUtil.replace(message, "<", "<");
|
||||
message= StringUtil.replace(message, ">", ">");
|
||||
}
|
||||
message=StringUtil.sanitizeXmlString(message);
|
||||
String uri= request.getRequestURI();
|
||||
if (uri!=null)
|
||||
{
|
||||
uri= StringUtil.replace(uri, "&", "&");
|
||||
uri= StringUtil.replace(uri, "<", "<");
|
||||
uri= StringUtil.replace(uri, ">", ">");
|
||||
}
|
||||
uri=StringUtil.sanitizeXmlString(uri);
|
||||
|
||||
writer.write("<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=ISO-8859-1\"/>\n");
|
||||
writer.write("<title>Error ");
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.eclipse.jetty.server.Response;
|
|||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.ByteArrayISO8859Writer;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
@ -275,29 +276,7 @@ public class ErrorHandler extends AbstractHandler
|
|||
if (string==null)
|
||||
return;
|
||||
|
||||
for (int i=0;i<string.length();i++)
|
||||
{
|
||||
char c=string.charAt(i);
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case '&' :
|
||||
writer.write("&");
|
||||
break;
|
||||
case '<' :
|
||||
writer.write("<");
|
||||
break;
|
||||
case '>' :
|
||||
writer.write(">");
|
||||
break;
|
||||
|
||||
default:
|
||||
if (Character.isISOControl(c) && !Character.isWhitespace(c))
|
||||
writer.write('?');
|
||||
else
|
||||
writer.write(c);
|
||||
}
|
||||
}
|
||||
writer.write(StringUtil.sanitizeXmlString(string));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -733,5 +733,73 @@ public class StringUtil
|
|||
|
||||
return s.substring(1,s.length()-1).split(" *, *");
|
||||
}
|
||||
|
||||
public static String sanitizeXmlString(String html)
|
||||
{
|
||||
if (html==null)
|
||||
return null;
|
||||
|
||||
int i=0;
|
||||
|
||||
// Are there any characters that need sanitizing?
|
||||
loop: for (;i<html.length();i++)
|
||||
{
|
||||
char c=html.charAt(i);
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case '&' :
|
||||
case '<' :
|
||||
case '>' :
|
||||
case '\'':
|
||||
case '"':
|
||||
break loop;
|
||||
|
||||
default:
|
||||
if (Character.isISOControl(c) && !Character.isWhitespace(c))
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
|
||||
// No characters need sanitizing, so return original string
|
||||
if (i==html.length())
|
||||
return html;
|
||||
|
||||
// Create builder with OK content so far
|
||||
StringBuilder out = new StringBuilder(html.length()*4/3);
|
||||
out.append(html,0,i);
|
||||
|
||||
// sanitize remaining content
|
||||
for (;i<html.length();i++)
|
||||
{
|
||||
char c=html.charAt(i);
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case '&' :
|
||||
out.append("&");
|
||||
break;
|
||||
case '<' :
|
||||
out.append("<");
|
||||
break;
|
||||
case '>' :
|
||||
out.append(">");
|
||||
break;
|
||||
case '\'':
|
||||
out.append("'");
|
||||
break;
|
||||
case '"':
|
||||
out.append(""");
|
||||
break;
|
||||
|
||||
default:
|
||||
if (Character.isISOControl(c) && !Character.isWhitespace(c))
|
||||
out.append('?');
|
||||
else
|
||||
out.append(c);
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -613,7 +613,7 @@ public abstract class Resource implements ResourceFactory, Closeable
|
|||
|
||||
private static String deTag(String raw)
|
||||
{
|
||||
return StringUtil.replace( StringUtil.replace(raw,"<","<"), ">", ">");
|
||||
return StringUtil.sanitizeXmlString(raw);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -201,7 +201,8 @@ public class StringUtilTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testIsBlank() {
|
||||
public void testIsBlank()
|
||||
{
|
||||
Assert.assertTrue(StringUtil.isBlank(null));
|
||||
Assert.assertTrue(StringUtil.isBlank(""));
|
||||
Assert.assertTrue(StringUtil.isBlank("\r\n"));
|
||||
|
@ -216,7 +217,8 @@ public class StringUtilTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testIsNotBlank() {
|
||||
public void testIsNotBlank()
|
||||
{
|
||||
Assert.assertFalse(StringUtil.isNotBlank(null));
|
||||
Assert.assertFalse(StringUtil.isNotBlank(""));
|
||||
Assert.assertFalse(StringUtil.isNotBlank("\r\n"));
|
||||
|
@ -229,4 +231,14 @@ public class StringUtilTest
|
|||
Assert.assertTrue(StringUtil.isNotBlank("."));
|
||||
Assert.assertTrue(StringUtil.isNotBlank(";\n"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSanitizeHTML()
|
||||
{
|
||||
assertEquals(null,StringUtil.sanitizeXmlString(null));
|
||||
assertEquals("",StringUtil.sanitizeXmlString(""));
|
||||
assertEquals("<&>",StringUtil.sanitizeXmlString("<&>"));
|
||||
assertEquals("Hello <Cruel> World",StringUtil.sanitizeXmlString("Hello <Cruel> World"));
|
||||
assertEquals("Hello ? World",StringUtil.sanitizeXmlString("Hello \u0000 World"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.eclipse.jetty.io.ByteBufferPool;
|
|||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.server.HttpConnection;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -477,7 +478,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
}
|
||||
else
|
||||
{
|
||||
warn.append('"').append(ua.replaceAll("<", "<")).append("\" ");
|
||||
warn.append('"').append(StringUtil.sanitizeXmlString(ua)).append("\" ");
|
||||
}
|
||||
warn.append("requested WebSocket version [").append(version);
|
||||
warn.append("], Jetty supports version");
|
||||
|
|
|
@ -25,6 +25,8 @@ import java.io.OutputStreamWriter;
|
|||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
||||
public class XmlAppendable
|
||||
{
|
||||
private final String SPACES=" ";
|
||||
|
@ -82,32 +84,7 @@ public class XmlAppendable
|
|||
public XmlAppendable content(String s) throws IOException
|
||||
{
|
||||
if (s!=null)
|
||||
{
|
||||
for (int i=0;i<s.length();i++)
|
||||
{
|
||||
char c = s.charAt(i);
|
||||
switch(c)
|
||||
{
|
||||
case '<':
|
||||
_out.append("<");
|
||||
break;
|
||||
case '>':
|
||||
_out.append(">");
|
||||
break;
|
||||
case '&':
|
||||
_out.append("&");
|
||||
break;
|
||||
case '\'':
|
||||
_out.append("'");
|
||||
break;
|
||||
case '"':
|
||||
_out.append(""");
|
||||
break;
|
||||
default:
|
||||
_out.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
_out.append(StringUtil.sanitizeXmlString(s));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue