StrategyDns.java

1
/*******************************************************************************
2
 * Copyhacked (H) 2012-2025.
3
 * This program and the accompanying materials
4
 * are made available under no term at all, use it like
5
 * you want, but share and discuss it
6
 * every time possible with every body.
7
 *
8
 * Contributors:
9
 *      ron190 at ymail dot com - initial implementation
10
 *******************************************************************************/
11
package com.jsql.model.injection.strategy;
12
13
import com.jsql.model.InjectionModel;
14
import com.jsql.model.accessible.ResourceAccess;
15
import com.jsql.view.subscriber.Seal;
16
import com.jsql.model.injection.strategy.blind.AbstractInjectionBit.BlindOperator;
17
import com.jsql.model.injection.engine.model.EngineYaml;
18
import com.jsql.model.suspendable.AbstractSuspendable;
19
import com.jsql.util.I18nUtil;
20
import com.jsql.util.LogLevelUtil;
21
import com.jsql.util.StringUtil;
22
import org.apache.commons.lang3.StringUtils;
23
import org.apache.logging.log4j.LogManager;
24
import org.apache.logging.log4j.Logger;
25
26
import java.util.regex.Pattern;
27
28
public class StrategyDns extends AbstractStrategy {
29
30
    private static final Logger LOGGER = LogManager.getRootLogger();
31
    private BlindOperator blindOperator;
32
    private final DnsServer dnsServer;
33
34
    public StrategyDns(InjectionModel injectionModel) {
35
        super(injectionModel);
36
        this.dnsServer = new DnsServer(injectionModel);
37
    }
38
39
    @Override
40
    public void checkApplicability() {
41 1 1. checkApplicability : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().preferencesUtil().isStrategyDnsDisabled()) {
42
            LOGGER.log(LogLevelUtil.CONSOLE_INFORM, AbstractStrategy.FORMAT_SKIP_STRATEGY_DISABLED, this.getName());
43
            return;
44
        } else if (
45 1 1. checkApplicability : negated conditional → NO_COVERAGE
            StringUtils.isBlank(this.injectionModel.getMediatorUtils().preferencesUtil().getDnsDomain())
46 1 1. checkApplicability : negated conditional → NO_COVERAGE
            || !StringUtils.isNumeric(this.injectionModel.getMediatorUtils().preferencesUtil().getDnsPort())
47
        ) {
48
            LOGGER.log(
49
                LogLevelUtil.CONSOLE_INFORM,
50
                "Incorrect domain '{}' or port '{}', skipping Dns strategy",
51
                this.injectionModel.getMediatorUtils().preferencesUtil().getDnsDomain(),
52
                this.injectionModel.getMediatorUtils().preferencesUtil().getDnsPort()
53
            );
54
            return;
55
        } else if (
56 1 1. checkApplicability : negated conditional → NO_COVERAGE
            StringUtils.isEmpty(this.injectionModel.getMediatorEngine().getEngine().instance().getModelYaml().getStrategy().getDns())
57
        ) {
58
            LOGGER.log(
59
                LogLevelUtil.CONSOLE_INFORM,
60
                AbstractStrategy.FORMAT_STRATEGY_NOT_IMPLEMENTED,
61
                this.getName(),
62
                this.injectionModel.getMediatorEngine().getEngine()
63
            );
64
            return;
65
        }
66
67 1 1. checkApplicability : removed call to com/jsql/model/injection/strategy/StrategyDns::checkInjection → NO_COVERAGE
        this.checkInjection(BlindOperator.OR);
68 1 1. checkApplicability : removed call to com/jsql/model/injection/strategy/StrategyDns::checkInjection → NO_COVERAGE
        this.checkInjection(BlindOperator.AND);
69 1 1. checkApplicability : removed call to com/jsql/model/injection/strategy/StrategyDns::checkInjection → NO_COVERAGE
        this.checkInjection(BlindOperator.STACK);
70 1 1. checkApplicability : removed call to com/jsql/model/injection/strategy/StrategyDns::checkInjection → NO_COVERAGE
        this.checkInjection(BlindOperator.NO_MODE);
71
72 1 1. checkApplicability : negated conditional → NO_COVERAGE
        if (this.isApplicable) {
73 1 1. checkApplicability : removed call to com/jsql/model/injection/strategy/StrategyDns::allow → NO_COVERAGE
            this.allow();
74
        } else {
75 1 1. checkApplicability : removed call to com/jsql/model/injection/strategy/StrategyDns::unallow → NO_COVERAGE
            this.unallow();
76
        }
77
    }
