Merge pull request #6247 from p0wn4j/spring-responseentity-redirect-sink

[Java] CWE-601: Add Spring URL Redirect ResponseEntity sink
This commit is contained in:
Chris Smowton
2021-07-22 09:45:30 +01:00
committed by GitHub
6 changed files with 240 additions and 38 deletions

View File

@@ -34,6 +34,29 @@ public class SpringUrlRedirect {
}
@GetMapping("url5")
public ResponseEntity<Void> bad5(String redirectUrl) {
return ResponseEntity.status(HttpStatus.FOUND)
.location(URI.create(redirectUrl))
.build();
}
@GetMapping("url6")
public ResponseEntity<Void> bad6(String redirectUrl) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setLocation(URI.create(redirectUrl));
return new ResponseEntity<>(httpHeaders, HttpStatus.SEE_OTHER);
}
@GetMapping("url7")
public ResponseEntity<Void> bad7(String redirectUrl) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Location", redirectUrl);
return ResponseEntity.status(HttpStatus.SEE_OTHER).headers(httpHeaders).build();
}
@GetMapping("url8")
public RedirectView good1(String redirectUrl) {
RedirectView rv = new RedirectView();
if (redirectUrl.startsWith(VALID_REDIRECT)){

View File

@@ -21,10 +21,10 @@ redirects on the server; then choose from that list based on the user input prov
<example>
<p>The following examples show the bad case and the good case respectively.
In <code>bad1</code> method and <code>bad2</code> method and <code>bad3</code> method and
<code>bad4</code> method, shows an HTTP request parameter being used directly in a URL redirect
without validating the input, which facilitates phishing attacks. In <code>good1</code> method,
shows how to solve this problem by verifying whether the user input is a known fixed string beginning.
The <code>bad</code> methods show an HTTP request parameter being used directly
in a URL redirect without validating the input, which facilitates phishing attacks.
In the <code>good1</code> method, it is shown how to solve this problem by verifying whether
the user input is a known fixed string beginning.
</p>
<sample src="SpringUrlRedirect.java" />
@@ -33,5 +33,6 @@ shows how to solve this problem by verifying whether the user input is a known f
<references>
<li>A Guide To Spring Redirects: <a href="https://www.baeldung.com/spring-redirect-and-forward">Spring Redirects</a>.</li>
<li>Url redirection - attack and defense: <a href="https://www.virtuesecurity.com/kb/url-redirection-attack-and-defense/">Url Redirection</a>.</li>
<li>How to redirect to an external URL from Spring Boot REST Controller (Post/Redirect/Get pattern)?: <a href="https://fullstackdeveloper.guru/2021/03/12/how-to-redirect-to-an-external-url-from-spring-boot-rest-controller/">ResponseEntity Redirection</a>.</li>
</references>
</qhelp>

View File

@@ -34,6 +34,10 @@ class SpringUrlRedirectFlowConfig extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) { sink instanceof SpringUrlRedirectSink }
override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
springUrlRedirectTaintStep(fromNode, toNode)
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof StartsWithSanitizer
}
@@ -57,6 +61,8 @@ class SpringUrlRedirectFlowConfig extends TaintTracking::Configuration {
not ma.getArgument(0).(CompileTimeConstantExpr).getStringValue().regexpMatch("^%s.*")
)
)
or
nonLocationHeaderSanitizer(node)
}
}

View File

