Skip to content

Commit e6a6a88

Browse files
committed
Move Jax XSS sinks to JaxWS.qll and add tests
1 parent d1fe62d commit e6a6a88

File tree

4 files changed

+73
-37
lines changed

4 files changed

+73
-37
lines changed

java/ql/src/semmle/code/java/frameworks/JaxWS.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import java
77
private import semmle.code.java.dataflow.ExternalFlow
8+
private import semmle.code.java.security.XSS
89

910
/**
1011
* Gets a name for the root package of JAX-RS.
@@ -308,6 +309,21 @@ class JaxRSConsumesAnnotation extends JaxRSAnnotation {
308309
JaxRSConsumesAnnotation() { this.getType().hasQualifiedName(getAJaxRsPackage(), "Consumes") }
309310
}
310311

312+
/** A default sink representing methods susceptible to XSS attacks. */
313+
private class JaxRSXssSink extends XssSink {
314+
JaxRSXssSink() {
315+
exists(JaxRsResourceMethod resourceMethod, ReturnStmt rs |
316+
resourceMethod = any(JaxRsResourceClass resourceClass).getAResourceMethod() and
317+
rs.getEnclosingCallable() = resourceMethod and
318+
this.asExpr() = rs.getResult()
319+
|
320+
not exists(resourceMethod.getProducesAnnotation())
321+
or
322+
resourceMethod.getProducesAnnotation().getADeclaredContentType() = "text/plain"
323+
)
324+
}
325+
}
326+
311327
/** A URL redirection sink from JAX-RS */
312328
private class JaxRsUrlRedirectSink extends SinkModelCsv {
313329
override predicate row(string row) {

java/ql/src/semmle/code/java/security/XSS.qll

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
/** Provides classes to reason about Cross-site scripting (XSS) vulnerabilities. */
22

33
import java
4-
import semmle.code.java.frameworks.JaxWS
54
import semmle.code.java.frameworks.Servlets
65
import semmle.code.java.frameworks.android.WebView
76
import semmle.code.java.frameworks.spring.SpringController
@@ -94,16 +93,6 @@ private class DefaultXssSink extends XssSink {
9493
returnType instanceof RawClass
9594
)
9695
)
97-
or
98-
exists(JaxRsResourceMethod resourceMethod, ReturnStmt rs |
99-
resourceMethod = any(JaxRsResourceClass resourceClass).getAResourceMethod() and
100-
rs.getEnclosingCallable() = resourceMethod and
101-
this.asExpr() = rs.getResult()
102-
|
103-
not exists(resourceMethod.getProducesAnnotation())
104-
or
105-
resourceMethod.getProducesAnnotation().getADeclaredContentType() = "text/plain"
106-
)
10796
}
10897
}
10998

java/ql/test/library-tests/frameworks/JaxWs/JaxRs.ql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import java
22
import semmle.code.java.frameworks.JaxWS
3+
import semmle.code.java.security.XSS
34
import TestUtilities.InlineExpectationsTest
45

56
class JaxRsTest extends InlineExpectationsTest {
@@ -143,5 +144,12 @@ class JaxRsTest extends InlineExpectationsTest {
143144
element = consumesAnnotation.toString() and
144145
value = ""
145146
)
147+
or
148+
tag = "XssSink" and
149+
exists(XssSink xssSink |
150+
xssSink.getLocation() = location and
151+
element = xssSink.toString() and
152+
value = ""
153+
)
146154
}
147155
}

java/ql/test/library-tests/frameworks/JaxWs/JaxRs1.java

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ public JaxRs1() { // $InjectableConstructor
3030
}
3131

