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

Mutations

35

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

39

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

40

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

42

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

59

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

60

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

62

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

66

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

70

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

71

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

74

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

79

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

84

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

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

87

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

98

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

99

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

100

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

117

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

119

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

120

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

128

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

143

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

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

148

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

160

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

163

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

182

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

185

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

195

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.19.1