Skip to content

Commit 0aa1251

Browse files
committed
Add more test cases
1 parent 590b9d8 commit 0aa1251

File tree

10 files changed

+281
-33
lines changed

10 files changed

+281
-33
lines changed

java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,15 +160,17 @@ private class ServletGetPathSource extends SourceModelCsv {
160160
}
161161
}
162162

163-
/** Taint model related to `java.nio.file.Path`. */
163+
/** Taint model related to `java.nio.file.Path` and `io.undertow.server.handlers.resource.Resource`. */
164164
private class FilePathFlowStep extends SummaryModelCsv {
165165
override predicate row(string row) {
166166
row =
167167
[
168168
"java.nio.file;Paths;true;get;;;Argument[0..1];ReturnValue;taint",
169169
"java.nio.file;Path;true;resolve;;;Argument[-1..0];ReturnValue;taint",
170170
"java.nio.file;Path;true;normalize;;;Argument[-1];ReturnValue;taint",
171-
"java.nio.file;Path;true;toString;;;Argument[-1];ReturnValue;taint"
171+
"io.undertow.server.handlers.resource;Resource;true;getFile;;;Argument[-1];ReturnValue;taint",
172+
"io.undertow.server.handlers.resource;Resource;true;getFilePath;;;Argument[-1];ReturnValue;taint",
173+
"io.undertow.server.handlers.resource;Resource;true;getPath;;;Argument[-1];ReturnValue;taint"
172174
]
173175
}
174176
}

java/ql/src/experimental/semmle/code/java/frameworks/Jsf.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Provides classes and predicates for working with the Java Server Faces (JSF).
33
*/
44

5-
import semmle.code.java.Type
5+
import java
66