3232
@GET
33-
void Get() { // $ResourceMethod $ResourceMethodOnResourceClass
33+
int Get() { // $ResourceMethod $ResourceMethodOnResourceClass
34+
return 0; // $XssSink
3435
}
3536

3637
@POST
@@ -39,7 +40,8 @@ void Post() { // $ResourceMethod $ResourceMethodOnResourceClass
3940

4041
@Produces("text/plain") // $ProducesAnnotation=text/plain
4142
@DELETE
42-
void Delete() { // $ResourceMethod=text/plain $ResourceMethodOnResourceClass
43+
double Delete() { // $ResourceMethod=text/plain $ResourceMethodOnResourceClass
44+
return 0.0; // $XssSink
4345
}
4446

4547
@Produces(MediaType.TEXT_HTML) // $ProducesAnnotation=text/html
@@ -59,27 +61,44 @@ void Head() { // $ResourceMethod $ResourceMethodOnResourceClass
5961
NonRootResourceClass subResourceLocator() { // $SubResourceLocator
6062
return null;
6163
}
62-
}
63-
64-
class NonRootResourceClass { // $NonRootResourceClass
65-
@Path("")
66-
AnotherNonRootResourceClass subResourceLocator1() { // $SubResourceLocator
67-
return null;
68-
}
6964

70-
@GET
71-
@Path("")
72-
NotAResourceClass1 NotASubResourceLocator1() { // $ResourceMethod
73-
return null;
74-
}
75-
76-
@GET
77-
NotAResourceClass2 NotASubResourceLocator2() { // $ResourceMethod
78-
return null;
79-
}
80-
81-
NotAResourceClass2 NotASubResourceLocator3() {
82-
return null;
65+
public class NonRootResourceClass { // $NonRootResourceClass
66+
@GET
67+
int Get() { // $ResourceMethod $ResourceMethodOnResourceClass
68+
return 0; // $XssSink
69+
}
70+
71+
@Produces("text/html") // $ProducesAnnotation=text/html
72+
@POST
73+
boolean Post() { // $ResourceMethod=text/html $ResourceMethodOnResourceClass
74+
return false;
75+
}
76+
77+
@Produces(MediaType.TEXT_PLAIN) // $ProducesAnnotation=text/plain
78+
@DELETE
79+
double Delete() { // $ResourceMethod=text/plain $ResourceMethodOnResourceClass
80+
return 0.0; // $XssSink
81+
}
82+
83+
@Path("")
84+
AnotherNonRootResourceClass subResourceLocator1() { // $SubResourceLocator
85+
return null;
86+
}
87+
88+
@GET
89+
@Path("")
90+
NotAResourceClass1 NotASubResourceLocator1() { // $ResourceMethod $ResourceMethodOnResourceClass
91+
return null; // $XssSink
92+
}
93+
94+
@GET
95+
NotAResourceClass2 NotASubResourceLocator2() { // $ResourceMethod $ResourceMethodOnResourceClass
96+
return null; // $XssSink
97+
}
98+
99+
NotAResourceClass2 NotASubResourceLocator3() {
100+
return null;
101+
}
83102
}
84103
}
85104

@@ -120,7 +139,8 @@ class NotAResourceClass2 {
120139

121140
class ExtendsJaxRs1 extends JaxRs1 {
122141
@Override
123-
void Get() { // $ResourceMethod
142+
int Get() { // $ResourceMethod
143+
return 1;
124144
}
125145

126146
@Override
@@ -129,7 +149,8 @@ void Post() {
129149
}
130150

131151
@Override
132-
void Delete() { // $ResourceMethod=text/plain
152+
double Delete() { // $ResourceMethod=text/plain
153+
return 1.0;
133154
}
134155

135156
@Override
@@ -151,7 +172,8 @@ void Head() {
151172
@Produces(MediaType.TEXT_XML) // $ProducesAnnotation=text/xml
152173
class ExtendsJaxRs1WithProducesAnnotation extends JaxRs1 {
153174
@Override
154-
void Get() { // $ResourceMethod=text/xml
175+
int Get() { // $ResourceMethod=text/xml
176+
return 2;
155177
}
156178

157179
@Override
@@ -160,7 +182,8 @@ void Post() {
160182
}
161183

162184
@Override
163-
void Delete() { // $ResourceMethod=text/plain
185+
double Delete() { // $ResourceMethod=text/plain
186+
return 2.0;
164187
}
165188

166189
@Override

0 commit comments

Comments
 (0)