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
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 this.parseCsrfFromCookie(headers);
36 this.parseCsrfFromHtml(pageSource);
37 }
38
39 private void parseCsrfFromHtml(String pageSource) {
40
41
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 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 new SimpleEntry<>(
75 input.attr("name"),
76 input.attr(INPUT_ATTR_VALUE)
77 )
78 );
79
80 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 !this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotProcessingCookies()
93 && 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 if (mapResponse.containsKey(SET_COOKIE_RESPONSE)) {
112
113
114
115
116 String[] cookieValues = StringUtils.split(mapResponse.get(SET_COOKIE_RESPONSE), ";");
117
118 optionalCookieCsrf = Stream.of(cookieValues)
119 .filter(cookie -> cookie.trim().toLowerCase().startsWith("xsrf-token"))
120 .map(cookie -> {
121
122 String[] cookieEntry = StringUtils.split(cookie, "=");
123
124 return new SimpleEntry<>(
125 cookieEntry[0].trim(),
126 cookieEntry[1].trim()
127 );
128 })
129 .findFirst();
130 }
131
132 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 !this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotProcessingCookies()
150 && 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 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 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 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 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 if (this.tokenCsrf == null) {
213 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 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 return urlInjectionFixed;
236 }
237
238
239
240
241 public boolean isCsrf() {
242 return this.tokenCsrf != null;
243 }
244
245 public SimpleEntry<String, String> getTokenCsrf() {
246 return this.tokenCsrf;
247 }
248
249 public void setTokenCsrf(SimpleEntry<String, String> tokenCsrf) {
250 this.tokenCsrf = tokenCsrf;
251 }
252 }