CsrfUtil.java

1
package com.jsql.util;
2
3
import com.jsql.model.InjectionModel;
4
import org.apache.commons.lang3.StringUtils;
5
import org.apache.logging.log4j.LogManager;
6
import org.apache.logging.log4j.Logger;
7
import org.jsoup.Jsoup;
8
9
import java.net.http.HttpRequest.Builder;
10
import java.util.AbstractMap.SimpleEntry;
11
import java.util.*;
12
import java.util.stream.Stream;
13
14
public class CsrfUtil {
15
    
16
    /**
17
     * Log4j logger sent to view.
18
     */
19
    private static final Logger LOGGER = LogManager.getRootLogger();
20
21
    private SimpleEntry<String, String> tokenCsrf = null;
22
    
23
    private static final String SET_COOKIE_RESPONSE = "set-cookie";
24
    private static final String INPUT_ATTR_VALUE = "value";
25
    private static final String MSG_ENABLE_CSRF = "Try with option CSRF processing enabled in preferences";
26
27
    private final InjectionModel injectionModel;
28
    
29
    public CsrfUtil(InjectionModel injectionModel) {
30
        this.injectionModel = injectionModel;
31
    }
32
33
    public void parseForCsrfToken(String pageSource, Map<String, String> headers) {
34 1 1. parseForCsrfToken : removed call to com/jsql/util/CsrfUtil::parseCsrfFromCookie → NO_COVERAGE
        this.parseCsrfFromCookie(headers);
35 1 1. parseForCsrfToken : removed call to com/jsql/util/CsrfUtil::parseCsrfFromHtml → NO_COVERAGE
        this.parseCsrfFromHtml(pageSource);
36
    }
37
38
    private void parseCsrfFromHtml(String pageSource) {
39
        // Change immutable list to mutable for adding user tag
40
        List<String> tags = new ArrayList<>(
41
            Arrays.asList(
42
                "[name=_csrf]",
43
                "[name=_token]",
44
                "[name=csrf-token]",
45
                "[name=_csrf_header]",
46
                "[name=csrf_token]",
47
                "[name=csrfToken]",
48
                "[name=user_token]",
49
                "[name=csrfmiddlewaretoken]",
50
                "[name=form_build_id]"
51
            )
52
        );
53
        
54 1 1. parseCsrfFromHtml : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isCsrfUserTag()) {
55
            tags.add(
56
                String.format(
57
                    "[name='%s']",
58
                    this.injectionModel.getMediatorUtils().getPreferencesUtil().csrfUserTag()
59
                )
60
            );
61
        }
62
        
63
        Optional<SimpleEntry<String, String>> optionalTokenCsrf = Jsoup.parse(pageSource)
64
            .select("input")
65
            .select(String.join(",", tags))
66
            .stream()
67
            .findFirst()
68
            .map(input ->
69 1 1. lambda$parseCsrfFromHtml$0 : replaced return value with null for com/jsql/util/CsrfUtil::lambda$parseCsrfFromHtml$0 → NO_COVERAGE
                new SimpleEntry<>(
70
                    input.attr("name"),
71
                    input.attr(CsrfUtil.INPUT_ATTR_VALUE)
72
                )
73
            );
74
        
75 1 1. parseCsrfFromHtml : negated conditional → NO_COVERAGE
        if (optionalTokenCsrf.isPresent()) {
76
            SimpleEntry<String, String> tokenCsrfFound = optionalTokenCsrf.get();
77
            LOGGER.log(
78
                LogLevelUtil.CONSOLE_INFORM,
79
                "Found Csrf token from HTML body: {}={}",
80
                tokenCsrfFound::getKey,
81
                tokenCsrfFound::getValue
82
            );
83
            if (
84 1 1. parseCsrfFromHtml : negated conditional → NO_COVERAGE
                !this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotProcessingCookies()
85 1 1. parseCsrfFromHtml : negated conditional → NO_COVERAGE
                && this.injectionModel.getMediatorUtils().getPreferencesUtil().isProcessingCsrf()
86
            ) {
87
                this.tokenCsrf = tokenCsrfFound;
88
                LOGGER.log(
89
                    LogLevelUtil.CONSOLE_SUCCESS,
90
                    "Csrf token added to query and header: {}",
91
                    tokenCsrfFound::getValue
92
                );
93
            } else {
94
                LOGGER.log(LogLevelUtil.CONSOLE_INFORM, CsrfUtil.MSG_ENABLE_CSRF);
95
            }
96
        }
97
    }