@@ -35,8 +35,13 @@ class RedirectAppendCall extends MethodAccess {
}
/** A URL redirection sink from spring controller method. */
class SpringUrlRedirectSink extends DataFlow::Node {
SpringUrlRedirectSink() {
abstract class SpringUrlRedirectSink extends DataFlow::Node { }
/**
* A sink for URL Redirection via the Spring View classes.
*/
private class SpringViewUrlRedirectSink extends SpringUrlRedirectSink {
SpringViewUrlRedirectSink() {
exists(RedirectBuilderExpr rbe |
rbe.getRightOperand() = this.asExpr() and
any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable())
@@ -71,3 +76,64 @@ class SpringUrlRedirectSink extends DataFlow::Node {
)
}
}
/**
* A sink for URL Redirection via the `ResponseEntity` class.
*/
private class SpringResponseEntityUrlRedirectSink extends SpringUrlRedirectSink {
SpringResponseEntityUrlRedirectSink() {
// Find `new ResponseEntity(httpHeaders, ...)` or
// `new ResponseEntity(..., httpHeaders, ...)` sinks
exists(ClassInstanceExpr cie, Argument argument |
cie.getConstructedType() instanceof SpringResponseEntity and
argument.getType() instanceof SpringHttpHeaders and
argument = cie.getArgument([0, 1]) and
this.asExpr() = argument
)
or
// Find `ResponseEntity.status(...).headers(taintHeaders).build()` or
// `ResponseEntity.status(...).location(URI.create(taintURL)).build()` sinks
exists(MethodAccess ma |
ma.getMethod()
.getDeclaringType()
.hasQualifiedName("org.springframework.http", "ResponseEntity$HeadersBuilder<BodyBuilder>") and
ma.getMethod().getName() in ["headers", "location"] and
this.asExpr() = ma.getArgument(0)
)
}
}
private class HttpHeadersMethodAccess extends MethodAccess {
HttpHeadersMethodAccess() { this.getMethod().getDeclaringType() instanceof SpringHttpHeaders }
}
private class HttpHeadersAddSetMethodAccess extends HttpHeadersMethodAccess {
HttpHeadersAddSetMethodAccess() { this.getMethod().getName() in ["add", "set"] }
}
private class HttpHeadersSetLocationMethodAccess extends HttpHeadersMethodAccess {
HttpHeadersSetLocationMethodAccess() { this.getMethod().hasName("setLocation") }
}
/**
* Holds if `fromNode` to `toNode` is a dataflow step from a tainted argument to
* a `HttpHeaders` instance qualifier, i.e. `httpHeaders.setLocation(tainted)`.
*/
predicate springUrlRedirectTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
exists(HttpHeadersSetLocationMethodAccess ma |
fromNode.asExpr() = ma.getArgument(0) and
toNode.asExpr() = ma.getQualifier()
)
}
/**
* A sanitizer to exclude the cases where the `HttpHeaders.add` or `HttpHeaders.set`
* methods are called with a HTTP header other than "Location".
* E.g: `httpHeaders.add("X-Some-Header", taintedUrlString)`
*/
predicate nonLocationHeaderSanitizer(DataFlow::Node node) {
exists(HttpHeadersAddSetMethodAccess ma, Argument firstArg | node.asExpr() = ma.getArgument(1) |
firstArg = ma.getArgument(0) and
not firstArg.(CompileTimeConstantExpr).getStringValue().matches("Location")
)
}

View File

@@ -1,35 +1,90 @@
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 |
| SpringUrlRedirect.java:37:24:37:41 | redirectUrl : String | SpringUrlRedirect.java:40:29:40:39 | redirectUrl |
| SpringUrlRedirect.java:45:24:45:41 | redirectUrl : String | SpringUrlRedirect.java:48:30:48:40 | redirectUrl |
| SpringUrlRedirect.java:53:24:53:41 | redirectUrl : String | SpringUrlRedirect.java:54:30:54:66 | format(...) |
| SpringUrlRedirect.java:58:24:58:41 | redirectUrl : String | SpringUrlRedirect.java:59:30:59:76 | format(...) |
| SpringUrlRedirect.java:17:30:17:47 | redirectUrl : String | SpringUrlRedirect.java:19:19:19:29 | redirectUrl |
| SpringUrlRedirect.java:24:24:24:41 | redirectUrl : String | SpringUrlRedirect.java:25:36:25:46 | redirectUrl |
| SpringUrlRedirect.java:30:30:30:47 | redirectUrl : String | SpringUrlRedirect.java:31:44:31:54 | redirectUrl |
| SpringUrlRedirect.java:36:30:36:47 | redirectUrl : String | SpringUrlRedirect.java:37:47:37:57 | redirectUrl |
| SpringUrlRedirect.java:41:24:41:41 | redirectUrl : String | SpringUrlRedirect.java:44:29:44:39 | redirectUrl |
| SpringUrlRedirect.java:49:24:49:41 | redirectUrl : String | SpringUrlRedirect.java:52:30:52:40 | redirectUrl |
| SpringUrlRedirect.java:57:24:57:41 | redirectUrl : String | SpringUrlRedirect.java:58:30:58:66 | format(...) |
| SpringUrlRedirect.java:62:24:62:41 | redirectUrl : String | SpringUrlRedirect.java:63:30:63:76 | format(...) |
| SpringUrlRedirect.java:89:38:89:55 | redirectUrl : String | SpringUrlRedirect.java:91:38:91:48 | redirectUrl : String |
| SpringUrlRedirect.java:91:38:91:48 | redirectUrl : String | SpringUrlRedirect.java:91:27:91:49 | create(...) |
| SpringUrlRedirect.java:96:39:96:56 | redirectUrl : String | SpringUrlRedirect.java:98:44:98:54 | redirectUrl : String |
| SpringUrlRedirect.java:98:33:98:55 | create(...) : URI | SpringUrlRedirect.java:100:37:100:47 | httpHeaders |
| SpringUrlRedirect.java:98:44:98:54 | redirectUrl : String | SpringUrlRedirect.java:98:33:98:55 | create(...) : URI |
| SpringUrlRedirect.java:104:39:104:56 | redirectUrl : String | SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String |
| SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders | SpringUrlRedirect.java:108:68:108:78 | httpHeaders |
| SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] [<map.value>, <element>] : String | SpringUrlRedirect.java:108:68:108:78 | httpHeaders |
| SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders |
| SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] [<map.value>, <element>] : String |
| SpringUrlRedirect.java:112:39:112:56 | redirectUrl : String | SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String |
| SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders | SpringUrlRedirect.java:116:37:116:47 | httpHeaders |
| SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] [<map.value>, <element>] : String | SpringUrlRedirect.java:116:37:116:47 | httpHeaders |
| SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders |
| SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] [<map.value>, <element>] : String |
| SpringUrlRedirect.java:120:33:120:50 | redirectUrl : String | SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String |
| SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders | SpringUrlRedirect.java:124:49:124:59 | httpHeaders |
| SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] [<map.value>, <element>] : String | SpringUrlRedirect.java:124:49:124:59 | httpHeaders |
| SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders |
| SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] [<map.value>, <element>] : String |
| SpringUrlRedirect.java:128:33:128:50 | redirectUrl : String | SpringUrlRedirect.java:130:44:130:54 | redirectUrl : String |
| SpringUrlRedirect.java:130:33:130:55 | create(...) : URI | SpringUrlRedirect.java:132:49:132:59 | httpHeaders |
| SpringUrlRedirect.java:130:44:130:54 | redirectUrl : String | SpringUrlRedirect.java:130:33:130:55 | create(...) : URI |
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 |
| SpringUrlRedirect.java:37:24:37:41 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:40:29:40:39 | redirectUrl | semmle.label | redirectUrl |
| SpringUrlRedirect.java:45:24:45:41 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:48:30:48:40 | redirectUrl | semmle.label | redirectUrl |
| SpringUrlRedirect.java:53:24:53:41 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:54:30:54:66 | format(...) | semmle.label | format(...) |
| SpringUrlRedirect.java:58:24:58:41 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:59:30:59:76 | format(...) | semmle.label | format(...) |
| SpringUrlRedirect.java:17:30:17:47 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:19:19:19:29 | redirectUrl | semmle.label | redirectUrl |
| SpringUrlRedirect.java:24:24:24:41 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:25:36:25:46 | redirectUrl | semmle.label | redirectUrl |
| SpringUrlRedirect.java:30:30:30:47 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:31:44:31:54 | redirectUrl | semmle.label | redirectUrl |
| SpringUrlRedirect.java:36:30:36:47 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:37:47:37:57 | redirectUrl | semmle.label | redirectUrl |
| SpringUrlRedirect.java:41:24:41:41 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:44:29:44:39 | redirectUrl | semmle.label | redirectUrl |
| SpringUrlRedirect.java:49:24:49:41 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:52:30:52:40 | redirectUrl | semmle.label | redirectUrl |
| SpringUrlRedirect.java:57:24:57:41 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:58:30:58:66 | format(...) | semmle.label | format(...) |
| SpringUrlRedirect.java:62:24:62:41 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:63:30:63:76 | format(...) | semmle.label | format(...) |
| SpringUrlRedirect.java:89:38:89:55 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:91:27:91:49 | create(...) | semmle.label | create(...) |
| SpringUrlRedirect.java:91:38:91:48 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:96:39:96:56 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:98:33:98:55 | create(...) : URI | semmle.label | create(...) : URI |
| SpringUrlRedirect.java:98:44:98:54 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:100:37:100:47 | httpHeaders | semmle.label | httpHeaders |
| SpringUrlRedirect.java:104:39:104:56 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders | semmle.label | httpHeaders [post update] : HttpHeaders |
| SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] [<map.value>, <element>] : String | semmle.label | httpHeaders [post update] [<map.value>, <element>] : String |
| SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:108:68:108:78 | httpHeaders | semmle.label | httpHeaders |
| SpringUrlRedirect.java:112:39:112:56 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders | semmle.label | httpHeaders [post update] : HttpHeaders |
| SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] [<map.value>, <element>] : String | semmle.label | httpHeaders [post update] [<map.value>, <element>] : String |
| SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:116:37:116:47 | httpHeaders | semmle.label | httpHeaders |
| SpringUrlRedirect.java:120:33:120:50 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders | semmle.label | httpHeaders [post update] : HttpHeaders |
| SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] [<map.value>, <element>] : String | semmle.label | httpHeaders [post update] [<map.value>, <element>] : String |
| SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:124:49:124:59 | httpHeaders | semmle.label | httpHeaders |
| SpringUrlRedirect.java:128:33:128:50 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:130:33:130:55 | create(...) : URI | semmle.label | create(...) : URI |
| SpringUrlRedirect.java:130:44:130:54 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:132:49:132:59 | httpHeaders | semmle.label | httpHeaders |
#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 |
| SpringUrlRedirect.java:40:29:40:39 | redirectUrl | SpringUrlRedirect.java:37:24:37:41 | redirectUrl : String | SpringUrlRedirect.java:40:29:40:39 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:37:24:37:41 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:48:30:48:40 | redirectUrl | SpringUrlRedirect.java:45:24:45:41 | redirectUrl : String | SpringUrlRedirect.java:48:30:48:40 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:45:24:45:41 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:54:30:54:66 | format(...) | SpringUrlRedirect.java:53:24:53:41 | redirectUrl : String | SpringUrlRedirect.java:54:30:54:66 | format(...) | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:53:24:53:41 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:59:30:59:76 | format(...) | SpringUrlRedirect.java:58:24:58:41 | redirectUrl : String | SpringUrlRedirect.java:59:30:59:76 | format(...) | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:58:24:58:41 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:19:19:19:29 | redirectUrl | SpringUrlRedirect.java:17:30:17:47 | redirectUrl : String | SpringUrlRedirect.java:19:19:19:29 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:17:30:17:47 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:25:36:25:46 | redirectUrl | SpringUrlRedirect.java:24:24:24:41 | redirectUrl : String | SpringUrlRedirect.java:25:36:25:46 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:24:24:24:41 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:31:44:31:54 | redirectUrl | SpringUrlRedirect.java:30:30:30:47 | redirectUrl : String | SpringUrlRedirect.java:31:44:31:54 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:30:30:30:47 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:37:47:37:57 | redirectUrl | SpringUrlRedirect.java:36:30:36:47 | redirectUrl : String | SpringUrlRedirect.java:37:47:37:57 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:36:30:36:47 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:44:29:44:39 | redirectUrl | SpringUrlRedirect.java:41:24:41:41 | redirectUrl : String | SpringUrlRedirect.java:44:29:44:39 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:41:24:41:41 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:52:30:52:40 | redirectUrl | SpringUrlRedirect.java:49:24:49:41 | redirectUrl : String | SpringUrlRedirect.java:52:30:52:40 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:49:24:49:41 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:58:30:58:66 | format(...) | SpringUrlRedirect.java:57:24:57:41 | redirectUrl : String | SpringUrlRedirect.java:58:30:58:66 | format(...) | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:57:24:57:41 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:63:30:63:76 | format(...) | SpringUrlRedirect.java:62:24:62:41 | redirectUrl : String | SpringUrlRedirect.java:63:30:63:76 | format(...) | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:62:24:62:41 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:91:27:91:49 | create(...) | SpringUrlRedirect.java:89:38:89:55 | redirectUrl : String | SpringUrlRedirect.java:91:27:91:49 | create(...) | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:89:38:89:55 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:100:37:100:47 | httpHeaders | SpringUrlRedirect.java:96:39:96:56 | redirectUrl : String | SpringUrlRedirect.java:100:37:100:47 | httpHeaders | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:96:39:96:56 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:108:68:108:78 | httpHeaders | SpringUrlRedirect.java:104:39:104:56 | redirectUrl : String | SpringUrlRedirect.java:108:68:108:78 | httpHeaders | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:104:39:104:56 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:116:37:116:47 | httpHeaders | SpringUrlRedirect.java:112:39:112:56 | redirectUrl : String | SpringUrlRedirect.java:116:37:116:47 | httpHeaders | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:112:39:112:56 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:124:49:124:59 | httpHeaders | SpringUrlRedirect.java:120:33:120:50 | redirectUrl : String | SpringUrlRedirect.java:124:49:124:59 | httpHeaders | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:120:33:120:50 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:132:49:132:59 | httpHeaders | SpringUrlRedirect.java:128:33:128:50 | redirectUrl : String | SpringUrlRedirect.java:132:49:132:59 | httpHeaders | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:128:33:128:50 | redirectUrl | user-provided value |

