View Javadoc
1   package com.jsql.model.injection.strategy;
2   
3   import com.jsql.model.InjectionModel;
4   import com.jsql.model.accessible.DataAccess;
5   import com.jsql.model.bean.util.Interaction;
6   import com.jsql.model.bean.util.Request;
7   import com.jsql.model.injection.vendor.model.VendorYaml;
8   import com.jsql.model.injection.vendor.model.yaml.Configuration;
9   import com.jsql.model.suspendable.AbstractSuspendable;
10  import com.jsql.util.I18nUtil;
11  import com.jsql.util.LogLevelUtil;
12  import com.jsql.util.StringUtil;
13  import org.apache.logging.log4j.LogManager;
14  import org.apache.logging.log4j.Logger;
15  
16  import java.util.regex.Matcher;
17  import java.util.regex.Pattern;
18  
19  public class StrategyInjectionStack extends AbstractStrategy {
20  
21      /**
22       * Log4j logger sent to view.
23       */
24      private static final Logger LOGGER = LogManager.getRootLogger();
25  
26      private String performanceLength = "0";
27  
28      public StrategyInjectionStack(InjectionModel injectionModel) {
29          super(injectionModel);
30      }
31  
32      @Override
33      public void checkApplicability() {
34          if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isStrategyStackDisabled()) {
35              LOGGER.log(LogLevelUtil.CONSOLE_INFORM, AbstractStrategy.FORMAT_SKIP_STRATEGY_DISABLED, this.getName());
36              return;
37          }
38  
39          // Reset applicability of new Vendor
40          this.isApplicable = false;
41          var strategyYaml = this.injectionModel.getMediatorVendor().getVendor().instance().getModelYaml().getStrategy();
42          var configurationYaml = strategyYaml.getConfiguration();
43  
44          this.logChecking();
45  
46          boolean methodIsApplicable = this.isApplicable(configurationYaml, strategyYaml.getStack());
47          if (methodIsApplicable) {
48              Matcher regexSearch = this.getPerformance(configurationYaml, strategyYaml.getStack());
49              if (!regexSearch.find()) {
50                  LOGGER.log(
51                      LogLevelUtil.CONSOLE_ERROR,
52                      "{} {} but injectable size is incorrect",
53                      () -> I18nUtil.valueByKey("LOG_VULNERABLE"),
54                      () -> "Stack"
55                  );
56                  methodIsApplicable = false;
57              } else {
58                  this.performanceLength = String.valueOf(regexSearch.group(1).length());
59              }
60          }
61  
62          if (methodIsApplicable) {
63              LOGGER.log(
64                  LogLevelUtil.CONSOLE_SUCCESS,
65                  "{} Stack injection showing [{}] characters",
66                  () -> I18nUtil.valueByKey("LOG_VULNERABLE"),
67                  () -> this.performanceLength
68              );
69              this.allow();
70          } else {
71              this.unallow();
72          }
73      }
74  
75      private boolean isApplicable(Configuration configurationYaml, String stack) {
76          var methodIsApplicable = false;
77          var indexZeroToFind = "0";
78          String performanceSourcePage = this.injectionModel.injectWithoutIndex(
79              VendorYaml.replaceTags(
80                  stack
81                  .replace(VendorYaml.WINDOW, configurationYaml.getSlidingWindow())
82                  .replace(VendorYaml.INJECTION, configurationYaml.getFailsafe().replace(VendorYaml.INDICE,indexZeroToFind))
83                  .replace(VendorYaml.WINDOW_CHAR, "1")
84                  .replace(VendorYaml.CAPACITY, VendorYaml.DEFAULT_CAPACITY)
85              ),
86              "stack#confirm"
87          );
88          String regexIndexZero = String.format(VendorYaml.FORMAT_INDEX, indexZeroToFind);
89          if (performanceSourcePage.matches("(?s).*"+ regexIndexZero +".*")) {
90              methodIsApplicable = true;
91              this.isApplicable = true;
92          }
93          return methodIsApplicable;
94      }
95  
96      private Matcher getPerformance(Configuration configurationYaml, String stack) {
97          String performanceSourcePage = this.injectionModel.injectWithoutIndex(
98              VendorYaml.replaceTags(
99                  stack
100                 .replace(VendorYaml.WINDOW, configurationYaml.getSlidingWindow())
101                 .replace(VendorYaml.INJECTION, configurationYaml.getCalibrator())
102                 .replace(VendorYaml.WINDOW_CHAR, "1")
103                 .replace(VendorYaml.CAPACITY, VendorYaml.DEFAULT_CAPACITY)
104             ),
105             "stack#size"
106         );
107         return Pattern.compile("(?s)"+ DataAccess.LEAD +"("+ VendorYaml.CALIBRATOR_SQL +"+)").matcher(performanceSourcePage);
108     }
109 
110     @Override
111     public void allow(int... i) {
112         this.injectionModel.appendAnalysisReport(
113             StringUtil.formatReport(LogLevelUtil.COLOR_BLU, "### Strategy: " + this.getName())
114             + this.injectionModel.getReportWithoutIndex(
115                 this.injectionModel.getMediatorVendor().getVendor().instance().sqlStack(StringUtil.formatReport(LogLevelUtil.COLOR_GREEN, "<query>"), "0", true),
116                 "metadataInjectionProcess"
117             )
118         );
119         this.markVulnerability(Interaction.MARK_STACK_VULNERABLE);
120     }
121 
122     @Override
123     public void unallow(int... i) {
124         this.markVulnerability(Interaction.MARK_STACK_INVULNERABLE);
125     }
126 
127     @Override
128     public String inject(String sqlQuery, String startPosition, AbstractSuspendable stoppable, String metadataInjectionProcess) {
129         return this.injectionModel.injectWithoutIndex(
130             this.injectionModel.getMediatorVendor().getVendor().instance().sqlStack(sqlQuery, startPosition, false),
131             metadataInjectionProcess
132         );
133     }
134 
135     @Override
136     public void activateWhenApplicable() {
137         if (this.injectionModel.getMediatorStrategy().getStrategy() == null && this.isApplicable()) {
138             LOGGER.log(
139                 LogLevelUtil.CONSOLE_INFORM,
140                 "{} [{}]",
141                 () -> I18nUtil.valueByKey("LOG_USING_STRATEGY"),
142                 this::getName
143             );
144             this.injectionModel.getMediatorStrategy().setStrategy(this.injectionModel.getMediatorStrategy().getStack());
145 
146             var request = new Request();
147             request.setMessage(Interaction.MARK_STACK_STRATEGY);
148             this.injectionModel.sendToViews(request);
149         }
150     }
151 
152     @Override
153     public String getPerformanceLength() {
154         return this.performanceLength;
155     }
156 
157     @Override
158     public String getName() {
159         return "Stack";
160     }
161 }