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 | * Log4j logger sent to view. | |
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 |
1
1. eval : negated conditional → KILLED |
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 |
1
1. eval : replaced return value with "" for com/jsql/util/TamperingUtil::eval → KILLED |
return resultSqlTampered.toString(); |
77 | } | |
78 | ||
79 | public String tamper(String sqlQueryDefault) { | |
80 | ||
81 | String lead; | |
82 | String sqlQuery; | |
83 | String trail; | |
84 | ||
85 | // Transform only SQL query without HTTP parameters and syntax changed, like p=1'+[sql] | |
86 | String regexToMatchTamperTags = String.format("(?s)(.*%s)(.*)(%s.*)", TAG_OPENED, TAG_CLOSED); | |
87 | var matcherSql = Pattern.compile(regexToMatchTamperTags).matcher(sqlQueryDefault); | |
88 | ||
89 |
1
1. tamper : negated conditional → KILLED |
if (matcherSql.find()) { |
90 | ||
91 | lead = matcherSql.group(1); | |
92 | sqlQuery = matcherSql.group(2); | |
93 | trail = matcherSql.group(3); | |
94 | ||
95 | } else { | |
96 |
1
1. tamper : replaced return value with "" for com/jsql/util/TamperingUtil::tamper → NO_COVERAGE |
return sqlQueryDefault; |
97 | } | |
98 | ||
99 |
1
1. tamper : negated conditional → KILLED |
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 | // Empty when checking character insertion | |
116 |
1
1. tamper : negated conditional → KILLED |
if (StringUtils.isEmpty(sqlQuery)) { |
117 | return StringUtils.EMPTY; | |
118 | } | |
119 | ||
120 | // Transform all query, SQL and HTTP | |
121 | ||
122 | // Dependency to: EQUAL_TO_LIKE | |
123 |
1
1. tamper : negated conditional → KILLED |
if (this.isSpaceToDashComment) { |
124 | sqlQuery = eval(sqlQuery, TamperingType.SPACE_TO_DASH_COMMENT.instance().getJavascript()); | |
125 |
1
1. tamper : negated conditional → KILLED |
} else if (this.isSpaceToMultilineComment) { |
126 | sqlQuery = eval(sqlQuery, TamperingType.SPACE_TO_MULTILINE_COMMENT.instance().getJavascript()); | |
127 |
1
1. tamper : negated conditional → KILLED |
} 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); // char insertion included | |
133 | ||
134 |
1
1. tamper : replaced return value with "" for com/jsql/util/TamperingUtil::tamper → KILLED |
return sqlQuery; |
135 | } | |
136 | ||
137 | private String transform(String sqlQuery, boolean shouldApply, TamperingType tamperingType) { | |
138 | ||
139 |
1
1. transform : negated conditional → KILLED |
if (shouldApply) { |
140 |
1
1. transform : replaced return value with "" for com/jsql/util/TamperingUtil::transform → KILLED |
return eval(sqlQuery, tamperingType.instance().getJavascript()); |
141 | } | |
142 | ||
143 |
1
1. transform : replaced return value with "" for com/jsql/util/TamperingUtil::transform → KILLED |
return sqlQuery; |
144 | } | |
145 | ||
146 | ||
147 | // Builder | |
148 | ||
149 | public TamperingUtil withBase64() { | |
150 | this.isBase64 = true; | |
151 |
1
1. withBase64 : replaced return value with null for com/jsql/util/TamperingUtil::withBase64 → SURVIVED |
return this; |
152 | } | |
153 | ||
154 | public TamperingUtil withVersionComment() { | |
155 | this.isVersionComment = true; | |
156 |
1
1. withVersionComment : replaced return value with null for com/jsql/util/TamperingUtil::withVersionComment → KILLED |
return this; |
157 | } | |
158 | ||
159 | public TamperingUtil withFunctionComment() { | |
160 | this.isFunctionComment = true; | |
161 |
1
1. withFunctionComment : replaced return value with null for com/jsql/util/TamperingUtil::withFunctionComment → KILLED |
return this; |
162 | } | |
163 | ||
164 | public TamperingUtil withEqualToLike() { | |
165 | this.isEqualToLike = true; | |
166 |
1
1. withEqualToLike : replaced return value with null for com/jsql/util/TamperingUtil::withEqualToLike → SURVIVED |
return this; |
167 | } | |
168 | ||
169 | public TamperingUtil withRandomCase() { | |
170 | this.isRandomCase = true; | |
171 |
1
1. withRandomCase : replaced return value with null for com/jsql/util/TamperingUtil::withRandomCase → SURVIVED |
return this; |
172 | } | |
173 | ||
174 | public TamperingUtil withHexToChar() { | |
175 | this.isHexToChar = true; | |
176 |
1
1. withHexToChar : replaced return value with null for com/jsql/util/TamperingUtil::withHexToChar → SURVIVED |
return this; |
177 | } | |
178 | ||
179 | public TamperingUtil withStringToChar() { | |
180 | this.isStringToChar = true; | |
181 |
1
1. withStringToChar : replaced return value with null for com/jsql/util/TamperingUtil::withStringToChar → SURVIVED |
return this; |
182 | } | |
183 | ||
184 | public TamperingUtil withQuoteToUtf8() { | |
185 | this.isQuoteToUtf8 = true; | |
186 |
1
1. withQuoteToUtf8 : replaced return value with null for com/jsql/util/TamperingUtil::withQuoteToUtf8 → SURVIVED |
return this; |
187 | } | |
188 | ||
189 | public TamperingUtil withEval() { | |
190 | this.isEval = true; | |
191 |
1
1. withEval : replaced return value with null for com/jsql/util/TamperingUtil::withEval → SURVIVED |
return this; |
192 | } | |
193 | ||
194 | public TamperingUtil withSpaceToMultilineComment() { | |
195 | this.isSpaceToMultilineComment = true; | |
196 |
1
1. withSpaceToMultilineComment : replaced return value with null for com/jsql/util/TamperingUtil::withSpaceToMultilineComment → SURVIVED |
return this; |
197 | } | |
198 | ||
199 | public TamperingUtil withSpaceToDashComment() { | |
200 | this.isSpaceToDashComment = true; | |
201 |
1
1. withSpaceToDashComment : replaced return value with null for com/jsql/util/TamperingUtil::withSpaceToDashComment → SURVIVED |
return this; |
202 | } | |
203 | ||
204 | public TamperingUtil withSpaceToSharpComment() { | |
205 | this.isSpaceToSharpComment = true; | |
206 |
1
1. withSpaceToSharpComment : replaced return value with null for com/jsql/util/TamperingUtil::withSpaceToSharpComment → SURVIVED |
return this; |
207 | } | |
208 | ||
209 | | |
210 | // Getter and setter | |
211 | ||
212 | public String getCustomTamper() { | |
213 |
1
1. getCustomTamper : replaced return value with "" for com/jsql/util/TamperingUtil::getCustomTamper → NO_COVERAGE |
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 |
1
1. withBase64 : replaced return value with null for com/jsql/util/TamperingUtil::withBase64 → NO_COVERAGE |
return this; |
223 | } | |
224 | ||
225 | public TamperingUtil withEqualToLike(boolean selected) { | |
226 | this.isEqualToLike = selected; | |
227 |
1
1. withEqualToLike : replaced return value with null for com/jsql/util/TamperingUtil::withEqualToLike → NO_COVERAGE |
return this; |
228 | } | |
229 | ||
230 | public TamperingUtil withEval(boolean selected) { | |
231 | this.isEval = selected; | |
232 |
1
1. withEval : replaced return value with null for com/jsql/util/TamperingUtil::withEval → NO_COVERAGE |
return this; |
233 | } | |
234 | ||
235 | public TamperingUtil withFunctionComment(boolean selected) { | |
236 | this.isFunctionComment = selected; | |
237 |
1
1. withFunctionComment : replaced return value with null for com/jsql/util/TamperingUtil::withFunctionComment → NO_COVERAGE |
return this; |
238 | } | |
239 | ||
240 | public TamperingUtil withHexToChar(boolean selected) { | |
241 | this.isHexToChar = selected; | |
242 |
1
1. withHexToChar : replaced return value with null for com/jsql/util/TamperingUtil::withHexToChar → NO_COVERAGE |
return this; |
243 | } | |
244 | ||
245 | public TamperingUtil withQuoteToUtf8(boolean selected) { | |
246 | this.isQuoteToUtf8 = selected; | |
247 |
1
1. withQuoteToUtf8 : replaced return value with null for com/jsql/util/TamperingUtil::withQuoteToUtf8 → NO_COVERAGE |
return this; |
248 | } | |
249 | ||
250 | public TamperingUtil withRandomCase(boolean selected) { | |
251 | this.isRandomCase = selected; | |
252 |
1
1. withRandomCase : replaced return value with null for com/jsql/util/TamperingUtil::withRandomCase → NO_COVERAGE |
return this; |
253 | } | |
254 | ||
255 | public TamperingUtil withSpaceToDashComment(boolean selected) { | |
256 | this.isSpaceToDashComment = selected; | |
257 |
1
1. withSpaceToDashComment : replaced return value with null for com/jsql/util/TamperingUtil::withSpaceToDashComment → NO_COVERAGE |
return this; |
258 | } | |
259 | ||
260 | public TamperingUtil withSpaceToMultilineComment(boolean selected) { | |
261 | this.isSpaceToMultilineComment = selected; | |
262 |
1
1. withSpaceToMultilineComment : replaced return value with null for com/jsql/util/TamperingUtil::withSpaceToMultilineComment → NO_COVERAGE |
return this; |
263 | } | |
264 | ||
265 | public TamperingUtil withSpaceToSharpComment(boolean selected) { | |
266 | this.isSpaceToSharpComment = selected; | |
267 |
1
1. withSpaceToSharpComment : replaced return value with null for com/jsql/util/TamperingUtil::withSpaceToSharpComment → NO_COVERAGE |
return this; |
268 | } | |
269 | ||
270 | public TamperingUtil withStringToChar(boolean selected) { | |
271 | this.isStringToChar = selected; | |
272 |
1
1. withStringToChar : replaced return value with null for com/jsql/util/TamperingUtil::withStringToChar → NO_COVERAGE |
return this; |
273 | } | |
274 | ||
275 | public TamperingUtil withVersionComment(boolean selected) { | |
276 | this.isVersionComment = selected; | |
277 |
1
1. withVersionComment : replaced return value with null for com/jsql/util/TamperingUtil::withVersionComment → NO_COVERAGE |
return this; |
278 | } | |
279 | } | |
Mutations | ||
46 |
1.1 |
|
76 |
1.1 |
|
89 |
1.1 |
|
96 |
1.1 |
|
99 |
1.1 |
|
116 |
1.1 |
|
123 |
1.1 |
|
125 |
1.1 |
|
127 |
1.1 |
|
134 |
1.1 |
|
139 |
1.1 |
|
140 |
1.1 |
|
143 |
1.1 |
|
151 |
1.1 |
|
156 |
1.1 |
|
161 |
1.1 |
|
166 |
1.1 |
|
171 |
1.1 |
|
176 |
1.1 |
|
181 |
1.1 |
|
186 |
1.1 |
|
191 |
1.1 |
|
196 |
1.1 |
|
201 |
1.1 |
|
206 |
1.1 |
|
213 |
1.1 |
|
222 |
1.1 |
|
227 |
1.1 |
|
232 |
1.1 |
|
237 |
1.1 |
|
242 |
1.1 |
|
247 |
1.1 |
|
252 |
1.1 |
|
257 |
1.1 |
|
262 |
1.1 |
|
267 |
1.1 |
|
272 |
1.1 |
|
277 |
1.1 |