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
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
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
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
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
165 }
166
167 return output;
168 }
169 }