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