77
/**
88
* The JSF class `ExternalContext` for processing HTTP requests.

java/ql/test/experimental/query-tests/security/CWE-552/UnsafeResourceGet.java

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import java.io.PrintWriter;
66
import java.nio.file.Path;
77
import java.nio.file.Paths;
8+
import java.net.URI;
89
import java.net.URL;
10+
import java.net.URISyntaxException;
911

1012
import javax.servlet.http.HttpServlet;
1113
import javax.servlet.http.HttpServletRequest;
@@ -15,6 +17,11 @@
1517
import javax.servlet.ServletConfig;
1618
import javax.servlet.ServletContext;
1719

20+
import io.undertow.server.handlers.resource.FileResourceManager;
21+
import io.undertow.server.handlers.resource.Resource;
22+
import org.jboss.vfs.VFS;
23+
import org.jboss.vfs.VirtualFile;
24+
1825
public class UnsafeResourceGet extends HttpServlet {
1926
private static final String BASE_PATH = "/pages";
2027

@@ -137,7 +144,7 @@ protected void doHead(HttpServletRequest request, HttpServletResponse response)
137144
ServletOutputStream out = response.getOutputStream();
138145

139146
// A sample request /fake.jsp/../../../WEB-INF/web.xml can load the web.xml file
140-
// Note the class is in two levels of subpackages and `Class.loadResource` starts from its own directory
147+
// Note the class is in two levels of subpackages and `Class.getResource` starts from its own directory
141148
URL url = getClass().getResource(requestUrl);
142149

143150
InputStream in = url.openStream();
@@ -205,4 +212,59 @@ protected void doPutGood(HttpServletRequest request, HttpServletResponse respons
205212
}
206213
}
207214
}
215+
216+
// BAD: getResource constructed from `ClassLoader` without input validation
217+
protected void doPutBad(HttpServletRequest request, HttpServletResponse response)
218+
throws ServletException, IOException {
219+
String requestUrl = request.getParameter("requestURL");
220+
ServletOutputStream out = response.getOutputStream();
221+
222+
// A sample request /fake.jsp/../../../WEB-INF/web.xml can load the web.xml file
223+
// Note the class is in two levels of subpackages and `ClassLoader.getResource` starts from its own directory
224+
URL url = getClass().getClassLoader().getResource(requestUrl);
225+
226+
InputStream in = url.openStream();
227+
byte[] buf = new byte[4 * 1024]; // 4K buffer
228+
int bytesRead;
229+
while ((bytesRead = in.read(buf)) != -1) {
230+
out.write(buf, 0, bytesRead);
231+
}
232+
}
233+
234+
// BAD: getResource constructed using Undertow IO without input validation
235+
protected void doPutBad2(HttpServletRequest request, HttpServletResponse response)
236+
throws ServletException, IOException {
237+
String requestPath = request.getParameter("requestPath");
238+
239+
try {
240+
FileResourceManager rm = new FileResourceManager(VFS.getChild(new URI("/usr/share")).getPhysicalFile());
241+
Resource rs = rm.getResource(requestPath);
242+
243+
VirtualFile overlay = VFS.getChild(new URI("EAP_HOME/modules/"));
244+
// Do file operations
245+
overlay.getChild(rs.getPath());
246+
} catch (URISyntaxException ue) {
247+
throw new IOException("Cannot parse the URI");
248+
}
249+
}
250+
251+
// GOOD: getResource constructed using Undertow IO with input validation
252+
protected void doPutGood2(HttpServletRequest request, HttpServletResponse response)
253+
throws ServletException, IOException {
254+
String requestPath = request.getParameter("requestPath");
255+
256+
try {
257+
FileResourceManager rm = new FileResourceManager(VFS.getChild(new URI("/usr/share")).getPhysicalFile());
258+
Resource rs = rm.getResource(requestPath);
259+
260+
VirtualFile overlay = VFS.getChild(new URI("EAP_HOME/modules/"));
261+
String path = rs.getPath();
262+
if (path.startsWith("/trusted_path") && !path.contains("..")) {
263+
// Do file operations
264+
overlay.getChild(path);
265+
}
266+
} catch (URISyntaxException ue) {
267+
throw new IOException("Cannot parse the URI");
268+
}
269+
}
208270
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.example;
2+
3+
import javax.faces.context.FacesContext;
4+
import java.io.BufferedReader;
5+
import java.io.InputStream;
6+
import java.io.InputStreamReader;
7+
import java.io.IOException;
8+
import java.net.URL;
9+
import java.util.Map;
10+
11+
/** Sample class of JSF managed bean */
12+
public class UnsafeResourceGet2 {
13+
// BAD: getResourceAsStream constructed from `ExternalContext` without input validation
14+
public String parameterActionBad1() throws IOException {
15+
FacesContext fc = FacesContext.getCurrentInstance();
16+
Map<String, String> params = fc.getExternalContext().getRequestParameterMap();
17+
String loadUrl = params.get("loadUrl");
18+
19+
InputStreamReader isr = new InputStreamReader(fc.getExternalContext().getResourceAsStream(loadUrl));
20+
BufferedReader br = new BufferedReader(isr);
21+
if(br.ready()) {
22+
//Do Stuff
23+
return "result";
24+
}
25+
26+
return "home";
27+
}
28+
29+
// BAD: getResource constructed from `ExternalContext` without input validation
30+
public String parameterActionBad2() throws IOException {
31+
FacesContext fc = FacesContext.getCurrentInstance();
32+
Map<String, String> params = fc.getExternalContext().getRequestParameterMap();
33+
String loadUrl = params.get("loadUrl");
34+
35+
URL url = fc.getExternalContext().getResource(loadUrl);
36+
37+
InputStream in = url.openStream();
38+
//Do Stuff
39+
return "result";
40+
}
41+
42+
// GOOD: getResource constructed from `ExternalContext` with input validation
43+
public String parameterActionGood1() throws IOException {
44+
FacesContext fc = FacesContext.getCurrentInstance();
45+
Map<String, String> params = fc.getExternalContext().getRequestParameterMap();
46+
String loadUrl = params.get("loadUrl");
47+
48+
if (loadUrl.equals("/public/crossdomain.xml")) {
49+
URL url = fc.getExternalContext().getResource(loadUrl);
50+
51+
InputStream in = url.openStream();
52+
//Do Stuff
53+
return "result";
54+
}
55+
56+
return "home";
57+
}
58+
}

0 commit comments

Comments
 (0)