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