AbstractMethodInjection.java

1
package com.jsql.model.injection.method;
2
3
import com.jsql.model.InjectionModel;
4
import com.jsql.model.exception.JSqlException;
5
import com.jsql.model.exception.StoppedByUserSlidingException;
6
import com.jsql.util.JsonUtil;
7
import com.jsql.util.LogLevelUtil;
8
import org.apache.commons.lang3.StringUtils;
9
import org.apache.logging.log4j.LogManager;
10
import org.apache.logging.log4j.Logger;
11
import org.json.JSONException;
12
13
import java.io.Serializable;
14
import java.util.AbstractMap.SimpleEntry;
15
import java.util.List;
16
import java.util.regex.Pattern;
17
18
public abstract class AbstractMethodInjection implements Serializable {
19
    
20
    /**
21
     * Log4j logger sent to view.
22
     */
23
    private static final Logger LOGGER = LogManager.getRootLogger();
24
    
25
    protected final InjectionModel injectionModel;
26
    
27
    protected AbstractMethodInjection(InjectionModel injectionModel) {
28
        this.injectionModel = injectionModel;
29
    }
30
    
31
    public abstract boolean isCheckingAllParam();
32
    public abstract String getParamsAsString();
33
    public abstract List<SimpleEntry<String, String>> getParams();
34
    public abstract String name();
35
    
36
    public boolean testParameters(boolean hasFoundInjection) throws JSqlException {
37
38 1 1. testParameters : negated conditional → NO_COVERAGE
        if (!hasFoundInjection) {
39
40
            LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Checking {} params...", () -> name().toLowerCase());
41 2 1. testParameters : replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::testParameters → NO_COVERAGE
2. testParameters : replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::testParameters → NO_COVERAGE
            return this.testParameters();
42
        }
43
44 1 1. testParameters : replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::testParameters → NO_COVERAGE
        return true;
45
    }
46
47
    /**
48
     * Verify if injection works for specific Method using 3 modes: standard (last param), injection point
49
     * and full params injection. Special injections like JSON and SOAP are checked.
50
     * @return true if injection didn't fail
51
     * @throws JSqlException when no params' integrity, process stopped by user, or injection failure
52
     */
53
    public boolean testParameters() throws JSqlException {
54
55
        var hasFoundInjection = false;
56
        
57
        // Injects URL, Request or Header params only if user tests every params
58
        // or method is selected by user.
59
        if (
60 1 1. testParameters : negated conditional → NO_COVERAGE
            !this.injectionModel.getMediatorUtils().getPreferencesUtil().isCheckingAllParam()
61 1 1. testParameters : negated conditional → NO_COVERAGE
            && this.injectionModel.getMediatorUtils().getConnectionUtil().getMethodInjection() != this
62
        ) {
63 1 1. testParameters : replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::testParameters → NO_COVERAGE
            return false;
64
        }
65
        
66
        // Force injection method of model to current running method
67 1 1. testParameters : removed call to com/jsql/util/ConnectionUtil::setMethodInjection → NO_COVERAGE
        this.injectionModel.getMediatorUtils().getConnectionUtil().setMethodInjection(this);
68
        
69
        // Injection by injection point in params or in path
70
        if (
71 1 1. testParameters : negated conditional → NO_COVERAGE
            this.getParamsAsString().contains(InjectionModel.STAR)
72 1 1. testParameters : negated conditional → NO_COVERAGE
            || this.injectionModel.getMediatorUtils().getConnectionUtil().getUrlBase().contains(InjectionModel.STAR)
73
        ) {
74
            hasFoundInjection = this.checkParamWithStar();
75 1 1. testParameters : negated conditional → NO_COVERAGE
        } else if (!this.isCheckingAllParam()) {
76
            hasFoundInjection = this.checkLastParam();
77
        } else {
78
            hasFoundInjection = this.checkAllParams();
79
        }
80
        
81 2 1. testParameters : replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::testParameters → NO_COVERAGE
2. testParameters : replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::testParameters → NO_COVERAGE
        return hasFoundInjection;
82
    }
83
84
    private boolean checkParamWithStar() throws JSqlException {
85
        
86
        SimpleEntry<String, String> parameterToInject = this.getParams().stream()
87 2 1. lambda$checkParamWithStar$1 : replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::lambda$checkParamWithStar$1 → NO_COVERAGE
2. lambda$checkParamWithStar$1 : replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::lambda$checkParamWithStar$1 → NO_COVERAGE
            .filter(entry -> entry.getValue().contains("*"))
88
            .findFirst()
89
            .orElse(null);
90
91 2 1. checkParamWithStar : replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::checkParamWithStar → NO_COVERAGE
2. checkParamWithStar : replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::checkParamWithStar → NO_COVERAGE
        return this.injectionModel.getMediatorStrategy().testStrategies(parameterToInject);
92
    }
93
94
    /**
95
     *  Default injection: last param tested only
96
     */
97
    private boolean checkLastParam() throws JSqlException {
98
        
99
        // Will check param value by user.
100
        // Notice options 'Inject each URL params' and 'inject JSON' must be checked both
101
        // for JSON injection of last param
102
        SimpleEntry<String, String> parameterToInject = this.getParams().stream()
103 1 1. lambda$checkLastParam$2 : replaced return value with null for com/jsql/model/injection/method/AbstractMethodInjection::lambda$checkLastParam$2 → NO_COVERAGE
            .reduce((a, b) -> b)
104
            .orElseThrow(NullPointerException::new);
105
106 2 1. checkLastParam : replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::checkLastParam → NO_COVERAGE
2. checkLastParam : replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::checkLastParam → NO_COVERAGE
        return this.injectionModel.getMediatorStrategy().testStrategies(parameterToInject);
107
    }
108
109
    /**
110
     * Injection of every params: isCheckingAllParam() == true.
111
     * Params are tested one by one in two loops:
112
     * - inner loop erases * from previous param
113
     * - outer loop adds * to current param
114
     * @throws StoppedByUserSlidingException
115
     */
116
    private boolean checkAllParams() throws StoppedByUserSlidingException {
117
        
118
        // This param will be marked by * if injection is found,
119
        // inner loop will erase mark * otherwise
120
        for (SimpleEntry<String, String> paramBase: this.getParams()) {
121
            // This param is the current tested one.
122
            // For JSON value attributes are traversed one by one to test every values.
123
            // For standard value mark * is simply added to the end of its value.
124
            for (SimpleEntry<String, String> paramStar: this.getParams()) {
125 1 1. checkAllParams : negated conditional → NO_COVERAGE
                if (paramStar == paramBase) {
126
                    try {
127 1 1. checkAllParams : negated conditional → NO_COVERAGE
                        if (this.isParamInjectable(paramStar)) {
128 1 1. checkAllParams : replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::checkAllParams → NO_COVERAGE
                            return true;
129
                        }
130
                    } catch (JSONException e) {
131
                        LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
132
                    }
133
                }
134
            }
135
        }
136
    
137 1 1. checkAllParams : replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::checkAllParams → NO_COVERAGE
        return false;
138
    }
139
140
    private boolean isParamInjectable(SimpleEntry<String, String> paramStar) throws StoppedByUserSlidingException {
141
        
142
        boolean hasFoundInjection;
143
        
144
        // Will test if current value is a JSON entity
145
        Object jsonEntity = JsonUtil.getJson(paramStar.getValue());
146
        
147
        // Define a tree of JSON attributes with path as the key: root.a => value of a
148
        List<SimpleEntry<String, String>> attributesJson = JsonUtil.createEntries(jsonEntity, "root", null);
149
        
150
        // When option 'Inject JSON' is selected and there's a JSON entity to inject
151
        // then loop through each paths to add * at the end of value and test each strategies.
152
        // Marks * are erased between each tests.
153 2 1. isParamInjectable : negated conditional → NO_COVERAGE
2. isParamInjectable : negated conditional → NO_COVERAGE
        if (!attributesJson.isEmpty() && this.injectionModel.getMediatorUtils().getPreferencesUtil().isCheckingAllJsonParam()) {
154
            hasFoundInjection = this.injectionModel.getMediatorUtils().getJsonUtil().testJsonParam(this, paramStar);
155
        } else {
156
            hasFoundInjection = this.testJsonlessParam(paramStar);  // Standard non JSON injection
157
        }
158
        
159 2 1. isParamInjectable : replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::isParamInjectable → NO_COVERAGE
2. isParamInjectable : replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::isParamInjectable → NO_COVERAGE
        return hasFoundInjection;
160
    }
161
    
162
    public boolean testJsonlessParam(SimpleEntry<String, String> paramStar) throws StoppedByUserSlidingException {
163
164
        var hasFoundInjection = false;
165
166
        paramStar.setValue(paramStar.getValue() + InjectionModel.STAR);
167
        
168
        try {
169
            LOGGER.log(
170
                LogLevelUtil.CONSOLE_INFORM,
171
                "Checking {} parameter {}={}",
172
                this::name,
173
                paramStar::getKey,
174 1 1. lambda$testJsonlessParam$3 : replaced return value with null for com/jsql/model/injection/method/AbstractMethodInjection::lambda$testJsonlessParam$3 → NO_COVERAGE
                () -> paramStar.getValue().replace(InjectionModel.STAR, StringUtils.EMPTY)
175
            );
176
            
177
            // Test current standard value marked with * for injection
178
            // Keep original param
179
            hasFoundInjection = this.injectionModel.getMediatorStrategy().testStrategies(paramStar);
180
            
181
        } catch (StoppedByUserSlidingException e) { // Break all params processing in upper methods
182
            throw e;
183
        } catch (JSqlException e) {  // Injection failure
184
            LOGGER.log(
185
                LogLevelUtil.CONSOLE_ERROR,
186
                "No {} injection found for parameter {}={} ({})",
187
                this.name(),
188
                paramStar.getKey(),
189
                paramStar.getValue().replaceAll("\\+.?$|\\" + InjectionModel.STAR, StringUtils.EMPTY),
190
                e.getMessage()
191
            );
192
        } finally {
193 1 1. testJsonlessParam : negated conditional → NO_COVERAGE
            if (!hasFoundInjection) {  // Erase * from JSON if failure
194
                
195
                // Erase * at the end of each params
196 1 1. testJsonlessParam : removed call to java/util/List::forEach → NO_COVERAGE
                this.getParams().forEach(e ->
197
                    e.setValue(
198
                        e.getValue().replaceAll(Pattern.quote(InjectionModel.STAR) +"$", StringUtils.EMPTY)
199
                    )
200
                );
201
                
202
                // TODO It erases STAR from value => * can't be used in parameter
203
                paramStar.setValue(paramStar.getValue().replace(InjectionModel.STAR, StringUtils.EMPTY));
204
            }
205
        }
206
        
207 2 1. testJsonlessParam : replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::testJsonlessParam → NO_COVERAGE
2. testJsonlessParam : replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::testJsonlessParam → NO_COVERAGE
        return hasFoundInjection;
208
    }
209
}

