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
        
35 1 1. parseForCsrfToken : removed call to com/jsql/util/CsrfUtil::parseCsrfFromCookie → NO_COVERAGE
        this.parseCsrfFromCookie(headers);
36 1 1. parseForCsrfToken : removed call to com/jsql/util/CsrfUtil::parseCsrfFromHtml → NO_COVERAGE
        this.parseCsrfFromHtml(pageSource);
37
    }
38
39
    private void parseCsrfFromHtml(String pageSource) {
40
41
        // Change immutable list to mutable for adding user tag
42
        List<String> tags = new ArrayList<>(
43
            Arrays.asList(
44
                "[name=_csrf]",
45
                "[name=_token]",
46
                "[name=csrf-token]",
47
                "[name=_csrf_header]",
48
                "[name=csrf_token]",
49
                "[name=csrfToken]",
50
                "[name=user_token]",
51
                "[name=csrfmiddlewaretoken]",
52
                "[name=form_build_id]"
53
            )
54
        );
55
        
56 1 1. parseCsrfFromHtml : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isCsrfUserTag()) {
57
            tags.add(
58
                String.format(
59
                    "[name='%s']",
60
                    this.injectionModel.getMediatorUtils().getPreferencesUtil().csrfUserTag()
61
                )
62
            );
63
        }
64
        
65
        Optional<SimpleEntry<String, String>> optionalTokenCsrf = Jsoup
66
            .parse(pageSource)
67
            .select("input")
68
            .select(
69
                String.join(",", tags)
70
            )
71
            .stream()
72
            .findFirst()
73
            .map(input ->
74 1 1. lambda$parseCsrfFromHtml$0 : replaced return value with null for com/jsql/util/CsrfUtil::lambda$parseCsrfFromHtml$0 → NO_COVERAGE
                new SimpleEntry<>(
75
                    input.attr("name"),
76
                    input.attr(INPUT_ATTR_VALUE)
77
                )
78
            );
79
        
80 1 1. parseCsrfFromHtml : negated conditional → NO_COVERAGE
        if (optionalTokenCsrf.isPresent()) {
81
            
82
            SimpleEntry<String, String> tokenCsrfFound = optionalTokenCsrf.get();
83
            
84
            LOGGER.log(
85
                LogLevelUtil.CONSOLE_INFORM,
86
                "Found Csrf token from HTML body: {}={}",
87
                tokenCsrfFound::getKey,
88
                tokenCsrfFound::getValue
89
            );
90
            
91
            if (
92 1 1. parseCsrfFromHtml : negated conditional → NO_COVERAGE
                !this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotProcessingCookies()
93 1 1. parseCsrfFromHtml : negated conditional → NO_COVERAGE
                && this.injectionModel.getMediatorUtils().getPreferencesUtil().isProcessingCsrf()
94
            ) {
95
                this.tokenCsrf = tokenCsrfFound;
96
                LOGGER.log(
97
                    LogLevelUtil.CONSOLE_SUCCESS,
98
                    "Csrf token added to query and header: {}",
99
                    tokenCsrfFound::getValue
100
                );
101
            } else {
102
                LOGGER.log(LogLevelUtil.CONSOLE_INFORM, MSG_ENABLE_CSRF);
103
            }
104
        }
105
    }
106
107
    private void parseCsrfFromCookie(Map<String, String> mapResponse) {
108
        
109
        Optional<SimpleEntry<String, String>> optionalCookieCsrf = Optional.empty();
110
        
111 1 1. parseCsrfFromCookie : negated conditional → NO_COVERAGE
        if (mapResponse.containsKey(SET_COOKIE_RESPONSE)) {
112
            
113
            // Spring: Cookie XSRF-TOKEN => Header X-XSRF-TOKEN, GET/POST parameter _csrf
114
            // Laravel, Zend, Symfony
115
            
116
            String[] cookieValues = StringUtils.split(mapResponse.get(SET_COOKIE_RESPONSE), ";");
117
            
118
            optionalCookieCsrf = Stream.of(cookieValues)
119 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"))
120
                .map(cookie -> {
121
                    
122
                    String[] cookieEntry = StringUtils.split(cookie, "=");
123
124 1 1. lambda$parseCsrfFromCookie$2 : replaced return value with null for com/jsql/util/CsrfUtil::lambda$parseCsrfFromCookie$2 → NO_COVERAGE
                    return new SimpleEntry<>(
125
                        cookieEntry[0].trim(),
126
                        cookieEntry[1].trim()
127
                    );
128
                })
129
                .findFirst();
130
        }
131
        
132 1 1. parseCsrfFromCookie : negated conditional → NO_COVERAGE
        if (optionalCookieCsrf.isPresent()) {
133
            
134
            SimpleEntry<String, String> cookieCsrf = optionalCookieCsrf.get();
135
            
136
            LOGGER.log(
137
                LogLevelUtil.CONSOLE_ERROR,
138
                "Found CSRF token from Cookie: {}={}",
139
                cookieCsrf::getKey,
140
                cookieCsrf::getValue
141
            );
142
            
143
            SimpleEntry<String, String> headerCsrf = new SimpleEntry<>(
144
                cookieCsrf.getKey(),
145
                cookieCsrf.getValue()
146
            );
147
            
148
            if (
149 1 1. parseCsrfFromCookie : negated conditional → NO_COVERAGE
                !this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotProcessingCookies()
150 1 1. parseCsrfFromCookie : negated conditional → NO_COVERAGE
                && this.injectionModel.getMediatorUtils().getPreferencesUtil().isProcessingCsrf()
151
            ) {
152
                this.tokenCsrf = headerCsrf;
153
            } else {
154
                LOGGER.log(LogLevelUtil.CONSOLE_INFORM, MSG_ENABLE_CSRF);
155
            }
156
        }
157
    }
