CallableFile.java

1
package com.jsql.model.accessible;
2
3
import com.jsql.model.InjectionModel;
4
import com.jsql.model.exception.AbstractSlidingException;
5
import com.jsql.model.exception.InjectionFailureException;
6
import com.jsql.model.exception.LoopDetectedSlidingException;
7
import com.jsql.model.exception.StoppedByUserSlidingException;
8
import com.jsql.model.injection.engine.model.Engine;
9
import com.jsql.model.suspendable.SuspendableGetRows;
10
import com.jsql.util.LogLevelUtil;
11
import org.apache.commons.lang3.StringUtils;
12
import org.apache.logging.log4j.LogManager;
13
import org.apache.logging.log4j.Logger;
14
15
import java.util.AbstractMap;
16
import java.util.HashMap;
17
import java.util.Map;
18
import java.util.concurrent.Callable;
19
20
/**
21
 * Thread unit to read source of a file by SQL injection.
22
 * User can interrupt the process and get a partial result of the file content.
23
 */
24
public class CallableFile implements Callable<CallableFile> {
25
26
    private static final Logger LOGGER = LogManager.getRootLogger();
27
    public static final String REQUIRE_STACK = "Read file requirement: stack query";
28
    public static final String READ_FILE_NOT_IMPLEMENTED = "Read file not implemented for [{}], share a working example on GitHub to speed up release";
29
30
    /**
31
     * Path to the file to read.
32
     */
33
    private final String pathFile;
34
35
    /**
36
     * Source of file.
37
     */
38
    private String sourceFile = StringUtils.EMPTY;
39
    
40
    /**
41
     * Suspendable task that reads lines of the file by injection.
42
     */
43
    private final SuspendableGetRows suspendableReadFile;
44
45
    private final InjectionModel injectionModel;
46
    
47
    /**
48
     * Create Callable to read a file.
49
     */
50
    public CallableFile(String pathFile, InjectionModel injectionModel) {
51
        this.pathFile = pathFile;
52
        this.injectionModel= injectionModel;
53
        this.suspendableReadFile = new SuspendableGetRows(injectionModel);
54
    }
55
56
    @FunctionalInterface
57
    private interface Readable {
58
        String call() throws AbstractSlidingException;
59
    }
60
61
    /**
62
     * Read a file on the server using SQL injection.
63
     * Get partial result if user interrupts the process.
64
     */
65
    @Override
66
    public CallableFile call() throws Exception {
67
        Map<Engine, Readable> mapEngineReadable = new HashMap<>();
68 1 1. lambda$call$0 : replaced return value with "" for com/jsql/model/accessible/CallableFile::lambda$call$0 → NO_COVERAGE
        mapEngineReadable.put(this.injectionModel.getMediatorEngine().getMysql(), () -> this.injectionModel.getResourceAccess().getExploitMysql().getRead(this.pathFile));
69 1 1. lambda$call$1 : replaced return value with "" for com/jsql/model/accessible/CallableFile::lambda$call$1 → NO_COVERAGE
        mapEngineReadable.put(this.injectionModel.getMediatorEngine().getH2(), () -> this.injectionModel.getResourceAccess().getExploitH2().getRead(this.pathFile));
70 1 1. lambda$call$2 : replaced return value with "" for com/jsql/model/accessible/CallableFile::lambda$call$2 → NO_COVERAGE
        mapEngineReadable.put(this.injectionModel.getMediatorEngine().getSqlite(), () -> this.injectionModel.getResourceAccess().getExploitSqlite().getRead(this.pathFile));
71 1 1. lambda$call$3 : replaced return value with "" for com/jsql/model/accessible/CallableFile::lambda$call$3 → NO_COVERAGE
        mapEngineReadable.put(this.injectionModel.getMediatorEngine().getDerby(), () -> this.injectionModel.getResourceAccess().getExploitDerby().getRead(this.pathFile));
72 1 1. lambda$call$4 : replaced return value with "" for com/jsql/model/accessible/CallableFile::lambda$call$4 → NO_COVERAGE
        mapEngineReadable.put(this.injectionModel.getMediatorEngine().getHsqldb(), () -> this.injectionModel.getResourceAccess().getExploitHsqldb().getRead(this.pathFile));
73 1 1. lambda$call$5 : replaced return value with "" for com/jsql/model/accessible/CallableFile::lambda$call$5 → NO_COVERAGE
        mapEngineReadable.put(this.injectionModel.getMediatorEngine().getPostgres(), () -> this.injectionModel.getResourceAccess().getExploitPostgres().getRead(this.pathFile));
74 1 1. lambda$call$6 : replaced return value with "" for com/jsql/model/accessible/CallableFile::lambda$call$6 → NO_COVERAGE
        mapEngineReadable.put(this.injectionModel.getMediatorEngine().getSqlserver(), () -> this.injectionModel.getResourceAccess().getExploitSqlserver().getRead(this.pathFile));
75
76
        Readable readable = mapEngineReadable.entrySet().stream()
77 2 1. lambda$call$7 : replaced boolean return with true for com/jsql/model/accessible/CallableFile::lambda$call$7 → NO_COVERAGE
2. lambda$call$7 : negated conditional → NO_COVERAGE
            .filter(entry -> this.injectionModel.getMediatorEngine().getEngine() == entry.getKey())
78
            .findFirst()
79
            .orElse(new AbstractMap.SimpleEntry<>(null, () -> {
80
                LOGGER.log(
81
                    LogLevelUtil.CONSOLE_DEFAULT,
82
                    CallableFile.READ_FILE_NOT_IMPLEMENTED,
83
                    this.injectionModel.getMediatorEngine().getEngine()
84
                );
85
                return StringUtils.EMPTY;
86
            }))
87
            .getValue();
88
89
        String resultToParse = StringUtils.EMPTY;
90
        try {
91
            resultToParse = readable.call();
92
        } catch (InjectionFailureException e) {
93
            // Usually thrown if File does not exist
94
            LOGGER.log(LogLevelUtil.IGNORE, e);
95
        } catch (LoopDetectedSlidingException | StoppedByUserSlidingException e) {
96 1 1. call : negated conditional → NO_COVERAGE
            if (StringUtils.isNotEmpty(e.getSlidingWindowAllRows())) {  // Get partial source
97
                resultToParse = e.getSlidingWindowAllRows();
98 1 1. call : negated conditional → NO_COVERAGE
            } else if (StringUtils.isNotEmpty(e.getSlidingWindowCurrentRows())) {
99
                resultToParse = e.getSlidingWindowCurrentRows();
100
            }
101
            LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
102
        }
103
104
        this.sourceFile = resultToParse;
105 1 1. call : replaced return value with null for com/jsql/model/accessible/CallableFile::call → NO_COVERAGE
        return this;
106
    }
107
108
109
    // Getters
110
    
111
    public String getPathFile() {
112 1 1. getPathFile : replaced return value with "" for com/jsql/model/accessible/CallableFile::getPathFile → NO_COVERAGE
        return this.pathFile;
113
    }
114
115
    public String getSourceFile() {
116 1 1. getSourceFile : replaced return value with "" for com/jsql/model/accessible/CallableFile::getSourceFile → NO_COVERAGE
        return this.sourceFile;
117
    }
118
119
    public SuspendableGetRows getSuspendableReadFile() {
120 1 1. getSuspendableReadFile : replaced return value with null for com/jsql/model/accessible/CallableFile::getSuspendableReadFile → NO_COVERAGE
        return this.suspendableReadFile;
121
    }
122
}