Mutations

38

1.1
Location : testParameters
Killed by : none
negated conditional → NO_COVERAGE

41

1.1
Location : testParameters
Killed by : none
replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::testParameters → NO_COVERAGE

2.2
Location : testParameters
Killed by : none
replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::testParameters → NO_COVERAGE

44

1.1
Location : testParameters
Killed by : none
replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::testParameters → NO_COVERAGE

60

1.1
Location : testParameters
Killed by : none
negated conditional → NO_COVERAGE

61

1.1
Location : testParameters
Killed by : none
negated conditional → NO_COVERAGE

63

1.1
Location : testParameters
Killed by : none
replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::testParameters → NO_COVERAGE

67

1.1
Location : testParameters
Killed by : none
removed call to com/jsql/util/ConnectionUtil::setMethodInjection → NO_COVERAGE

71

1.1
Location : testParameters
Killed by : none
negated conditional → NO_COVERAGE

72

1.1
Location : testParameters
Killed by : none
negated conditional → NO_COVERAGE

75

1.1
Location : testParameters
Killed by : none
negated conditional → NO_COVERAGE

81

1.1
Location : testParameters
Killed by : none
replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::testParameters → NO_COVERAGE

2.2
Location : testParameters
Killed by : none
replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::testParameters → NO_COVERAGE

