TamperingUtil.java

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
Location : eval
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_12]
negated conditional → KILLED

67

1.1
Location : eval
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_12]
replaced return value with "" for com/jsql/util/TamperingUtil::eval → KILLED

79

1.1
Location : tamper
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_13]
negated conditional → KILLED

84

1.1
Location : tamper
Killed by : none
replaced return value with "" for com/jsql/util/TamperingUtil::tamper → NO_COVERAGE

87

1.1
Location : tamper
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_14]
negated conditional → KILLED

104

1.1
Location : tamper
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_13]
negated conditional → KILLED

111

1.1
Location : tamper
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_12]
negated conditional → KILLED

113

1.1
Location : tamper
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_12]
negated conditional → KILLED

115

1.1
Location : tamper
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_12]
negated conditional → KILLED

121

1.1
Location : tamper
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_13]
replaced return value with "" for com/jsql/util/TamperingUtil::tamper → KILLED

125

1.1
Location : transform
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_13]
negated conditional → KILLED

126

1.1
Location : transform
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_3]
replaced return value with "" for com/jsql/util/TamperingUtil::transform → KILLED

128

1.1
Location : transform
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_13]
replaced return value with "" for com/jsql/util/TamperingUtil::transform → KILLED

136

1.1
Location : withBase64
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withBase64 → SURVIVED
Covering tests

141

1.1
Location : withVersionComment
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_8]
replaced return value with null for com/jsql/util/TamperingUtil::withVersionComment → KILLED

146

1.1
Location : withFunctionComment
Killed by : TamperingUtilSpock.[engine:spock]/[spec:TamperingUtilSpock]/[feature:$spock_feature_0_9]
replaced return value with null for com/jsql/util/TamperingUtil::withFunctionComment → KILLED

151

1.1
Location : withEqualToLike
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withEqualToLike → SURVIVED
Covering tests

156

1.1
Location : withRandomCase
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withRandomCase → SURVIVED
Covering tests

161

1.1
Location : withHexToChar
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withHexToChar → SURVIVED
Covering tests

166

1.1
Location : withStringToChar
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withStringToChar → SURVIVED
Covering tests

171

1.1
Location : withQuoteToUtf8
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withQuoteToUtf8 → SURVIVED
Covering tests

176

1.1
Location : withEval
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withEval → SURVIVED
Covering tests

181

1.1
Location : withSpaceToMultilineComment
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withSpaceToMultilineComment → SURVIVED
Covering tests

186

1.1
Location : withSpaceToDashComment
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withSpaceToDashComment → SURVIVED
Covering tests

191

1.1
Location : withSpaceToSharpComment
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withSpaceToSharpComment → SURVIVED
Covering tests

198

1.1
Location : getCustomTamper
Killed by : none
replaced return value with "" for com/jsql/util/TamperingUtil::getCustomTamper → NO_COVERAGE

207

1.1
Location : withBase64
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withBase64 → NO_COVERAGE

212

1.1
Location : withEqualToLike
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withEqualToLike → NO_COVERAGE

217

1.1
Location : withEval
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withEval → NO_COVERAGE

222

1.1
Location : withFunctionComment
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withFunctionComment → NO_COVERAGE

227

1.1
Location : withHexToChar
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withHexToChar → NO_COVERAGE

232

1.1
Location : withQuoteToUtf8
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withQuoteToUtf8 → NO_COVERAGE

237

1.1
Location : withRandomCase
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withRandomCase → NO_COVERAGE

242

1.1
Location : withSpaceToDashComment
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withSpaceToDashComment → NO_COVERAGE

247

1.1
Location : withSpaceToMultilineComment
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withSpaceToMultilineComment → NO_COVERAGE

252

1.1
Location : withSpaceToSharpComment
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withSpaceToSharpComment → NO_COVERAGE

257

1.1
Location : withStringToChar
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withStringToChar → NO_COVERAGE

262

1.1
Location : withVersionComment
Killed by : none
replaced return value with null for com/jsql/util/TamperingUtil::withVersionComment → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.19.1