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