87

1.1
Location : lambda$checkParamWithStar$1
Killed by : none
replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::lambda$checkParamWithStar$1 → NO_COVERAGE

2.2
Location : lambda$checkParamWithStar$1
Killed by : none
replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::lambda$checkParamWithStar$1 → NO_COVERAGE

91

1.1
Location : checkParamWithStar
Killed by : none
replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::checkParamWithStar → NO_COVERAGE

2.2
Location : checkParamWithStar
Killed by : none
replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::checkParamWithStar → NO_COVERAGE

103

1.1
Location : lambda$checkLastParam$2
Killed by : none
replaced return value with null for com/jsql/model/injection/method/AbstractMethodInjection::lambda$checkLastParam$2 → NO_COVERAGE

106

1.1
Location : checkLastParam
Killed by : none
replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::checkLastParam → NO_COVERAGE

2.2
Location : checkLastParam
Killed by : none
replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::checkLastParam → NO_COVERAGE

125

1.1
Location : checkAllParams
Killed by : none
negated conditional → NO_COVERAGE

127

1.1
Location : checkAllParams
Killed by : none
negated conditional → NO_COVERAGE

128

1.1
Location : checkAllParams
Killed by : none
replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::checkAllParams → NO_COVERAGE

137

1.1
Location : checkAllParams
Killed by : none
replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::checkAllParams → NO_COVERAGE

153

1.1
Location : isParamInjectable
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : isParamInjectable
Killed by : none
negated conditional → NO_COVERAGE

159

1.1
Location : isParamInjectable
Killed by : none
replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::isParamInjectable → NO_COVERAGE

2.2
Location : isParamInjectable
Killed by : none
replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::isParamInjectable → NO_COVERAGE

174

1.1
Location : lambda$testJsonlessParam$3
Killed by : none
replaced return value with null for com/jsql/model/injection/method/AbstractMethodInjection::lambda$testJsonlessParam$3 → NO_COVERAGE

193

1.1
Location : testJsonlessParam
Killed by : none
negated conditional → NO_COVERAGE

196

1.1
Location : testJsonlessParam
Killed by : none
removed call to java/util/List::forEach → NO_COVERAGE

207

1.1
Location : testJsonlessParam
Killed by : none
replaced boolean return with true for com/jsql/model/injection/method/AbstractMethodInjection::testJsonlessParam → NO_COVERAGE

2.2
Location : testJsonlessParam
Killed by : none
replaced boolean return with false for com/jsql/model/injection/method/AbstractMethodInjection::testJsonlessParam → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.16.1