78
79
    private void checkInjection(BlindOperator blindOperator) {
80 1 1. checkInjection : negated conditional → NO_COVERAGE
        if (this.isApplicable) {
81
            return;
82
        }
83
        this.blindOperator = blindOperator;
84
        LOGGER.log(
85
            LogLevelUtil.CONSOLE_DEFAULT,
86
            "{} [{}] with [{}]...",
87 1 1. lambda$checkInjection$0 : replaced return value with null for com/jsql/model/injection/strategy/StrategyDns::lambda$checkInjection$0 → NO_COVERAGE
            () -> I18nUtil.valueByKey(AbstractStrategy.KEY_LOG_CHECKING_STRATEGY),
88
            this::getName,
89 1 1. lambda$checkInjection$1 : replaced return value with null for com/jsql/model/injection/strategy/StrategyDns::lambda$checkInjection$1 → NO_COVERAGE
            () -> blindOperator
90
        );
91
        String engineSpecificWithOperator = this.injectionModel.getMediatorEngine().getEngine().instance().sqlDns(
92
            String.format(
93
                "(select concat('', %s))",
94
                this.injectionModel.getMediatorEngine().getEngine().instance().getModelYaml().getStrategy().getConfiguration().getFailsafe().replace(EngineYaml.INDICE, "1")
95
            ),
96
            "1",
97
            blindOperator,
98
            false
99
        );
100
101 1 1. checkInjection : removed call to java/lang/Thread::start → NO_COVERAGE
        new Thread(this.dnsServer::listen).start();
102
        this.injectionModel.injectWithoutIndex(engineSpecificWithOperator, "dns#confirm");
103 1 1. checkInjection : removed call to com/jsql/model/injection/strategy/StrategyDns::waitDnsResponse → NO_COVERAGE
        this.waitDnsResponse(2500);
104
105
        var domainName = this.injectionModel.getMediatorUtils().preferencesUtil().getDnsDomain();
106
        this.isApplicable = this.dnsServer.getResults().stream().anyMatch(
107 3 1. lambda$checkInjection$2 : negated conditional → NO_COVERAGE
2. lambda$checkInjection$2 : replaced boolean return with true for com/jsql/model/injection/strategy/StrategyDns::lambda$checkInjection$2 → NO_COVERAGE
3. lambda$checkInjection$2 : negated conditional → NO_COVERAGE
            s -> s.contains(domainName) && s.contains(StringUtil.toHex(ResourceAccess.WEB_CONFIRM_RESULT))
108
        );
109 1 1. checkInjection : negated conditional → NO_COVERAGE
        if (this.isApplicable) {
110 1 1. checkInjection : removed call to java/util/List::clear → NO_COVERAGE
            this.dnsServer.getResults().clear();
111
            LOGGER.log(
112
                LogLevelUtil.CONSOLE_SUCCESS,
113
                "{} [{}] with [{}]",
114 1 1. lambda$checkInjection$3 : replaced return value with null for com/jsql/model/injection/strategy/StrategyDns::lambda$checkInjection$3 → NO_COVERAGE
                () -> I18nUtil.valueByKey(AbstractStrategy.KEY_LOG_VULNERABLE),
115
                this::getName,
116
                this.blindOperator::name
117
            );
118
        } else {
119 1 1. checkInjection : removed call to com/jsql/model/injection/strategy/DnsServer::close → NO_COVERAGE
            this.dnsServer.close();
120
        }
121
    }
122
123
    @Override
124
    public void allow(int... i) {
125 1 1. allow : removed call to com/jsql/model/InjectionModel::appendAnalysisReport → NO_COVERAGE
        this.injectionModel.appendAnalysisReport(
126
            StringUtil.formatReport(LogLevelUtil.COLOR_BLU, "### Strategy: " + this.getName())
127
            + this.injectionModel.getReportWithoutIndex(
128
                this.injectionModel.getMediatorEngine().getEngine().instance().sqlDns(
129
                    StringUtil.formatReport(LogLevelUtil.COLOR_GREEN, "<query>"),
130
                    "1",
131
                    this.blindOperator,
132
                    true
133
                ),
134
                "metadataInjectionProcess",
135
                null
136
            )
137
        );
138 1 1. allow : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
        this.injectionModel.sendToViews(new Seal.MarkStrategyVulnerable(this));
139
    }
140
141
    @Override
142
    public void unallow(int... i) {
143 1 1. unallow : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
        this.injectionModel.sendToViews(new Seal.MarkStrategyInvulnerable(this));
144
    }
145
146
    @Override
