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