View Javadoc
1   package com.jsql.util;
2   
3   import com.jsql.model.InjectionModel;
4   import com.jsql.model.exception.JSqlException;
5   import org.apache.commons.lang3.StringUtils;
6   import org.apache.logging.log4j.LogManager;
7   import org.apache.logging.log4j.Logger;
8   import org.w3c.dom.Document;
9   import org.w3c.dom.Node;
10  import org.xml.sax.InputSource;
11  import org.xml.sax.SAXException;
12  
13  import javax.xml.XMLConstants;
14  import javax.xml.parsers.DocumentBuilderFactory;
15  import javax.xml.parsers.ParserConfigurationException;
16  import javax.xml.transform.TransformerException;
17  import javax.xml.transform.TransformerFactory;
18  import javax.xml.transform.dom.DOMSource;
19  import javax.xml.transform.stream.StreamResult;
20  import java.io.IOException;
21  import java.io.StringReader;
22  import java.io.StringWriter;
23  import java.util.regex.Pattern;
24  
25  public class SoapUtil {
26      
27      private static final Logger LOGGER = LogManager.getRootLogger();
28  
29      private final InjectionModel injectionModel;
30      
31      public SoapUtil(InjectionModel injectionModel) {
32          this.injectionModel = injectionModel;
33      }
34  
35      public boolean testParameters(boolean hasFoundInjection) {
36          if (!hasFoundInjection) {
37              LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "{} SOAP...", () -> I18nUtil.valueByKey("LOG_CHECKING"));
38          } else {
39              return true;
40          }
41  
42          if (
43              this.injectionModel.getMediatorUtils().getPreferencesUtil().isCheckingAllSoapParam()
44              && this.injectionModel.getMediatorUtils().getParameterUtil().isRequestSoap()
45          ) {
46              try {
47                  var doc = SoapUtil.convertToDocument(this.injectionModel.getMediatorUtils().getParameterUtil().getRawRequest());
48                  LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Parsing SOAP from Request...");
49                  return this.isTextNodeInjectable(doc, doc.getDocumentElement());
50              } catch (Exception e) {
51                  LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "SOAP not detected");
52              }
53          }
54          return false;
55      }
56      
57      public static Document convertToDocument(String xmlStr) throws ParserConfigurationException, SAXException, IOException {
58          var factory = DocumentBuilderFactory.newInstance();
59          factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, StringUtils.EMPTY);
60          factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, StringUtils.EMPTY);
61          factory.setAttribute(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
62          factory.setExpandEntityReferences(false);
63          var builder = factory.newDocumentBuilder();
64          return builder.parse(new InputSource(new StringReader(xmlStr)));
65      }
66  
67      public boolean isTextNodeInjectable(Document doc, Node node) {
68          var nodeList = node.getChildNodes();
69          for (var i = 0 ; i < nodeList.getLength() ; i++) {
70              var currentNode = nodeList.item(i);
71              if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
72                  if (this.isTextNodeInjectable(doc, currentNode)) {  // calls this method for all the children which is Element
73                      return true;
74                  }
75              } else if (currentNode.getNodeType() == Node.TEXT_NODE) {
76                  
77                  SoapUtil.removeInjectionPoint(doc, doc.getDocumentElement());
78                  currentNode.setTextContent(currentNode.getTextContent().replace(InjectionModel.STAR, StringUtils.EMPTY) + InjectionModel.STAR);
79                  this.injectionModel.getMediatorUtils().getParameterUtil().initRequest(SoapUtil.convertDocumentToString(doc));
80                  
81                  try {
82                      LOGGER.log(
83                          LogLevelUtil.CONSOLE_INFORM,
84                          "{} SOAP {}={}",
85                          () -> I18nUtil.valueByKey("LOG_CHECKING"),
86                          () -> currentNode.getParentNode().getNodeName(),
87                          () -> currentNode.getTextContent().replace(InjectionModel.STAR, StringUtils.EMPTY)
88                      );
89                      if (this.injectionModel.getMediatorMethod().getRequest().testParameters()) {
90                          return true;
91                      }
92                  } catch (JSqlException e) {
93                      // Injection failure
94                      LOGGER.log(
95                          LogLevelUtil.CONSOLE_ERROR,
96                          String.format(
97                              "No SOAP Request injection for %s=%s",
98                              currentNode.getParentNode().getNodeName(),
99                              currentNode.getTextContent().replace(InjectionModel.STAR, StringUtils.EMPTY)
100                         )
101                     );
102                 }
103             }
104         }
105         return false;
106     }
107 
108     public static void removeInjectionPoint(Document doc, Node node) {
109         var nodeList = node.getChildNodes();
110         for (var i = 0 ; i < nodeList.getLength() ; i++) {
111             var currentNode = nodeList.item(i);
112             if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
113                 SoapUtil.removeInjectionPoint(doc, currentNode);  // calls this method for all the children which is Element
114             } else if (currentNode.getNodeType() == Node.TEXT_NODE) {
115                 currentNode.setTextContent(
116                     currentNode
117                     .getTextContent()
118                     .replaceAll(Pattern.quote(InjectionModel.STAR) + "*$", StringUtils.EMPTY)
119                 );
120             }
121         }
122     }
123     
124     private static String convertDocumentToString(Document doc) {
125         var transformerFactory = TransformerFactory.newInstance();
126         transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, StringUtils.EMPTY);
127         transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, StringUtils.EMPTY);
128         
129         String output = null;
130         try {
131             var transformer = transformerFactory.newTransformer();
132             var writer = new StringWriter();
133             transformer.transform(new DOMSource(doc), new StreamResult(writer));
134             output = writer.getBuffer().toString();
135         } catch (TransformerException e) {
136             // ignore
137         }
138         return output;
139     }
140 }