mirror of
https://github.com/github/codeql.git
synced 2026-04-28 02:05:14 +02:00
Java: remove path-injection related models and tests for now
This commit is contained in:
@@ -1,155 +0,0 @@
|
||||
package com.example;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/** Sample class of Spring RestController */
|
||||
@RestController
|
||||
public class UnsafeLoadSpringResource {
|
||||
@GetMapping("/file1")
|
||||
//BAD: Get resource from ClassPathResource without input validation
|
||||
public String getFileContent1(@RequestParam(name="fileName") String fileName) {
|
||||
// A request such as the following can disclose source code and application configuration
|
||||
// fileName=/../../WEB-INF/views/page.jsp
|
||||
// fileName=/com/example/package/SampleController.class
|
||||
ClassPathResource clr = new ClassPathResource(fileName);
|
||||
char[] buffer = new char[4096];
|
||||
StringBuilder out = new StringBuilder();
|
||||
try {
|
||||
Reader in = new FileReader(clr.getFilename()); // $ hasUnsafeUrlForward (path-inj?)
|
||||
for (int numRead; (numRead = in.read(buffer, 0, buffer.length)) > 0; ) {
|
||||
out.append(buffer, 0, numRead);
|
||||
}
|
||||
} catch (IOException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
@GetMapping("/file1a")
|
||||
//GOOD: Get resource from ClassPathResource with input path validation
|
||||
public String getFileContent1a(@RequestParam(name="fileName") String fileName) {
|
||||
String result = null;
|
||||
if (fileName.startsWith("/safe_dir") && !fileName.contains("..")) {
|
||||
ClassPathResource clr = new ClassPathResource(fileName);
|
||||
char[] buffer = new char[4096];
|
||||
StringBuilder out = new StringBuilder();
|
||||
try {
|
||||
Reader in = new InputStreamReader(clr.getInputStream(), "UTF-8");
|
||||
for (int numRead; (numRead = in.read(buffer, 0, buffer.length)) > 0; ) {
|
||||
out.append(buffer, 0, numRead);
|
||||
}
|
||||
} catch (IOException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
result = out.toString();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@GetMapping("/file2")
|
||||
//BAD: Get resource from ResourceUtils without input validation
|
||||
public String getFileContent2(@RequestParam(name="fileName") String fileName) {
|
||||
String content = null;
|
||||
|
||||
try {
|
||||
// A request such as the following can disclose source code and system configuration
|
||||
// fileName=/etc/hosts
|
||||
// fileName=file:/etc/hosts
|
||||
// fileName=/opt/appdir/WEB-INF/views/page.jsp
|
||||
File file = ResourceUtils.getFile(fileName); // $ hasUnsafeUrlForward (path-inj?)
|
||||
//Read File Content
|
||||
content = new String(Files.readAllBytes(file.toPath()));
|
||||
} catch (IOException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
@GetMapping("/file2a")
|
||||
//GOOD: Get resource from ResourceUtils with input path validation
|
||||
public String getFileContent2a(@RequestParam(name="fileName") String fileName) {
|
||||
String content = null;
|
||||
|
||||
if (fileName.startsWith("/safe_dir") && !fileName.contains("..")) {
|
||||
try {
|
||||
File file = ResourceUtils.getFile(fileName);
|
||||
//Read File Content
|
||||
content = new String(Files.readAllBytes(file.toPath()));
|
||||
} catch (IOException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
ResourceLoader resourceLoader;
|
||||
|
||||
@GetMapping("/file3")
|
||||
//BAD: Get resource from ResourceLoader (same as application context) without input validation
|
||||
// Note it is not detected without the generic `resource.getInputStream()` check
|
||||
public String getFileContent3(@RequestParam(name="fileName") String fileName) {
|
||||
String content = null;
|
||||
|
||||
try {
|
||||
// A request such as the following can disclose source code and system configuration
|
||||
// fileName=/WEB-INF/views/page.jsp
|
||||
// fileName=/WEB-INF/classes/com/example/package/SampleController.class
|
||||
// fileName=file:/etc/hosts
|
||||
Resource resource = resourceLoader.getResource(fileName); // $ hasUnsafeUrlForward (path-inj?)
|
||||
|
||||
char[] buffer = new char[4096];
|
||||
StringBuilder out = new StringBuilder();
|
||||
|
||||
Reader in = new InputStreamReader(resource.getInputStream(), "UTF-8");
|
||||
for (int numRead; (numRead = in.read(buffer, 0, buffer.length)) > 0; ) {
|
||||
out.append(buffer, 0, numRead);
|
||||
}
|
||||
content = out.toString();
|
||||
} catch (IOException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
@GetMapping("/file3a")
|
||||
//GOOD: Get resource from ResourceLoader (same as application context) with input path validation
|
||||
public String getFileContent3a(@RequestParam(name="fileName") String fileName) {
|
||||
String content = null;
|
||||
|
||||
if (fileName.startsWith("/safe_dir") && !fileName.contains("..")) {
|
||||
try {
|
||||
Resource resource = resourceLoader.getResource(fileName);
|
||||
|
||||
char[] buffer = new char[4096];
|
||||
StringBuilder out = new StringBuilder();
|
||||
|
||||
Reader in = new InputStreamReader(resource.getInputStream(), "UTF-8");
|
||||
for (int numRead; (numRead = in.read(buffer, 0, buffer.length)) > 0; ) {
|
||||
out.append(buffer, 0, numRead);
|
||||
}
|
||||
content = out.toString();
|
||||
} catch (IOException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
return content;
|
||||
}
|
||||
}
|
||||
@@ -1,270 +0,0 @@
|
||||
package com.example;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import io.undertow.server.handlers.resource.FileResourceManager;
|
||||
import io.undertow.server.handlers.resource.Resource;
|
||||
import org.jboss.vfs.VFS;
|
||||
import org.jboss.vfs.VirtualFile;
|
||||
|
||||
public class UnsafeResourceGet extends HttpServlet {
|
||||
private static final String BASE_PATH = "/pages";
|
||||
|
||||
@Override
|
||||
// BAD: getResource constructed from `ServletContext` without input validation
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestUrl = request.getParameter("requestURL");
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
|
||||
ServletConfig cfg = getServletConfig();
|
||||
ServletContext sc = cfg.getServletContext();
|
||||
|
||||
// A sample request /fake.jsp/../WEB-INF/web.xml can load the web.xml file
|
||||
URL url = sc.getResource(requestUrl);
|
||||
|
||||
InputStream in = url.openStream(); // $ hasUnsafeUrlForward (SSRF)
|
||||
byte[] buf = new byte[4 * 1024]; // 4K buffer
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: getResource constructed from `ServletContext` with input validation
|
||||
protected void doGetGood(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestUrl = request.getParameter("requestURL");
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
|
||||
ServletConfig cfg = getServletConfig();
|
||||
ServletContext sc = cfg.getServletContext();
|
||||
|
||||
Path path = Paths.get(requestUrl).normalize().toRealPath();
|
||||
if (path.startsWith(BASE_PATH)) {
|
||||
URL url = sc.getResource(path.toString());
|
||||
|
||||
InputStream in = url.openStream();
|
||||
byte[] buf = new byte[4 * 1024]; // 4K buffer
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: getResource constructed from `ServletContext` with null check only
|
||||
protected void doGetGood2(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestUrl = request.getParameter("requestURL");
|
||||
PrintWriter writer = response.getWriter();
|
||||
|
||||
ServletConfig cfg = getServletConfig();
|
||||
ServletContext sc = cfg.getServletContext();
|
||||
|
||||
// A sample request /fake.jsp/../WEB-INF/web.xml can load the web.xml file
|
||||
URL url = sc.getResource(requestUrl);
|
||||
if (url == null) {
|
||||
writer.println("Requested source not found");
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: getResource constructed from `ServletContext` with `equals` check
|
||||
protected void doGetGood3(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestUrl = request.getParameter("requestURL");
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
|
||||
ServletContext sc = request.getServletContext();
|
||||
|
||||
if (requestUrl.equals("/public/crossdomain.xml")) {
|
||||
URL url = sc.getResource(requestUrl);
|
||||
|
||||
InputStream in = url.openStream();
|
||||
byte[] buf = new byte[4 * 1024]; // 4K buffer
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
// BAD: getResourceAsStream constructed from `ServletContext` without input validation
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestPath = request.getParameter("requestPath");
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
|
||||
// A sample request /fake.jsp/../WEB-INF/web.xml can load the web.xml file
|
||||
InputStream in = request.getServletContext().getResourceAsStream(requestPath); // $ hasUnsafeUrlForward (path-inj?)
|
||||
byte[] buf = new byte[4 * 1024]; // 4K buffer
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: getResourceAsStream constructed from `ServletContext` with input validation
|
||||
protected void doPostGood(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestPath = request.getParameter("requestPath");
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
|
||||
if (!requestPath.contains("..") && requestPath.startsWith("/trusted")) {
|
||||
InputStream in = request.getServletContext().getResourceAsStream(requestPath);
|
||||
byte[] buf = new byte[4 * 1024]; // 4K buffer
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
// BAD: getResource constructed from `Class` without input validation
|
||||
protected void doHead(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestUrl = request.getParameter("requestURL");
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
|
||||
// A sample request /fake.jsp/../../../WEB-INF/web.xml can load the web.xml file
|
||||
// Note the class is in two levels of subpackages and `Class.getResource` starts from its own directory
|
||||
URL url = getClass().getResource(requestUrl);
|
||||
|
||||
InputStream in = url.openStream(); // $ hasUnsafeUrlForward (SSRF)
|
||||
byte[] buf = new byte[4 * 1024]; // 4K buffer
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: getResource constructed from `Class` with input validation
|
||||
protected void doHeadGood(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestUrl = request.getParameter("requestURL");
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
|
||||
Path path = Paths.get(requestUrl).normalize().toRealPath();
|
||||
if (path.startsWith(BASE_PATH)) {
|
||||
URL url = getClass().getResource(path.toString());
|
||||
|
||||
InputStream in = url.openStream();
|
||||
byte[] buf = new byte[4 * 1024]; // 4K buffer
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
// BAD: getResourceAsStream constructed from `ClassLoader` without input validation
|
||||
protected void doPut(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestPath = request.getParameter("requestPath");
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
|
||||
ServletConfig cfg = getServletConfig();
|
||||
ServletContext sc = cfg.getServletContext();
|
||||
|
||||
// A sample request /fake.jsp/../../../WEB-INF/web.xml can load the web.xml file
|
||||
// Note the class is in two levels of subpackages and `ClassLoader.getResourceAsStream` starts from its own directory
|
||||
InputStream in = getClass().getClassLoader().getResourceAsStream(requestPath); // $ hasUnsafeUrlForward (path-inj?)
|
||||
byte[] buf = new byte[4 * 1024]; // 4K buffer
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: getResourceAsStream constructed from `ClassLoader` with input validation
|
||||
protected void doPutGood(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestPath = request.getParameter("requestPath");
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
|
||||
ServletConfig cfg = getServletConfig();
|
||||
ServletContext sc = cfg.getServletContext();
|
||||
|
||||
if (!requestPath.contains("..") && requestPath.startsWith("/trusted")) {
|
||||
InputStream in = getClass().getClassLoader().getResourceAsStream(requestPath);
|
||||
byte[] buf = new byte[4 * 1024]; // 4K buffer
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BAD: getResource constructed from `ClassLoader` without input validation
|
||||
protected void doPutBad(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestUrl = request.getParameter("requestURL");
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
|
||||
// A sample request /fake.jsp/../../../WEB-INF/web.xml can load the web.xml file
|
||||
// Note the class is in two levels of subpackages and `ClassLoader.getResource` starts from its own directory
|
||||
URL url = getClass().getClassLoader().getResource(requestUrl);
|
||||
|
||||
InputStream in = url.openStream(); // $ hasUnsafeUrlForward (SSRF)
|
||||
byte[] buf = new byte[4 * 1024]; // 4K buffer
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
// BAD: getResource constructed using Undertow IO without input validation
|
||||
protected void doPutBad2(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestPath = request.getParameter("requestPath");
|
||||
|
||||
try {
|
||||
FileResourceManager rm = new FileResourceManager(VFS.getChild(new URI("/usr/share")).getPhysicalFile());
|
||||
Resource rs = rm.getResource(requestPath);
|
||||
|
||||
VirtualFile overlay = VFS.getChild(new URI("EAP_HOME/modules/"));
|
||||
// Do file operations
|
||||
overlay.getChild(rs.getPath()); // $ hasUnsafeUrlForward (path-inj?)
|
||||
} catch (URISyntaxException ue) {
|
||||
throw new IOException("Cannot parse the URI");
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: getResource constructed using Undertow IO with input validation
|
||||
protected void doPutGood2(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String requestPath = request.getParameter("requestPath");
|
||||
|
||||
try {
|
||||
FileResourceManager rm = new FileResourceManager(VFS.getChild(new URI("/usr/share")).getPhysicalFile());
|
||||
Resource rs = rm.getResource(requestPath);
|
||||
|
||||
VirtualFile overlay = VFS.getChild(new URI("EAP_HOME/modules/"));
|
||||
String path = rs.getPath();
|
||||
if (path.startsWith("/trusted_path") && !path.contains("..")) {
|
||||
// Do file operations
|
||||
overlay.getChild(path);
|
||||
}
|
||||
} catch (URISyntaxException ue) {
|
||||
throw new IOException("Cannot parse the URI");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package com.example;
|
||||
|
||||
import javax.faces.context.FacesContext;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
/** Sample class of JSF managed bean */
|
||||
public class UnsafeResourceGet2 {
|
||||
// BAD: getResourceAsStream constructed from `ExternalContext` without input validation
|
||||
public String parameterActionBad1() throws IOException {
|
||||
FacesContext fc = FacesContext.getCurrentInstance();
|
||||
Map<String, String> params = fc.getExternalContext().getRequestParameterMap();
|
||||
String loadUrl = params.get("loadUrl");
|
||||
|
||||
InputStreamReader isr = new InputStreamReader(fc.getExternalContext().getResourceAsStream(loadUrl)); // $ hasUnsafeUrlForward (path-inj?)
|
||||
BufferedReader br = new BufferedReader(isr);
|
||||
if(br.ready()) {
|
||||
//Do Stuff
|
||||
return "result";
|
||||
}
|
||||
|
||||
return "home";
|
||||
}
|
||||
|
||||
// BAD: getResource constructed from `ExternalContext` without input validation
|
||||
public String parameterActionBad2() throws IOException {
|
||||
FacesContext fc = FacesContext.getCurrentInstance();
|
||||
Map<String, String> params = fc.getExternalContext().getRequestParameterMap();
|
||||
String loadUrl = params.get("loadUrl");
|
||||
|
||||
URL url = fc.getExternalContext().getResource(loadUrl);
|
||||
|
||||
InputStream in = url.openStream(); // $ hasUnsafeUrlForward (SSRF)
|
||||
//Do Stuff
|
||||
return "result";
|
||||
}
|
||||
|
||||
// GOOD: getResource constructed from `ExternalContext` with input validation
|
||||
public String parameterActionGood1() throws IOException {
|
||||
FacesContext fc = FacesContext.getCurrentInstance();
|
||||
Map<String, String> params = fc.getExternalContext().getRequestParameterMap();
|
||||
String loadUrl = params.get("loadUrl");
|
||||
|
||||
if (loadUrl.equals("/public/crossdomain.xml")) {
|
||||
URL url = fc.getExternalContext().getResource(loadUrl);
|
||||
|
||||
InputStream in = url.openStream();
|
||||
//Do Stuff
|
||||
return "result";
|
||||
}
|
||||
|
||||
return "home";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user