158
159
    public void addHeaderToken(Builder httpRequest) {
160
        
161 1 1. addHeaderToken : negated conditional → NO_COVERAGE
        if (this.tokenCsrf == null) {
162
             return;
163
        }
164
165
        httpRequest.setHeader("X-XSRF-TOKEN", this.tokenCsrf.getValue());
166
        httpRequest.setHeader("X-CSRF-TOKEN", this.tokenCsrf.getValue());
167
        
168 1 1. addHeaderToken : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isCsrfUserTag()) {
169
            httpRequest.setHeader(
170
                this.injectionModel.getMediatorUtils().getPreferencesUtil().csrfUserTagOutput(),
171
                this.tokenCsrf.getValue()
172
            );
173
        }
174
    }
175
176
    public void addRequestToken(StringBuilder httpRequest) {
177
178 1 1. addRequestToken : negated conditional → NO_COVERAGE
        if (this.tokenCsrf == null) {
179
            return;
180
        }
181
182
        httpRequest.append(
183
            String.format(
184
                "%s=%s&",
185
                this.tokenCsrf.getKey(),
186
                this.tokenCsrf.getValue()
187
            )
188
        );
189
        
190
        httpRequest.append(
191
            String.format(
192
                "_csrf=%s&",
193
                this.tokenCsrf.getValue()
194
            )
195
        );
196
        
197 1 1. addRequestToken : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isCsrfUserTag()) {
198
            httpRequest.append(
199
                String.format(
200
                    "%s=%s&",
201
                    this.injectionModel.getMediatorUtils().getPreferencesUtil().csrfUserTagOutput(),
202
                    this.tokenCsrf.getValue()
203
                )
204
            );
205
        }
206
    }
207
    
208
    public String addQueryStringToken(String urlInjection) {
209
        
210
        String urlInjectionFixed = urlInjection;
211
212 1 1. addQueryStringToken : negated conditional → NO_COVERAGE
        if (this.tokenCsrf == null) {
213 1 1. addQueryStringToken : replaced return value with "" for com/jsql/util/CsrfUtil::addQueryStringToken → NO_COVERAGE
            return urlInjectionFixed;
214
        }
215
216
        urlInjectionFixed += String.format(
217
            "&%s=%s",
218
            this.tokenCsrf.getKey(),
219
            this.tokenCsrf.getValue()
220
        );
221
        
222
        urlInjectionFixed += String.format(
223
            "&_csrf=%s",
224
            this.tokenCsrf.getValue()
225
        );
226
        
227 1 1. addQueryStringToken : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isCsrfUserTag()) {
228
            urlInjectionFixed += String.format(
229
                "&%s=%s",
230
                this.injectionModel.getMediatorUtils().getPreferencesUtil().csrfUserTagOutput(),
231
                this.tokenCsrf.getValue()
232
            );
233
        }
234
        
235 1 1. addQueryStringToken : replaced return value with "" for com/jsql/util/CsrfUtil::addQueryStringToken → NO_COVERAGE
        return urlInjectionFixed;
236
    }
237
    
238
    
239
    // Getter / Setter
240
241
    public boolean isCsrf() {
242 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;
243
    }
244
245
    public SimpleEntry<String, String> getTokenCsrf() {
246 1 1. getTokenCsrf : replaced return value with null for com/jsql/util/CsrfUtil::getTokenCsrf → NO_COVERAGE
        return this.tokenCsrf;
247
    }
248
249
    public void setTokenCsrf(SimpleEntry<String, String> tokenCsrf) {
250
        this.tokenCsrf = tokenCsrf;
251
    }
252
}

Mutations

35

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

36

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

56

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

74

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

80

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

92

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

93

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

111

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

119

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

124

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

132

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

149

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

150

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

161

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

168

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

178

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

197

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

212

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

213

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

227

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

235

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

242

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

246

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