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
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 }