1 package com.jsql.util;
2
3 import com.jsql.util.tampering.TamperingType;
4 import org.apache.commons.lang3.StringUtils;
5 import org.apache.logging.log4j.LogManager;
6 import org.apache.logging.log4j.Logger;
7
8 import javax.script.Invocable;
9 import javax.script.ScriptEngine;
10 import javax.script.ScriptEngineManager;
11 import javax.script.ScriptException;
12 import java.util.regex.Pattern;
13
14 public class TamperingUtil {
15
16
17
18
19 private static final Logger LOGGER = LogManager.getRootLogger();
20
21 public static final String TAG_OPENED = "<tampering>";
22 public static final String TAG_CLOSED = "</tampering>";
23
24 private boolean isBase64 = false;
25 private boolean isVersionComment = false;
26 private boolean isFunctionComment = false;
27 private boolean isEqualToLike = false;
28 private boolean isRandomCase = false;
29 private boolean isHexToChar = false;
30 private boolean isStringToChar = false;
31 private boolean isQuoteToUtf8 = false;
32 private boolean isEval = false;
33 private boolean isSpaceToMultilineComment = false;
34 private boolean isSpaceToDashComment = false;
35 private boolean isSpaceToSharpComment = false;
36
37 private String customTamper = null;
38
39 private static final ScriptEngineManager SCRIPT_ENGINE_MANAGER = new ScriptEngineManager();
40
41 private static String eval(String sqlQuery, String jsTampering) {
42
43 Object resultSqlTampered;
44
45 try {
46 if (StringUtils.isEmpty(jsTampering)) {
47 throw new ScriptException("Tampering context is empty");
48 }
49
50 ScriptEngine nashornEngine = SCRIPT_ENGINE_MANAGER.getEngineByName("nashorn");
51 nashornEngine.eval(jsTampering);
52
53 var nashornInvocable = (Invocable) nashornEngine;
54 resultSqlTampered = nashornInvocable.invokeFunction("tampering", sqlQuery);
55
56 } catch (ScriptException e) {
57
58 LOGGER.log(
59 LogLevelUtil.CONSOLE_ERROR,
60 String.format("Tampering context contains errors: %s", e.getMessage()),
61 e
62 );
63 resultSqlTampered = sqlQuery;
64
65 } catch (NoSuchMethodException e) {
66
67 LOGGER.log(
68 LogLevelUtil.CONSOLE_ERROR,
69 String.format("Tampering context is not properly defined: %s", e.getMessage()),
70 e
71 );
72 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Minimal tampering context is: var tampering = function(sql) {return sql}");
73 resultSqlTampered = sqlQuery;
74 }
75
76 return resultSqlTampered.toString();
77 }
78
79 public String tamper(String sqlQueryDefault) {
80
81 String lead;
82 String sqlQuery;
83 String trail;
84
85
86 String regexToMatchTamperTags = String.format("(?s)(.*%s)(.*)(%s.*)", TAG_OPENED, TAG_CLOSED);
87 var matcherSql = Pattern.compile(regexToMatchTamperTags).matcher(sqlQueryDefault);
88
89 if (matcherSql.find()) {
90
91 lead = matcherSql.group(1);
92 sqlQuery = matcherSql.group(2);
93 trail = matcherSql.group(3);
94
95 } else {
96 return sqlQueryDefault;
97 }
98
99 if (this.isEval) {
100 sqlQuery = eval(sqlQuery, this.customTamper);
101 }
102
103 sqlQuery = transform(sqlQuery, this.isHexToChar, TamperingType.HEX_TO_CHAR);
104 sqlQuery = transform(sqlQuery, this.isStringToChar, TamperingType.STRING_TO_CHAR);
105 sqlQuery = transform(sqlQuery, this.isFunctionComment, TamperingType.COMMENT_TO_METHOD_SIGNATURE);
106 sqlQuery = transform(sqlQuery, this.isVersionComment, TamperingType.VERSIONED_COMMENT_TO_METHOD_SIGNATURE);
107 sqlQuery = transform(sqlQuery, this.isRandomCase, TamperingType.RANDOM_CASE);
108 sqlQuery = transform(sqlQuery, this.isEqualToLike, TamperingType.EQUAL_TO_LIKE);
109
110 sqlQuery = lead + sqlQuery + trail;
111
112 String regexToremoveTamperTags = String.format("(?i)%s|%s", TAG_OPENED, TAG_CLOSED);
113 sqlQuery = sqlQuery.replaceAll(regexToremoveTamperTags, StringUtils.EMPTY);
114
115
116 if (StringUtils.isEmpty(sqlQuery)) {
117 return StringUtils.EMPTY;
118 }
119
120
121
122
123 if (this.isSpaceToDashComment) {
124 sqlQuery = eval(sqlQuery, TamperingType.SPACE_TO_DASH_COMMENT.instance().getJavascript());
125 } else if (this.isSpaceToMultilineComment) {
126 sqlQuery = eval(sqlQuery, TamperingType.SPACE_TO_MULTILINE_COMMENT.instance().getJavascript());
127 } else if (this.isSpaceToSharpComment) {
128 sqlQuery = eval(sqlQuery, TamperingType.SPACE_TO_SHARP_COMMENT.instance().getJavascript());
129 }
130
131 sqlQuery = transform(sqlQuery, this.isBase64, TamperingType.BASE64);
132 sqlQuery = transform(sqlQuery, this.isQuoteToUtf8, TamperingType.QUOTE_TO_UTF8);
133
134 return sqlQuery;
135 }
136
137 private String transform(String sqlQuery, boolean shouldApply, TamperingType tamperingType) {
138
139 if (shouldApply) {
140 return eval(sqlQuery, tamperingType.instance().getJavascript());
141 }
142
143 return sqlQuery;
144 }
145
146
147
148
149 public TamperingUtil withBase64() {
150 this.isBase64 = true;
151 return this;
152 }
153
154 public TamperingUtil withVersionComment() {
155 this.isVersionComment = true;
156 return this;
157 }
158
159 public TamperingUtil withFunctionComment() {
160 this.isFunctionComment = true;
161 return this;
162 }
163
164 public TamperingUtil withEqualToLike() {
165 this.isEqualToLike = true;
166 return this;
167 }
168
169 public TamperingUtil withRandomCase() {
170 this.isRandomCase = true;
171 return this;
172 }
173
174 public TamperingUtil withHexToChar() {
175 this.isHexToChar = true;
176 return this;
177 }
178
179 public TamperingUtil withStringToChar() {
180 this.isStringToChar = true;
181 return this;
182 }
183
184 public TamperingUtil withQuoteToUtf8() {
185 this.isQuoteToUtf8 = true;
186 return this;
187 }
188
189 public TamperingUtil withEval() {
190 this.isEval = true;
191 return this;
192 }
193
194 public TamperingUtil withSpaceToMultilineComment() {
195 this.isSpaceToMultilineComment = true;
196 return this;
197 }
198
199 public TamperingUtil withSpaceToDashComment() {
200 this.isSpaceToDashComment = true;
201 return this;
202 }
203
204 public TamperingUtil withSpaceToSharpComment() {
205 this.isSpaceToSharpComment = true;
206 return this;
207 }
208
209
210
211
212 public String getCustomTamper() {
213 return this.customTamper;
214 }
215
216 public void setCustomTamper(String customTamper) {
217 this.customTamper = customTamper;
218 }
219
220 public TamperingUtil withBase64(boolean selected) {
221 this.isBase64 = selected;
222 return this;
223 }
224
225 public TamperingUtil withEqualToLike(boolean selected) {
226 this.isEqualToLike = selected;
227 return this;
228 }
229
230 public TamperingUtil withEval(boolean selected) {
231 this.isEval = selected;
232 return this;
233 }
234
235 public TamperingUtil withFunctionComment(boolean selected) {
236 this.isFunctionComment = selected;
237 return this;
238 }
239
240 public TamperingUtil withHexToChar(boolean selected) {
241 this.isHexToChar = selected;
242 return this;
243 }
244
245 public TamperingUtil withQuoteToUtf8(boolean selected) {
246 this.isQuoteToUtf8 = selected;
247 return this;
248 }
249
250 public TamperingUtil withRandomCase(boolean selected) {
251 this.isRandomCase = selected;
252 return this;
253 }
254
255 public TamperingUtil withSpaceToDashComment(boolean selected) {
256 this.isSpaceToDashComment = selected;
257 return this;
258 }
259
260 public TamperingUtil withSpaceToMultilineComment(boolean selected) {
261 this.isSpaceToMultilineComment = selected;
262 return this;
263 }
264
265 public TamperingUtil withSpaceToSharpComment(boolean selected) {
266 this.isSpaceToSharpComment = selected;
267 return this;
268 }
269
270 public TamperingUtil withStringToChar(boolean selected) {
271 this.isStringToChar = selected;
272 return this;
273 }
274
275 public TamperingUtil withVersionComment(boolean selected) {
276 this.isVersionComment = selected;
277 return this;
278 }
279 }