98
99
    private void parseCsrfFromCookie(Map<String, String> mapResponse) {
100
        Optional<SimpleEntry<String, String>> optionalCookieCsrf = Optional.empty();
101
        
102 1 1. parseCsrfFromCookie : negated conditional → NO_COVERAGE
        if (mapResponse.containsKey(CsrfUtil.SET_COOKIE_RESPONSE)) {
103
            // Spring: Cookie XSRF-TOKEN => Header X-XSRF-TOKEN, GET/POST parameter _csrf
104
            // Laravel, Zend, Symfony
105
            String[] cookieValues = StringUtils.split(mapResponse.get(CsrfUtil.SET_COOKIE_RESPONSE), ";");
106
            optionalCookieCsrf = Stream.of(cookieValues)
107 2 1. lambda$parseCsrfFromCookie$1 : replaced boolean return with true for com/jsql/util/CsrfUtil::lambda$parseCsrfFromCookie$1 → NO_COVERAGE
2. lambda$parseCsrfFromCookie$1 : replaced boolean return with false for com/jsql/util/CsrfUtil::lambda$parseCsrfFromCookie$1 → NO_COVERAGE
                .filter(cookie -> cookie.trim().toLowerCase().startsWith("xsrf-token"))
108
                .map(cookie -> {
109
                    String[] cookieEntry = StringUtils.split(cookie, "=");
110 1 1. lambda$parseCsrfFromCookie$2 : replaced return value with null for com/jsql/util/CsrfUtil::lambda$parseCsrfFromCookie$2 → NO_COVERAGE
                    return new SimpleEntry<>(
111
                        cookieEntry[0].trim(),
112
                        cookieEntry[1].trim()
113
                    );
114
                })
115
                .findFirst();
116
        }
117
        
118 1 1. parseCsrfFromCookie : negated conditional → NO_COVERAGE
        if (optionalCookieCsrf.isPresent()) {
119
            SimpleEntry<String, String> cookieCsrf = optionalCookieCsrf.get();
120
            LOGGER.log(
121
                LogLevelUtil.CONSOLE_ERROR,
122
                "Found CSRF token from Cookie: {}={}",
123
                cookieCsrf::getKey,
124
                cookieCsrf::getValue
125
            );
126
            SimpleEntry<String, String> headerCsrf = new SimpleEntry<>(
127
                cookieCsrf.getKey(),
128
                cookieCsrf.getValue()
129
            );
130
            if (
131 1 1. parseCsrfFromCookie : negated conditional → NO_COVERAGE
                !this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotProcessingCookies()
132 1 1. parseCsrfFromCookie : negated conditional → NO_COVERAGE
                && this.injectionModel.getMediatorUtils().getPreferencesUtil().isProcessingCsrf()
133
            ) {
134
                this.tokenCsrf = headerCsrf;
135
            } else {
136
                LOGGER.log(LogLevelUtil.CONSOLE_INFORM, CsrfUtil.MSG_ENABLE_CSRF);
137
            }
138
        }
139
    }
140
141
    public void addHeaderToken(Builder httpRequest) {
142 1 1. addHeaderToken : negated conditional → NO_COVERAGE
        if (this.tokenCsrf == null) {
143
             return;
144
        }
145
146
        httpRequest.setHeader("X-XSRF-TOKEN", this.tokenCsrf.getValue());
147
        httpRequest.setHeader("X-CSRF-TOKEN", this.tokenCsrf.getValue());
148
        
149 1 1. addHeaderToken : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isCsrfUserTag()) {
150
            httpRequest.setHeader(
151
                this.injectionModel.getMediatorUtils().getPreferencesUtil().csrfUserTagOutput(),
152
                this.tokenCsrf.getValue()
153
            );
154
        }
155
    }
156
157
    public void addRequestToken(StringBuilder httpRequest) {
158 1 1. addRequestToken : negated conditional → NO_COVERAGE
        if (this.tokenCsrf == null) {
159
            return;
160
        }
161
        httpRequest.append(
162
            String.format(
163
                "%s=%s&",
164
                this.tokenCsrf.getKey(),
165
                this.tokenCsrf.getValue()
166
            )
167
        );
168
        httpRequest.append(
169
            String.format(
170
                "_csrf=%s&",
171
                this.tokenCsrf.getValue()
172
            )
173
        );
174 1 1. addRequestToken : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isCsrfUserTag()) {
175
            httpRequest.append(
176
                String.format(
177
                    "%s=%s&",
178
                    this.injectionModel.getMediatorUtils().getPreferencesUtil().csrfUserTagOutput(),
179
                    this.tokenCsrf.getValue()
180
                )
181
            );
182
        }