Mutations

68

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

69

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

70

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

71

1.1
Location : lambda$call$3
Killed by : none
replaced return value with "" for com/jsql/model/accessible/CallableFile::lambda$call$3 → NO_COVERAGE

72

1.1
Location : lambda$call$4
Killed by : none
replaced return value with "" for com/jsql/model/accessible/CallableFile::lambda$call$4 → NO_COVERAGE

73

1.1
Location : lambda$call$5
Killed by : none
replaced return value with "" for com/jsql/model/accessible/CallableFile::lambda$call$5 → NO_COVERAGE

74

1.1
Location : lambda$call$6
Killed by : none
replaced return value with "" for com/jsql/model/accessible/CallableFile::lambda$call$6 → NO_COVERAGE

77

1.1
Location : lambda$call$7
Killed by : none
replaced boolean return with true for com/jsql/model/accessible/CallableFile::lambda$call$7 → NO_COVERAGE

2.2
Location : lambda$call$7
Killed by : none
negated conditional → NO_COVERAGE

96

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

98

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

105

1.1
Location : call
Killed by : none
replaced return value with null for com/jsql/model/accessible/CallableFile::call → NO_COVERAGE

112

1.1
Location : getPathFile
Killed by : none
replaced return value with "" for com/jsql/model/accessible/CallableFile::getPathFile → NO_COVERAGE

116

1.1
Location : getSourceFile
Killed by : none
replaced return value with "" for com/jsql/model/accessible/CallableFile::getSourceFile → NO_COVERAGE

120

1.1
Location : getSuspendableReadFile
Killed by : none
replaced return value with null for com/jsql/model/accessible/CallableFile::getSuspendableReadFile → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.23.0