147
    public String inject(String sqlQuery, String startPosition, AbstractSuspendable stoppable, String metadataInjectionProcess) {
148
        new Thread(() -> this.injectionModel.injectWithoutIndex(
149
            this.injectionModel.getMediatorEngine().getEngine().instance().sqlDns(
150
                sqlQuery,
151
                startPosition,
152
                this.blindOperator,
153
                false
154
            ),
155
            metadataInjectionProcess
156 1 1. inject : removed call to java/lang/Thread::start → NO_COVERAGE
        )).start();
157 1 1. inject : removed call to com/jsql/model/injection/strategy/StrategyDns::waitDnsResponse → NO_COVERAGE
        this.waitDnsResponse(5000);
158
159
        String result = this.dnsServer.getResults().getFirst();
160
        var domainName = this.injectionModel.getMediatorUtils().preferencesUtil().getDnsDomain();
161
        String regexToMatchTamperTags = String.format("(?i).{3}\\.([a-z0-9]*)\\..{3}\\.%s\\.", domainName);
162
        var matcherSql = Pattern.compile(regexToMatchTamperTags).matcher(result);
163 1 1. inject : negated conditional → NO_COVERAGE
        if (matcherSql.find()) {
164
            result = matcherSql.group(1);
165
        } else {
166
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Incorrect DNS response: {}", result);
167
        }
168 1 1. inject : removed call to java/util/List::clear → NO_COVERAGE
        this.dnsServer.getResults().clear();
169 1 1. inject : replaced return value with "" for com/jsql/model/injection/strategy/StrategyDns::inject → NO_COVERAGE
        return StringUtil.fromHex(result);
170
    }
171
172
    private void waitDnsResponse(int maxTime) {
173
        int currentTime = 0;
174 3 1. waitDnsResponse : negated conditional → NO_COVERAGE
2. waitDnsResponse : changed conditional boundary → NO_COVERAGE
3. waitDnsResponse : negated conditional → NO_COVERAGE
        while (this.dnsServer.getResults().isEmpty() && currentTime <= maxTime) {
175
            try {
176
                int waitTime = 250;
177 1 1. waitDnsResponse : removed call to java/lang/Thread::sleep → NO_COVERAGE
                Thread.sleep(waitTime);
178 1 1. waitDnsResponse : Replaced integer addition with subtraction → NO_COVERAGE
                currentTime += waitTime;
179
            } catch (InterruptedException e) {
180
                LOGGER.log(LogLevelUtil.IGNORE, e, e);
181 1 1. waitDnsResponse : removed call to java/lang/Thread::interrupt → NO_COVERAGE
                Thread.currentThread().interrupt();
182
            }
183
        }
184 2 1. waitDnsResponse : changed conditional boundary → NO_COVERAGE
2. waitDnsResponse : negated conditional → NO_COVERAGE
        if (currentTime > maxTime) {
185
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Missing DNS response after {} ms", maxTime);
186
        }
187
    }
188
189
    @Override
190
    public void activateWhenApplicable() {
191 2 1. activateWhenApplicable : negated conditional → NO_COVERAGE
2. activateWhenApplicable : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorStrategy().getStrategy() == null && this.isApplicable()) {
192
            LOGGER.log(
193
                LogLevelUtil.CONSOLE_INFORM,
194
                "{} [{}] with [{}]",
195 1 1. lambda$activateWhenApplicable$5 : replaced return value with null for com/jsql/model/injection/strategy/StrategyDns::lambda$activateWhenApplicable$5 → NO_COVERAGE
                () -> I18nUtil.valueByKey("LOG_USING_STRATEGY"),
196
                this::getName,
197
                this.blindOperator::name
198
            );
199 1 1. activateWhenApplicable : removed call to com/jsql/model/injection/strategy/MediatorStrategy::setStrategy → NO_COVERAGE
            this.injectionModel.getMediatorStrategy().setStrategy(this);
200 1 1. activateWhenApplicable : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
            this.injectionModel.sendToViews(new Seal.ActivateStrategy(this));
201
        }
202
    }
203
    
204
    @Override
205
    public String getPerformanceLength() {
206 1 1. getPerformanceLength : replaced return value with "" for com/jsql/model/injection/strategy/StrategyDns::getPerformanceLength → NO_COVERAGE
        return EngineYaml.DEFAULT_CAPACITY;
207
    }
208
    
209
    @Override
210
    public String getName() {
211 1 1. getName : replaced return value with "" for com/jsql/model/injection/strategy/StrategyDns::getName → NO_COVERAGE
        return "Dns";
212
    }
213
}

Mutations

41

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

45

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

46

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

56

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

67