View File

@@ -3,6 +3,10 @@ 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;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import java.net.URI;
@Controller
public class SpringUrlRedirect {
@@ -80,4 +84,51 @@ public class SpringUrlRedirect {
public String good3(String status) {
return "redirect:" + String.format("/stories/search/criteria?status=%s", status);
}
@GetMapping("url12")
public ResponseEntity<Void> bad9(String redirectUrl) {
return ResponseEntity.status(HttpStatus.FOUND)
.location(URI.create(redirectUrl))
.build();
}
@GetMapping("url13")
public ResponseEntity<Void> bad10(String redirectUrl) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setLocation(URI.create(redirectUrl));
return new ResponseEntity<>(httpHeaders, HttpStatus.SEE_OTHER);
}
@GetMapping("url14")
public ResponseEntity<Void> bad11(String redirectUrl) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Location", redirectUrl);
return ResponseEntity.status(HttpStatus.SEE_OTHER).headers(httpHeaders).build();
}
@GetMapping("url15")
public ResponseEntity<Void> bad12(String redirectUrl) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Location", redirectUrl);
return new ResponseEntity<>(httpHeaders, HttpStatus.SEE_OTHER);
}
@GetMapping("url16")
public ResponseEntity bad13(String redirectUrl) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Location", redirectUrl);
return new ResponseEntity<>("TestBody", httpHeaders, HttpStatus.SEE_OTHER);
}
@GetMapping("url17")
public ResponseEntity bad14(String redirectUrl) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setLocation(URI.create(redirectUrl));
return new ResponseEntity<>("TestBody", httpHeaders, HttpStatus.SEE_OTHER);
}
}