mirror of
https://github.com/github/codeql.git
synced 2026-05-01 11:45:14 +02:00
Share SpringUrlRedirect library
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
import SpringUrlRedirect
|
||||
import experimental.semmle.code.java.security.SpringUrlRedirect
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.controlflow.Guards
|
||||
import DataFlow::PathGraph
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
import experimental.semmle.code.java.security.SpringUrlRedirect
|
||||
import semmle.code.java.controlflow.Guards
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.UrlRedirect
|
||||
import DataFlow::PathGraph
|
||||
import Regex
|
||||
import SpringUrlRedirect
|
||||
|
||||
/** Source model of remote flow source with servlets. */
|
||||
private class GetServletUriSource extends SourceModelCsv {
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
/** Provides methods related to Spring URL redirect from /src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll. */
|
||||
|
||||
private import java
|
||||
private import semmle.code.java.dataflow.FlowSources
|
||||
|
||||
/**
|
||||
* A concatenate expression using the string `redirect:` or `ajaxredirect:` or `forward:` on the left.
|
||||
*
|
||||
* E.g: `"redirect:" + redirectUrl`
|
||||
*/
|
||||
class RedirectBuilderExpr extends AddExpr {
|
||||
RedirectBuilderExpr() {
|
||||
this.getLeftOperand().(CompileTimeConstantExpr).getStringValue() in [
|
||||
"redirect:", "ajaxredirect:", "forward:"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `StringBuilder.append` or `StringBuffer.append` method, and the parameter value is
|
||||
* `"redirect:"` or `"ajaxredirect:"` or `"forward:"`.
|
||||
*
|
||||
* E.g: `StringBuilder.append("redirect:")`
|
||||
*/
|
||||
class RedirectAppendCall extends MethodAccess {
|
||||
RedirectAppendCall() {
|
||||
this.getMethod().hasName("append") and
|
||||
this.getMethod().getDeclaringType() instanceof StringBuildingType and
|
||||
this.getArgument(0).(CompileTimeConstantExpr).getStringValue() in [
|
||||
"redirect:", "ajaxredirect:", "forward:"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/** A URL redirection sink from spring controller method. */
|
||||
abstract class SpringUrlRedirectSink extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A sink for URL Redirection via the Spring View classes.
|
||||
*/
|
||||
private class SpringViewUrlRedirectSink extends SpringUrlRedirectSink {
|
||||
SpringViewUrlRedirectSink() {
|
||||
// Hardcoded redirect such as "redirect:login"
|
||||
this.asExpr()
|
||||
.(CompileTimeConstantExpr)
|
||||
.getStringValue()
|
||||
.indexOf(["redirect:", "ajaxredirect:", "forward:"]) = 0 and
|
||||
any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable())
|
||||
or
|
||||
exists(RedirectBuilderExpr rbe |
|
||||
rbe.getRightOperand() = this.asExpr() and
|
||||
any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable())
|
||||
)
|
||||
or
|
||||
exists(MethodAccess ma, RedirectAppendCall rac |
|
||||
DataFlow2::localExprFlow(rac.getQualifier(), ma.getQualifier()) and
|
||||
ma.getMethod().hasName("append") and
|
||||
ma.getArgument(0) = this.asExpr() and
|
||||
any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable())
|
||||
)
|
||||
or
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod().hasName("setUrl") and
|
||||
ma.getMethod()
|
||||
.getDeclaringType()
|
||||
.hasQualifiedName("org.springframework.web.servlet.view", "AbstractUrlBasedView") and
|
||||
ma.getArgument(0) = this.asExpr()
|
||||
)
|
||||
or
|
||||
exists(ClassInstanceExpr cie |
|
||||
cie.getConstructedType()
|
||||
.hasQualifiedName("org.springframework.web.servlet.view", "RedirectView") and
|
||||
cie.getArgument(0) = this.asExpr()
|
||||
)
|
||||
or
|
||||
exists(ClassInstanceExpr cie |
|
||||
cie.getConstructedType().hasQualifiedName("org.springframework.web.servlet", "ModelAndView") and
|
||||
exists(RedirectBuilderExpr rbe |
|
||||
rbe = cie.getArgument(0) and rbe.getRightOperand() = this.asExpr()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
import java
|
||||
import DataFlow
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.dataflow.DataFlow2
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.frameworks.spring.SpringController
|
||||
/** Provides classes and predicates related to Spring URL redirect. */
|
||||
|
||||
private import java
|
||||
private import semmle.code.java.dataflow.FlowSources
|
||||
|
||||
/**
|
||||
* A concatenate expression using the string `redirect:` or `ajaxredirect:` or `forward:` on the left.
|
||||
@@ -42,6 +40,13 @@ abstract class SpringUrlRedirectSink extends DataFlow::Node { }
|
||||
*/
|
||||
private class SpringViewUrlRedirectSink extends SpringUrlRedirectSink {
|
||||
SpringViewUrlRedirectSink() {
|
||||
// Hardcoded redirect such as "redirect:login"
|
||||
this.asExpr()
|
||||
.(CompileTimeConstantExpr)
|
||||
.getStringValue()
|
||||
.indexOf(["redirect:", "ajaxredirect:", "forward:"]) = 0 and
|
||||
any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable())
|
||||
or
|
||||
exists(RedirectBuilderExpr rbe |
|
||||
rbe.getRightOperand() = this.asExpr() and
|
||||
any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable())
|
||||
Reference in New Issue
Block a user