1.1
Location : checkApplicability
Killed by : none
removed call to com/jsql/model/injection/strategy/StrategyDns::checkInjection → NO_COVERAGE

68

1.1
Location : checkApplicability
Killed by : none
removed call to com/jsql/model/injection/strategy/StrategyDns::checkInjection → NO_COVERAGE

69

1.1
Location : checkApplicability
Killed by : none
removed call to com/jsql/model/injection/strategy/StrategyDns::checkInjection → NO_COVERAGE

70

1.1
Location : checkApplicability
Killed by : none
removed call to com/jsql/model/injection/strategy/StrategyDns::checkInjection → NO_COVERAGE

72

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

73

1.1
Location : checkApplicability
Killed by : none
removed call to com/jsql/model/injection/strategy/StrategyDns::allow → NO_COVERAGE

75

1.1
Location : checkApplicability
Killed by : none
removed call to com/jsql/model/injection/strategy/StrategyDns::unallow → NO_COVERAGE

80

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

87

1.1
Location : lambda$checkInjection$0
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/StrategyDns::lambda$checkInjection$0 → NO_COVERAGE

89

1.1
Location : lambda$checkInjection$1
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/StrategyDns::lambda$checkInjection$1 → NO_COVERAGE

101

1.1
Location : checkInjection
Killed by : none
removed call to java/lang/Thread::start → NO_COVERAGE

103

1.1
Location : checkInjection
Killed by : none
removed call to com/jsql/model/injection/strategy/StrategyDns::waitDnsResponse → NO_COVERAGE

107

1.1
Location : lambda$checkInjection$2
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : lambda$checkInjection$2
Killed by : none
replaced boolean return with true for com/jsql/model/injection/strategy/StrategyDns::lambda$checkInjection$2 → NO_COVERAGE

3.3
Location : lambda$checkInjection$2
Killed by : none
negated conditional → NO_COVERAGE

109

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

110

1.1
Location : checkInjection
Killed by : none
removed call to java/util/List::clear → NO_COVERAGE

114

1.1
Location : lambda$checkInjection$3
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/StrategyDns::lambda$checkInjection$3 → NO_COVERAGE

119

1.1
Location : checkInjection
Killed by : none
removed call to com/jsql/model/injection/strategy/DnsServer::close → NO_COVERAGE

125

1.1
Location : allow
Killed by : none
removed call to com/jsql/model/InjectionModel::appendAnalysisReport → NO_COVERAGE

138

1.1
Location : allow
Killed by : none
removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE

143

1.1
Location : unallow
Killed by : none
removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE

156

1.1
Location : inject
Killed by : none
removed call to java/lang/Thread::start → NO_COVERAGE

157

1.1
Location : inject
Killed by : none
removed call to com/jsql/model/injection/strategy/StrategyDns::waitDnsResponse → NO_COVERAGE

163

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

168

1.1
Location : inject
Killed by : none
removed call to java/util/List::clear → NO_COVERAGE

169

1.1
Location : inject
Killed by : none
replaced return value with "" for com/jsql/model/injection/strategy/StrategyDns::inject → NO_COVERAGE

174

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

2.2
Location : waitDnsResponse
Killed by : none
changed conditional boundary → NO_COVERAGE

3.3
Location : waitDnsResponse
Killed by : none
negated conditional → NO_COVERAGE

177

1.1
Location : waitDnsResponse
Killed by : none
removed call to java/lang/Thread::sleep → NO_COVERAGE

178

1.1
Location : waitDnsResponse
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

181

1.1
Location : waitDnsResponse
Killed by : none
removed call to java/lang/Thread::interrupt → NO_COVERAGE

184

1.1
Location : waitDnsResponse
Killed by : none
changed conditional boundary → NO_COVERAGE

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

191

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

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

195

1.1
Location : lambda$activateWhenApplicable$5
Killed by : none
replaced return value with null for com/jsql/model/injection/strategy/StrategyDns::lambda$activateWhenApplicable$5 → NO_COVERAGE

199

1.1
Location : activateWhenApplicable
Killed by : none
removed call to com/jsql/model/injection/strategy/MediatorStrategy::setStrategy → NO_COVERAGE

200

1.1
Location : activateWhenApplicable
Killed by : none
removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE

206

1.1
Location : getPerformanceLength
Killed by : none
replaced return value with "" for com/jsql/model/injection/strategy/StrategyDns::getPerformanceLength → NO_COVERAGE

211

1.1
Location : getName
Killed by : none
replaced return value with "" for com/jsql/model/injection/strategy/StrategyDns::getName → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.22.1