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)) {
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
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);
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
137 }
138 return output;
139 }
140 }