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