diff --git a/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XXEServlet.java b/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XEEandXXEServlet.java similarity index 61% rename from src/main/java/org/t246osslab/easybuggy/vulnerabilities/XXEServlet.java rename to src/main/java/org/t246osslab/easybuggy/vulnerabilities/XEEandXXEServlet.java index ad7aac87..b86af322 100644 --- a/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XXEServlet.java +++ b/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XEEandXXEServlet.java @@ -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); @@ -48,15 +48,19 @@ protected void doGet(HttpServletRequest req, HttpServletResponse res) throws Ser Locale locale = req.getLocale(); StringBuilder bodyHtml = new StringBuilder(); - bodyHtml.append("
"); + if ("/xee".equals(req.getServletPath())) { + bodyHtml.append(""); + } else { + bodyHtml.append(""); + } bodyHtml.append(MessageUtils.getMsg("msg.add.users.by.xml", locale)); bodyHtml.append("

"); bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); - bodyHtml.append(TAB + ESAPI.encoder().encodeForHTML( - "") + "
"); - bodyHtml.append(TAB + ESAPI.encoder().encodeForHTML( - "") + "
"); + bodyHtml.append(TAB + ESAPI.encoder() + .encodeForHTML("") + "
"); + bodyHtml.append(TAB + ESAPI.encoder() + .encodeForHTML("") + "
"); bodyHtml.append(ESAPI.encoder().encodeForHTML("
")); bodyHtml.append("

"); bodyHtml.append("
"); @@ -68,21 +72,47 @@ protected void doGet(HttpServletRequest req, HttpServletResponse res) throws Ser bodyHtml.append(req.getAttribute("errorMessage")); bodyHtml.append("

"); } - bodyHtml.append(MessageUtils.getMsg("msg.note.xxe.step1", locale)); - bodyHtml.append("

"); - bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); - bodyHtml.append(ESAPI.encoder().encodeForHTML("\">") + "
"); - bodyHtml.append(ESAPI.encoder().encodeForHTML("%p2;")); - bodyHtml.append("

"); - bodyHtml.append(MessageUtils.getMsg("msg.note.xxe.step2", locale)); - bodyHtml.append("

"); - bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); - bodyHtml.append(ESAPI.encoder() - .encodeForHTML("") + "
"); - bodyHtml.append(ESAPI.encoder().encodeForHTML("")); + if ("/xee".equals(req.getServletPath())) { + bodyHtml.append(MessageUtils.getMsg("msg.note.xee", locale)); + bodyHtml.append("

"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append(ESAPI.encoder().encodeForHTML(""); + bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("]>") + "
"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("") + + "
"); + bodyHtml.append(TAB + ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append(TAB + ESAPI.encoder().encodeForHTML("
") + "
"); + bodyHtml.append(TAB + ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append(TAB + TAB + ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append(TAB + TAB + TAB + ESAPI.encoder().encodeForHTML("&x100;") + "
"); + bodyHtml.append(TAB + TAB + ESAPI.encoder().encodeForHTML("
") + "
"); + bodyHtml.append(TAB + ESAPI.encoder().encodeForHTML("
") + "
"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("
") + "
"); + } else { + bodyHtml.append(MessageUtils.getMsg("msg.note.xxe.step1", locale)); + bodyHtml.append("

"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append( + ESAPI.encoder().encodeForHTML("\">") + "
"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("%p2;")); + bodyHtml.append("

"); + bodyHtml.append(MessageUtils.getMsg("msg.note.xxe.step2", locale)); + bodyHtml.append("

"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("") + "
"); + bodyHtml.append( + ESAPI.encoder().encodeForHTML("") + + "
"); + bodyHtml.append(ESAPI.encoder().encodeForHTML("")); + } bodyHtml.append(""); - 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 { @@ -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("

"); - bodyHtml.append(customHandler.getResult()); - } + bodyHtml.append("

"); + bodyHtml.append(customHandler.getResult()); bodyHtml.append("

"); bodyHtml.append(""); @@ -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("

ou: " + ESAPI.encoder().encodeForHTML(attributes.getValue("ou")) + "

"); + String ou = attributes.getValue("ou"); + if (ou == null || "".equals(ou)) { + return; + } + isOuExist = true; + result.append("

ou: " + ESAPI.encoder().encodeForHTML(ou) + "

"); result.append("
"); result.append("
"); result.append(""); @@ -201,12 +244,13 @@ public void startElement(String uri, String localName, String qName, Attributes result.append(""); result.append(""); result.append(""); - } else if ("user".equals(qName)) { + } else if (isOuExist && "user".equals(qName)) { result.append(""); result.append(""); result.append(""); result.append(""); result.append(""); + isRegistered = true; } } @@ -221,5 +265,9 @@ public void endElement(String uri, String localName, String qName) throws SAXExc String getResult() { return result.toString(); } + + boolean isRegistered() { + return isRegistered; + } } } diff --git a/src/main/resources/indexpage_en.properties b/src/main/resources/indexpage_en.properties index fe5b38e0..b665a3ec 100644 --- a/src/main/resources/indexpage_en.properties +++ b/src/main/resources/indexpage_en.properties @@ -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. diff --git a/src/main/resources/indexpage_ja.properties b/src/main/resources/indexpage_ja.properties index 8b2aedb5..2b4f364f 100644 --- a/src/main/resources/indexpage_ja.properties +++ b/src/main/resources/indexpage_ja.properties @@ -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 diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index ad4f3950..27b57c8b 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -129,6 +129,8 @@ msg.note.unrestricted.size.upload=  \ It is easy to guess an account who can logs in since authentication error messages on this page is too detailed. +msg.note.xee=  \ +If you upload the following file, it will waste server resource. msg.note.xss=  \ Session ID is shown if you set name to >tpircs/<;)eikooc.tnemucod(trela>tpIrcs< msg.note.xxe.step1=  \ diff --git a/src/main/resources/messages_ja.properties b/src/main/resources/messages_ja.properties index df2e67f4..01a71578 100644 --- a/src/main/resources/messages_ja.properties +++ b/src/main/resources/messages_ja.properties @@ -129,6 +129,8 @@ msg.note.unrestricted.size.upload=  \ \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=  \ +\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=  \ \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=  \ diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp index 1c9c951d..0e2649e1 100644 --- a/src/main/webapp/index.jsp +++ b/src/main/webapp/index.jsp @@ -214,16 +214,21 @@ key="function.name.csrf" />:

-
  • - : - -

  • :

  • +
  • + : + +

  • +
  • + : + +

  • phonemail
    " + ESAPI.encoder().encodeForHTML(attributes.getValue("uid")) + "" + ESAPI.encoder().encodeForHTML(attributes.getValue("phone")) + "" + ESAPI.encoder().encodeForHTML(attributes.getValue("mail")) + "