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   
9   import java.util.regex.Matcher;
10  import java.util.regex.Pattern;
11  
12  public class MultipartUtil {
13  
14      /**
15       * Log4j logger sent to view.
16       */
17      private static final Logger LOGGER = LogManager.getRootLogger();
18  
19      private final InjectionModel injectionModel;
20  
21      public MultipartUtil(InjectionModel injectionModel) {
22          this.injectionModel = injectionModel;
23      }
24  
25      public boolean testParameters(boolean hasFoundInjection) {
26  
27          if (!hasFoundInjection) {
28              LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Checking multipart params...");
29          } else {
30              return true;
31          }
32          
33          String rawHeader = this.injectionModel.getMediatorUtils().getParameterUtil().getRawHeader();
34          String rawRequest = this.injectionModel.getMediatorUtils().getParameterUtil().getRawRequest();
35  
36          Matcher matcherBoundary = Pattern.compile("boundary=([^;]*)").matcher(rawHeader);
37  
38          if (!matcherBoundary.find()) {
39              return false;
40          }
41          
42          String boundary = matcherBoundary.group(1);
43  
44          Matcher matcherFormDataParameters = Pattern
45              .compile("Content-Disposition\\s*:\\s*form-data\\s*;\\s*name\\s*=\"(.*?)\"(.*?)--" + boundary, Pattern.DOTALL)
46              .matcher(rawRequest);
47  
48          while (matcherFormDataParameters.find()) {
49              if (isBoundaryInjectable(rawRequest, boundary, matcherFormDataParameters)) {
50                  return true;
51              }
52          }
53  
54          return false;
55      }
56  
57      private boolean isBoundaryInjectable(String rawRequest, String boundary, Matcher matcherFormDataParameters) {
58  
59          String nameParameter = matcherFormDataParameters.group(1);
60          String valueParameter = matcherFormDataParameters.group(2);
61  
62          String rawRequestWithStar = rawRequest.replaceAll(
63              "(?i)(Content-Disposition\\s*:\\s*form-data\\s*;\\s*name\\s*=\\s*\"" + nameParameter + "\".*?)([\\\\r\\\\n]*--" + boundary + ")",
64              "$1" + InjectionModel.STAR + "$2"
65          );
66  
67          this.injectionModel.getMediatorUtils().getParameterUtil().initializeRequest(rawRequestWithStar);
68  
69          try {
70              LOGGER.log(
71                  LogLevelUtil.CONSOLE_INFORM,
72                  "Checking Multipart boundary injection for {}={}",
73                  () -> nameParameter,
74                  () -> valueParameter.replace(InjectionModel.STAR, StringUtils.EMPTY)
75              );
76  
77              return this.injectionModel.getMediatorMethod().getRequest().testParameters();
78  
79          } catch (JSqlException e) {
80              LOGGER.log(
81                  LogLevelUtil.CONSOLE_ERROR,
82                  String.format(
83                      "No Multipart boundary injection for %s=%s",
84                      nameParameter,
85                      valueParameter.replace(InjectionModel.STAR, StringUtils.EMPTY)
86                  )
87              );
88          }
89  
90          return false;
91      }
92  }