|
1 | 1 | import java |
2 | 2 | import semmle.code.java.frameworks.Servlets |
3 | 3 | import semmle.code.java.frameworks.android.WebView |
| 4 | +import semmle.code.java.frameworks.spring.SpringController |
| 5 | +import semmle.code.java.frameworks.spring.SpringHttp |
4 | 6 | import semmle.code.java.dataflow.TaintTracking |
5 | 7 |
|
6 | 8 | /* |
@@ -30,6 +32,42 @@ class XssSink extends DataFlow::ExprNode { |
30 | 32 | m.getAReference().getArgument(1) = this.getExpr() and m.getName() = "loadDataWithBaseURL" |
31 | 33 | ) |
32 | 34 | ) |
| 35 | + or |
| 36 | + exists(SpringRequestMappingMethod requestMappingMethod, ReturnStmt rs | |
| 37 | + requestMappingMethod = rs.getEnclosingCallable() and |
| 38 | + this.asExpr() = rs.getResult() | |
| 39 | + // If a Spring request mapping method is either annotated with @ResponseBody (or equivalent), |
| 40 | + // or returns a HttpEntity or sub-type, then the return value of the method is converted into |
| 41 | + // a HTTP reponse using a HttpMessageConverter implementation. The implementation is chosen |
| 42 | + // based on the return type of the method, and the Accept header of the request. |
| 43 | + |
| 44 | + // By default, the only message converter which produces a response which is vulnerable to |
| 45 | + // XSS is the StringHttpMessageConverter, which "Accept"s all text/* content types, including |
| 46 | + // text/html. Therefore, if a browser request includes "text/html" in the "Accept" header, |
| 47 | + // any String returned will be converted into a text/html response. |
| 48 | + requestMappingMethod.isResponseBody() and requestMappingMethod.getReturnType() instanceof TypeString |
| 49 | + or |
| 50 | + exists(Type returnType | |
| 51 | + // A return type of HttpEntity<T> or ResponseEntity<T> represents a HTTP response with both |
| 52 | + // a body and a set of headers. The body is subject to the same HttpMessageConverter |
| 53 | + // process as above. |
| 54 | + returnType = requestMappingMethod.getReturnType() and |
| 55 | + ( |
| 56 | + returnType instanceof SpringHttpEntity |
| 57 | + or |
| 58 | + returnType instanceof SpringResponseEntity |
| 59 | + ) |
| 60 | + | |
| 61 | + // The type argument, representing the type of the body, is type String |
| 62 | + returnType.(ParameterizedClass).getTypeArgument(0) instanceof TypeString |
| 63 | + or |
| 64 | + // Return type is a Raw class, which means no static type information on the body. In this |
| 65 | + // case we will still treat this as an XSS sink, but rely on our taint flow steps for |
| 66 | + // HttpEntity/ResponseEntity to only pass taint into those instances if the body type was |
| 67 | + // String. |
| 68 | + returnType instanceof RawClass |
| 69 | + ) |
| 70 | + ) |
33 | 71 | } |
34 | 72 | } |
35 | 73 |
|
|
0 commit comments