183
    }
184
    
185
    public String addQueryStringToken(String urlInjection) {
186
        String urlInjectionFixed = urlInjection;
187 1 1. addQueryStringToken : negated conditional → NO_COVERAGE
        if (this.tokenCsrf == null) {
188 1 1. addQueryStringToken : replaced return value with "" for com/jsql/util/CsrfUtil::addQueryStringToken → NO_COVERAGE
            return urlInjectionFixed;
189
        }
190
        urlInjectionFixed += String.format(
191
            "&%s=%s",
192
            this.tokenCsrf.getKey(),
193
            this.tokenCsrf.getValue()
194
        );
195
        urlInjectionFixed += String.format(
196
            "&_csrf=%s",
197
            this.tokenCsrf.getValue()
198
        );
199 1 1. addQueryStringToken : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isCsrfUserTag()) {
200
            urlInjectionFixed += String.format(
201
                "&%s=%s",
202
                this.injectionModel.getMediatorUtils().getPreferencesUtil().csrfUserTagOutput(),
203
                this.tokenCsrf.getValue()
204
            );
205
        }
206 1 1. addQueryStringToken : replaced return value with "" for com/jsql/util/CsrfUtil::addQueryStringToken → NO_COVERAGE
        return urlInjectionFixed;
207
    }
208
    
209
    
210
    // Getter / Setter
211
212
    public boolean isCsrf() {
213 2 1. isCsrf : replaced boolean return with true for com/jsql/util/CsrfUtil::isCsrf → NO_COVERAGE
2. isCsrf : negated conditional → NO_COVERAGE
        return this.tokenCsrf != null;
214
    }
215
216
    public SimpleEntry<String, String> getTokenCsrf() {
217 1 1. getTokenCsrf : replaced return value with null for com/jsql/util/CsrfUtil::getTokenCsrf → NO_COVERAGE
        return this.tokenCsrf;
218
    }
219
220
    public void setTokenCsrf(SimpleEntry<String, String> tokenCsrf) {
221
        this.tokenCsrf = tokenCsrf;
222
    }
223
}

Mutations

34

1.1
Location : parseForCsrfToken
Killed by : none
removed call to com/jsql/util/CsrfUtil::parseCsrfFromCookie → NO_COVERAGE

35

1.1
Location : parseForCsrfToken
Killed by : none
removed call to com/jsql/util/CsrfUtil::parseCsrfFromHtml → NO_COVERAGE

54

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

69

1.1
Location : lambda$parseCsrfFromHtml$0
Killed by : none
replaced return value with null for com/jsql/util/CsrfUtil::lambda$parseCsrfFromHtml$0 → NO_COVERAGE

75

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

84

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

85

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

102

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

107

1.1
Location : lambda$parseCsrfFromCookie$1
Killed by : none
replaced boolean return with true for com/jsql/util/CsrfUtil::lambda$parseCsrfFromCookie$1 → NO_COVERAGE

2.2
Location : lambda$parseCsrfFromCookie$1
Killed by : none
replaced boolean return with false for com/jsql/util/CsrfUtil::lambda$parseCsrfFromCookie$1 → NO_COVERAGE

110

1.1
Location : lambda$parseCsrfFromCookie$2
Killed by : none
replaced return value with null for com/jsql/util/CsrfUtil::lambda$parseCsrfFromCookie$2 → NO_COVERAGE

118

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

131

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

132

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

142

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

149

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

158

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

174

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

187

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

188

1.1
Location : addQueryStringToken
Killed by : none
replaced return value with "" for com/jsql/util/CsrfUtil::addQueryStringToken → NO_COVERAGE

199

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

206

1.1
Location : addQueryStringToken
Killed by : none
replaced return value with "" for com/jsql/util/CsrfUtil::addQueryStringToken → NO_COVERAGE

213

1.1
Location : isCsrf
Killed by : none
replaced boolean return with true for com/jsql/util/CsrfUtil::isCsrf → NO_COVERAGE

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

217

1.1
Location : getTokenCsrf
Killed by : none
replaced return value with null for com/jsql/util/CsrfUtil::getTokenCsrf → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.19.1