Skip to content

Commit ddc544a

Browse files
committed
Initial support for Play Framework > 2.6.x
1 parent 7544bc8 commit ddc544a

40 files changed

+4683
-1
lines changed

java/ql/src/semmle/code/java/dataflow/FlowSources.qll

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import semmle.code.java.frameworks.android.WebView
1717
import semmle.code.java.frameworks.JaxWS
1818
import semmle.code.java.frameworks.javase.WebSocket
1919
import semmle.code.java.frameworks.android.Intent
20+
import semmle.code.java.frameworks.play.PlayController
21+
import semmle.code.java.frameworks.play.PlayHTTPRequestHeader
2022
import semmle.code.java.frameworks.spring.SpringWeb
2123
import semmle.code.java.frameworks.spring.SpringController
2224
import semmle.code.java.frameworks.spring.SpringWebClient
@@ -122,6 +124,18 @@ private class SpringMultipartRequestSource extends RemoteFlowSource {
122124
override string getSourceType() { result = "Spring MultipartRequest getter" }
123125
}
124126

127+
class PlayParameterSource extends RemoteFlowSource {
128+
PlayParameterSource() {
129+
exists(PlayActionQueryParameter p | p = this.asParameter())
130+
or
131+
exists(PlayHTTPRequestHeaderMethods m |
132+
m.hasName("getQueryString") and m.getAParameter() = this.asParameter()
133+
)
134+
}
135+
136+
override string getSourceType() { result = "Play Query Parameters" }
137+
}
138+
125139
private class SpringMultipartFileSource extends RemoteFlowSource {
126140
SpringMultipartFileSource() {
127141
exists(MethodAccess ma, Method m |
@@ -245,6 +259,7 @@ private class RemoteTaintedMethod extends Method {
245259
this instanceof HttpServletRequestGetRequestURIMethod or
246260
this instanceof HttpServletRequestGetRequestURLMethod or
247261
this instanceof HttpServletRequestGetRemoteUserMethod or
262+
this instanceof PlayRequestGetMethod or
248263
this instanceof SpringWebRequestGetMethod or
249264
this instanceof SpringRestTemplateResponseEntityMethod or
250265
this instanceof ServletRequestGetBodyMethod or
@@ -264,6 +279,13 @@ private class RemoteTaintedMethod extends Method {
264279
}
265280
}
266281

282+
private class PlayRequestGetMethod extends PlayHTTPRequestHeaderMethods {
283+
PlayRequestGetMethod() {
284+
this.hasName("Header") or
285+
this.hasName("getQueryString")
286+
}
287+
}
288+
267289
private class SpringWebRequestGetMethod extends Method {
268290
SpringWebRequestGetMethod() {
269291
exists(SpringWebRequest swr | this = swr.getAMethod() |
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import java
2+
import semmle.code.java.dataflow.FlowSources
3+
import semmle.code.java.frameworks.play.PlayController
4+
import semmle.code.java.frameworks.play.PlayAddCSRFToken
5+
import semmle.code.java.frameworks.play.PlayAsyncResult
6+
import semmle.code.java.frameworks.play.PlayBodyParser
7+
import semmle.code.java.frameworks.play.PlayHTTPRequestHeader
8+
import semmle.code.java.frameworks.play.PlayMVCResult
9+
import semmle.code.java.frameworks.play.PlayMVCResults
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import java
2+
3+
/**
4+
* Play Framework AddCSRFToken
5+
*
6+
* @description Gets the methods using AddCSRFToken annotation.
7+
* (https://www.playframework.com/documentation/2.6.x/JavaBodyParsers#Choosing-an-explicit-body-parser)
8+
*/
9+
class PlayAddCSRFTokenAnnotation extends Annotation {
10+
PlayAddCSRFTokenAnnotation() {
11+
this.getType().hasQualifiedName("play.filters.csrf", "AddCSRFToken")
12+
}
13+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import java
2+
3+
/**
4+
* Play Framework Async Promise of Generic Result
5+
*
6+
* @description Gets the Promise<Result> Generic Type of (play.libs.F), This is async in 2.6x and below.
7+
* (https://www.playframework.com/documentation/2.5.1/api/java/play/libs/F.Promise.html)
8+
*/
9+
class PlayAsyncResultPromise extends Member {
10+
PlayAsyncResultPromise() {
11+
exists(Class c |
12+
c.hasQualifiedName("play.libs", "F") and
13+
this = c.getAMember() and
14+
this.getQualifiedName() = "F.Promise<Result>"
15+
)
16+
}
17+
}
18+
19+
/**
20+
* Play Framework Async Generic Result extending generic promise API called CompletionStage.
21+
*
22+
* @description Gets the CompletionStage<Result> Generic Type of (java.util.concurrent)
23+
* (https://www.playframework.com/documentation/2.6.x/JavaAsync)
24+
*/
25+
class PlayAsyncResultCompletionStage extends Type {
26+
PlayAsyncResultCompletionStage() {
27+
this.hasName("CompletionStage<Result>") and
28+
this.getCompilationUnit().getPackage().hasName("java.util.concurrent")
29+
}
30+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import java
2+
3+
/**
4+
* Play Framework Explicit Body Parser
5+
*
6+
* @description Gets the methods using the explicit body parser annotation. The methods are usually controller action methods
7+
* (https://www.playframework.com/documentation/2.8.x/JavaBodyParsers#Choosing-an-explicit-body-parser)
8+
*/
9+
class PlayBodyParserAnnotation extends Annotation {
10+
PlayBodyParserAnnotation() { this.getType().hasQualifiedName("play.mvc", "BodyParser<>$Of") }
11+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import java
2+
import semmle.code.java.frameworks.play.PlayAsyncResult
3+
import semmle.code.java.frameworks.play.PlayMVCResult
4+
5+
/**
6+
* Play MVC Framework Controller
7+
*
8+
* @description Gets the play.mvc.Controller class
9+
*/
10+
class PlayMVCControllerClass extends Class {
11+
PlayMVCControllerClass() { this.hasQualifiedName("play.mvc", "Controller") }
12+
}
13+
14+
/**
15+
* Play Framework Controller which extends/implements
16+
*
17+
* @description Gets the classes which extends play.mvc.controller rescursively.
18+
*/
19+
class PlayController extends Class {
20+
PlayController() {
21+
exists(Class t | this.extendsOrImplements*(t) and t instanceof PlayMVCControllerClass)
22+
}
23+
}
24+
25+
/**
26+
* Play Framework Controller Action Methods
27+
*
28+
* @description Gets the controller action methods defined against it.
29+
* (https://www.playframework.com/documentation/2.8.x/JavaActions)
30+
* @tip Checking for Public methods usually retrieves direct controller mapped methods defined in routes.
31+
*/
32+
class PlayControllerActionMethod extends Method {
33+
PlayControllerActionMethod() {
34+
exists(PlayController controller |
35+
this = controller.getAMethod() and
36+
(
37+
this.getReturnType() instanceof PlayAsyncResultPromise or
38+
this.getReturnType() instanceof PlayMVCResult or
39+
this.getReturnType() instanceof PlayAsyncResultCompletionStage
40+
)
41+
)
42+
}
43+
}
44+
45+
/**
46+
* Play Action-Method parameters, these are essentially part of routes.
47+
*/
48+
class PlayActionQueryParameter extends Parameter {
49+
PlayActionQueryParameter() {
50+
exists(PlayControllerActionMethod a |
51+
a.isPublic() and
52+
this = a.getAParameter()
53+
)
54+
}
55+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import java
2+
3+
/**
4+
* Play MVC Framework HTTP Request Header
5+
*
6+
* @description Member of play.mvc.HTTP. Gets the play.mvc.HTTP$RequestHeader class/interface
7+
*/
8+
class PlayMVCHTTPRequestHeader extends RefType {
9+
PlayMVCHTTPRequestHeader() { this.hasQualifiedName("play.mvc", "Http$RequestHeader") }
10+
}
11+
12+
/**
13+
* Play Framework HTTP$RequestHeader Methods
14+
*
15+
* @description Gets the methods of play.mvc.HTTP$RequestHeader like - headers, getQueryString, getHeader, uri
16+
* (https://www.playframework.com/documentation/2.6.0/api/java/play/mvc/Http.RequestHeader.html)
17+
*/
18+
class PlayHTTPRequestHeaderMethods extends Method {
19+
PlayHTTPRequestHeaderMethods() { this.getDeclaringType() instanceof PlayMVCHTTPRequestHeader }
20+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import java
2+
3+
/**
4+
* Play MVC Framework Result
5+
*
6+
* @description Gets the play.mvc.Result class - Used to set a HTTP result with a status code, a set of HTTP headers and a body to be sent to the web client.
7+
* (https://www.playframework.com/documentation/2.8.x/JavaActions)
8+
*/
9+
class PlayMVCResult extends Class {
10+
PlayMVCResult() { this.hasQualifiedName("play.mvc", "Result") }
11+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import java
2+
3+
/**
4+
* Play MVC Framework Results
5+
*
6+
* @description Gets the play.mvc.Results class - Helper utilities to generate results
7+
* (https://www.playframework.com/documentation/2.8.x/JavaActions)
8+
*/
9+
class PlayMVCResults extends Class {
10+
PlayMVCResults() { this.hasQualifiedName("play.mvc", "Results") }
11+
}
12+
13+
/**
14+
* Play Framework mvc.Results Methods
15+
*
16+
* @description Gets the methods of play.mvc.Results like - ok, status, redirect etc.
17+
* (https://www.playframework.com/documentation/2.5.8/api/java/play/mvc/Results.html)
18+
*/
19+
class PlayHTTPResultsMethods extends Method {
20+
PlayHTTPResultsMethods() { this.getDeclaringType() instanceof PlayMVCResults }
21+
22+
/**
23+
* Gets all references to play.mvc.Results ok method
24+
*/
25+
MethodAccess ok() {
26+
exists(MethodAccess ma | ma = this.getAReference() and this.hasName("ok") | result = ma)
27+
}
28+
29+
/**
30+
* Gets all references to play.mvc.Results redirect method
31+
*/
32+
MethodAccess redirect() {
33+
exists(MethodAccess ma | ma = this.getAReference() and this.hasName("redirect") | result = ma)
34+
}
35+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import play.mvc.Controller;
2+
import play.mvc.Result;
3+
import play.filters.csrf.AddCSRFToken;
4+
import java.util.concurrent.CompletionStage;
5+
6+
7+
public class PlayResource extends Controller {
8+
9+
@AddCSRFToken
10+
public Result play_index(String username, String password) {
11+
String append_token = "password" + password;
12+
ok("Working");
13+
}
14+
}

0 commit comments

Comments
 (0)