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      /**
28       * Log4j logger sent to view.
29       */
30      private static final Logger LOGGER = LogManager.getRootLogger();
31  
32      private final InjectionModel injectionModel;
33      
34      public SoapUtil(InjectionModel injectionModel) {
35          
36          this.injectionModel = injectionModel;
37      }
38  
39      public boolean testParameters(boolean hasFoundInjection) {
40  
41          if (!hasFoundInjection) {
42              LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Checking SOAP params...");
43          } else {
44              return true;
45          }
46  
47          if (
48              this.injectionModel.getMediatorUtils().getPreferencesUtil().isCheckingAllSoapParam()
49              && this.injectionModel.getMediatorUtils().getParameterUtil().isRequestSoap()
50          ) {
51              try {
52                  var doc = SoapUtil.convertToDocument(this.injectionModel.getMediatorUtils().getParameterUtil().getRawRequest());
53                  LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Parsing SOAP from Request...");
54                  
55                  return this.isTextNodeInjectable(doc, doc.getDocumentElement());
56                  
57              } catch (Exception e) {
58                  LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "SOAP not detected");
59              }
60          }
61          
62          return false;
63      }
64      
65      public static Document convertToDocument(String xmlStr) throws ParserConfigurationException, SAXException, IOException {
66          
67          var factory = DocumentBuilderFactory.newInstance();
68          
69          factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, StringUtils.EMPTY);
70          factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, StringUtils.EMPTY);
71          factory.setAttribute(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
72          factory.setExpandEntityReferences(false);
73  
74          var builder = factory.newDocumentBuilder();
75          
76          return builder.parse(new InputSource(new StringReader(xmlStr)));
77      }
78  
79      public boolean isTextNodeInjectable(Document doc, Node node) {
80          
81          var nodeList = node.getChildNodes();
82  
83          for (var i = 0; i < nodeList.getLength(); i++) {
84              
85              var currentNode = nodeList.item(i);
86              
87              if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
88                  //calls this method for all the children which is Element
89                  if (this.isTextNodeInjectable(doc, currentNode)) {
90                      return true;
91                  }
92              } else if (currentNode.getNodeType() == Node.TEXT_NODE) {
93                  
94                  SoapUtil.removeInjectionPoint(doc, doc.getDocumentElement());
95                  
96                  currentNode.setTextContent(currentNode.getTextContent().replace(InjectionModel.STAR, StringUtils.EMPTY) + InjectionModel.STAR);
97                  
98                  this.injectionModel.getMediatorUtils().getParameterUtil().initializeRequest(SoapUtil.convertDocumentToString(doc));
99                  
100                 try {
101                     LOGGER.log(
102                         LogLevelUtil.CONSOLE_INFORM,
103                         "Checking SOAP Request injection for {}={}",
104                         () -> currentNode.getParentNode().getNodeName(),
105                         () -> currentNode.getTextContent().replace(InjectionModel.STAR, StringUtils.EMPTY)
106                     );
107                     
108                     if (this.injectionModel.getMediatorMethod().getRequest().testParameters()) {
109                         return true;
110                     }
111                 } catch (JSqlException e) {
112                     // Injection failure
113                     LOGGER.log(
114                         LogLevelUtil.CONSOLE_ERROR,
115                         String.format(
116                             "No SOAP Request injection for %s=%s",
117                             currentNode.getParentNode().getNodeName(),
118                             currentNode.getTextContent().replace(InjectionModel.STAR, StringUtils.EMPTY)
119                         )
120                     );
121                 }
122             }
123         }
124         
125         return false;
126     }
127 
128     public static void removeInjectionPoint(Document doc, Node node) {
129         
130         var nodeList = node.getChildNodes();
131         
132         for (var i = 0; i < nodeList.getLength(); i++) {
133             
134             var currentNode = nodeList.item(i);
135             
136             if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
137                 //calls this method for all the children which is Element
138                 SoapUtil.removeInjectionPoint(doc, currentNode);
139             } else if (currentNode.getNodeType() == Node.TEXT_NODE) {
140                 currentNode.setTextContent(
141                     currentNode
142                     .getTextContent()
143                     .replaceAll(Pattern.quote(InjectionModel.STAR) + "*$", StringUtils.EMPTY)
144                 );
145             }
146         }
147     }
148     
149     private static String convertDocumentToString(Document doc) {
150         
151         var transformerFactory = TransformerFactory.newInstance();
152         transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, StringUtils.EMPTY);
153         transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, StringUtils.EMPTY);
154         
155         String output = null;
156         
157         try {
158             var transformer = transformerFactory.newTransformer();
159             var writer = new StringWriter();
160             transformer.transform(new DOMSource(doc), new StreamResult(writer));
161             output = writer.getBuffer().toString();
162             
163         } catch (TransformerException e) {
164             // ignore
165         }
166         
167         return output;
168     }
169 }