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