mirror of
https://github.com/github/codeql.git
synced 2026-05-02 20:25:13 +02:00
Add spring url redirection detect
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
edges
|
||||
| SpringUrlRedirect.java:13:30:13:47 | redirectUrl : String | SpringUrlRedirect.java:15:19:15:29 | redirectUrl |
|
||||
| SpringUrlRedirect.java:20:24:20:41 | redirectUrl : String | SpringUrlRedirect.java:21:36:21:46 | redirectUrl |
|
||||
| SpringUrlRedirect.java:26:30:26:47 | redirectUrl : String | SpringUrlRedirect.java:27:44:27:54 | redirectUrl |
|
||||
| SpringUrlRedirect.java:32:30:32:47 | redirectUrl : String | SpringUrlRedirect.java:33:47:33:57 | redirectUrl |
|
||||
nodes
|
||||
| SpringUrlRedirect.java:13:30:13:47 | redirectUrl : String | semmle.label | redirectUrl : String |
|
||||
| SpringUrlRedirect.java:15:19:15:29 | redirectUrl | semmle.label | redirectUrl |
|
||||
| SpringUrlRedirect.java:20:24:20:41 | redirectUrl : String | semmle.label | redirectUrl : String |
|
||||
| SpringUrlRedirect.java:21:36:21:46 | redirectUrl | semmle.label | redirectUrl |
|
||||
| SpringUrlRedirect.java:26:30:26:47 | redirectUrl : String | semmle.label | redirectUrl : String |
|
||||
| SpringUrlRedirect.java:27:44:27:54 | redirectUrl | semmle.label | redirectUrl |
|
||||
| SpringUrlRedirect.java:32:30:32:47 | redirectUrl : String | semmle.label | redirectUrl : String |
|
||||
| SpringUrlRedirect.java:33:47:33:57 | redirectUrl | semmle.label | redirectUrl |
|
||||
#select
|
||||
| SpringUrlRedirect.java:15:19:15:29 | redirectUrl | SpringUrlRedirect.java:13:30:13:47 | redirectUrl : String | SpringUrlRedirect.java:15:19:15:29 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:13:30:13:47 | redirectUrl | user-provided value |
|
||||
| SpringUrlRedirect.java:21:36:21:46 | redirectUrl | SpringUrlRedirect.java:20:24:20:41 | redirectUrl : String | SpringUrlRedirect.java:21:36:21:46 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:20:24:20:41 | redirectUrl | user-provided value |
|
||||
| SpringUrlRedirect.java:27:44:27:54 | redirectUrl | SpringUrlRedirect.java:26:30:26:47 | redirectUrl : String | SpringUrlRedirect.java:27:44:27:54 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:26:30:26:47 | redirectUrl | user-provided value |
|
||||
| SpringUrlRedirect.java:33:47:33:57 | redirectUrl | SpringUrlRedirect.java:32:30:32:47 | redirectUrl : String | SpringUrlRedirect.java:33:47:33:57 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:32:30:32:47 | redirectUrl | user-provided value |
|
||||
@@ -0,0 +1,52 @@
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
@Controller
|
||||
public class SpringUrlRedirect {
|
||||
|
||||
private final static String VALID_REDIRECT = "http://127.0.0.1";
|
||||
|
||||
@GetMapping("url1")
|
||||
public RedirectView bad1(String redirectUrl, HttpServletResponse response) throws Exception {
|
||||
RedirectView rv = new RedirectView();
|
||||
rv.setUrl(redirectUrl);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@GetMapping("url2")
|
||||
public String bad2(String redirectUrl) {
|
||||
String url = "redirect:" + redirectUrl;
|
||||
return url;
|
||||
}
|
||||
|
||||
@GetMapping("url3")
|
||||
public RedirectView bad3(String redirectUrl) {
|
||||
RedirectView rv = new RedirectView(redirectUrl);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@GetMapping("url4")
|
||||
public ModelAndView bad4(String redirectUrl) {
|
||||
return new ModelAndView("redirect:" + redirectUrl);
|
||||
}
|
||||
|
||||
@GetMapping("url5")
|
||||
public RedirectView good1(String redirectUrl) {
|
||||
RedirectView rv = new RedirectView();
|
||||
if (redirectUrl.startsWith(VALID_REDIRECT)){
|
||||
rv.setUrl(redirectUrl);
|
||||
}else {
|
||||
rv.setUrl(VALID_REDIRECT);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@GetMapping("url6")
|
||||
public ModelAndView good2(String token) {
|
||||
String url = "/edit?token=" + token;
|
||||
return new ModelAndView("redirect:" + url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
|
||||
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/springframework-5.2.3/
|
||||
@@ -0,0 +1,107 @@
|
||||
package org.springframework.web.servlet;
|
||||
|
||||
import java.util.Map;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
public class ModelAndView {
|
||||
@Nullable
|
||||
private Object view;
|
||||
@Nullable
|
||||
private HttpStatus status;
|
||||
private boolean cleared = false;
|
||||
|
||||
public ModelAndView() {
|
||||
}
|
||||
|
||||
public ModelAndView(String viewName) {
|
||||
this.view = viewName;
|
||||
}
|
||||
|
||||
public ModelAndView(View view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
public ModelAndView(String viewName, @Nullable Map<String, ?> model) { }
|
||||
|
||||
public ModelAndView(View view, @Nullable Map<String, ?> model) { }
|
||||
|
||||
public ModelAndView(String viewName, HttpStatus status) { }
|
||||
|
||||
public ModelAndView(@Nullable String viewName, @Nullable Map<String, ?> model, @Nullable HttpStatus status) { }
|
||||
|
||||
public ModelAndView(String viewName, String modelName, Object modelObject) { }
|
||||
|
||||
public ModelAndView(View view, String modelName, Object modelObject) { }
|
||||
|
||||
public void setViewName(@Nullable String viewName) {
|
||||
this.view = viewName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getViewName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void setView(@Nullable View view) { }
|
||||
|
||||
@Nullable
|
||||
public View getView() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasView() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isReference() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Map<String, Object> getModelInternal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, Object> getModel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setStatus(@Nullable HttpStatus status) { }
|
||||
|
||||
@Nullable
|
||||
public HttpStatus getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public ModelAndView addObject(String attributeName, @Nullable Object attributeValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ModelAndView addObject(Object attributeValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ModelAndView addAllObjects(@Nullable Map<String, ?> modelMap) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void clear() { }
|
||||
|
||||
public boolean isEmpty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean wasCleared() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "";
|
||||
}
|
||||
|
||||
private String formatView() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.springframework.web.servlet;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
public interface View {
|
||||
String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";
|
||||
String PATH_VARIABLES = View.class.getName() + ".pathVariables";
|
||||
String SELECTED_CONTENT_TYPE = View.class.getName() + ".selectedContentType";
|
||||
|
||||
@Nullable
|
||||
default String getContentType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
void render(@Nullable Map<String, ?> var1, HttpServletRequest var2, HttpServletResponse var3) throws Exception;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.springframework.web.servlet.view;
|
||||
|
||||
import java.util.Locale;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
public abstract class AbstractUrlBasedView {
|
||||
@Nullable
|
||||
private String url;
|
||||
|
||||
protected AbstractUrlBasedView() { }
|
||||
|
||||
protected AbstractUrlBasedView(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public void setUrl(@Nullable String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getUrl() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception { }
|
||||
|
||||
protected boolean isUrlRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean checkResource(Locale locale) throws Exception {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
package org.springframework.web.servlet.view;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
public class RedirectView extends AbstractUrlBasedView {
|
||||
private static final Pattern URI_TEMPLATE_VARIABLE_PATTERN = Pattern.compile("\\{([^/]+?)\\}");
|
||||
private boolean contextRelative = false;
|
||||
private boolean http10Compatible = true;
|
||||
private boolean exposeModelAttributes = true;
|
||||
@Nullable
|
||||
private String encodingScheme;
|
||||
@Nullable
|
||||
private HttpStatus statusCode;
|
||||
private boolean expandUriTemplateVariables = true;
|
||||
private boolean propagateQueryParams = false;
|
||||
@Nullable
|
||||
private String[] hosts;
|
||||
|
||||
public RedirectView() { }
|
||||
|
||||
public RedirectView(String url) { }
|
||||
|
||||
public RedirectView(String url, boolean contextRelative) { }
|
||||
|
||||
public RedirectView(String url, boolean contextRelative, boolean http10Compatible) { }
|
||||
|
||||
public RedirectView(String url, boolean contextRelative, boolean http10Compatible, boolean exposeModelAttributes) { }
|
||||
|
||||
public void setContextRelative(boolean contextRelative) { }
|
||||
|
||||
public void setHttp10Compatible(boolean http10Compatible) { }
|
||||
|
||||
public void setExposeModelAttributes(boolean exposeModelAttributes) { }
|
||||
|
||||
public void setEncodingScheme(String encodingScheme) { }
|
||||
|
||||
public void setStatusCode(HttpStatus statusCode) { }
|
||||
|
||||
public void setExpandUriTemplateVariables(boolean expandUriTemplateVariables) { }
|
||||
|
||||
public void setPropagateQueryParams(boolean propagateQueryParams) { }
|
||||
|
||||
public boolean isPropagateQueryProperties() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setHosts(@Nullable String... hosts) { }
|
||||
|
||||
@Nullable
|
||||
public String[] getHosts() {
|
||||
return this.hosts;
|
||||
}
|
||||
|
||||
public boolean isRedirectView() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isContextRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws IOException { }
|
||||
|
||||
protected final String createTargetUrl(Map<String, Object> model, HttpServletRequest request) throws UnsupportedEncodingException {
|
||||
return "";
|
||||
}
|
||||
|
||||
private String getContextPath(HttpServletRequest request) {
|
||||
return "";
|
||||
}
|
||||
|
||||
protected StringBuilder replaceUriTemplateVariables(String targetUrl, Map<String, Object> model, Map<String, String> currentUriVariables, String encodingScheme) throws UnsupportedEncodingException {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, String> getCurrentRequestUriVariables(HttpServletRequest request) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void appendCurrentQueryParams(StringBuilder targetUrl, HttpServletRequest request) { }
|
||||
|
||||
protected void appendQueryProperties(StringBuilder targetUrl, Map<String, Object> model, String encodingScheme) throws UnsupportedEncodingException { }
|
||||
|
||||
protected Map<String, Object> queryProperties(Map<String, Object> model) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean isEligibleProperty(String key, @Nullable Object value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isEligibleValue(@Nullable Object value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected String urlEncode(String input, String encodingScheme) throws UnsupportedEncodingException {
|
||||
return "";
|
||||
}
|
||||
|
||||
protected String updateTargetUrl(String targetUrl, Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) {
|
||||
return "";
|
||||
}
|
||||
|
||||
protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String targetUrl, boolean http10Compatible) throws IOException { }
|
||||
|
||||
protected boolean isRemoteHost(String targetUrl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected HttpStatus getHttp11StatusCode(HttpServletRequest request, HttpServletResponse response, String targetUrl) {
|
||||
return this.statusCode;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user