mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge pull request #7712 from luchua-bc/java/file-path-injection
Java: CWE-073 File path injection with the JFinal framework
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
edges
|
||||
| FilePathInjection.java:21:21:21:34 | getPara(...) : String | FilePathInjection.java:26:47:26:59 | finalFilePath |
|
||||
| FilePathInjection.java:64:21:64:34 | getPara(...) : String | FilePathInjection.java:72:47:72:59 | finalFilePath |
|
||||
| FilePathInjection.java:87:21:87:34 | getPara(...) : String | FilePathInjection.java:95:47:95:59 | finalFilePath |
|
||||
| FilePathInjection.java:205:17:205:44 | getParameter(...) : String | FilePathInjection.java:209:24:209:31 | filePath |
|
||||
nodes
|
||||
| FilePathInjection.java:21:21:21:34 | getPara(...) : String | semmle.label | getPara(...) : String |
|
||||
| FilePathInjection.java:26:47:26:59 | finalFilePath | semmle.label | finalFilePath |
|
||||
| FilePathInjection.java:64:21:64:34 | getPara(...) : String | semmle.label | getPara(...) : String |
|
||||
| FilePathInjection.java:72:47:72:59 | finalFilePath | semmle.label | finalFilePath |
|
||||
| FilePathInjection.java:87:21:87:34 | getPara(...) : String | semmle.label | getPara(...) : String |
|
||||
| FilePathInjection.java:95:47:95:59 | finalFilePath | semmle.label | finalFilePath |
|
||||
| FilePathInjection.java:205:17:205:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| FilePathInjection.java:209:24:209:31 | filePath | semmle.label | filePath |
|
||||
subpaths
|
||||
#select
|
||||
| FilePathInjection.java:26:47:26:59 | finalFilePath | FilePathInjection.java:21:21:21:34 | getPara(...) : String | FilePathInjection.java:26:47:26:59 | finalFilePath | External control of file name or path due to $@. | FilePathInjection.java:21:21:21:34 | getPara(...) | user-provided value |
|
||||
| FilePathInjection.java:72:47:72:59 | finalFilePath | FilePathInjection.java:64:21:64:34 | getPara(...) : String | FilePathInjection.java:72:47:72:59 | finalFilePath | External control of file name or path due to $@. | FilePathInjection.java:64:21:64:34 | getPara(...) | user-provided value |
|
||||
| FilePathInjection.java:95:47:95:59 | finalFilePath | FilePathInjection.java:87:21:87:34 | getPara(...) : String | FilePathInjection.java:95:47:95:59 | finalFilePath | External control of file name or path due to $@. | FilePathInjection.java:87:21:87:34 | getPara(...) | user-provided value |
|
||||
| FilePathInjection.java:209:24:209:31 | filePath | FilePathInjection.java:205:17:205:44 | getParameter(...) : String | FilePathInjection.java:209:24:209:31 | filePath | External control of file name or path due to $@. | FilePathInjection.java:205:17:205:44 | getParameter(...) | user-provided value |
|
||||
@@ -0,0 +1,245 @@
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import com.jfinal.core.Controller;
|
||||
|
||||
public class FilePathInjection extends Controller {
|
||||
private static final String BASE_PATH = "/pages";
|
||||
|
||||
// BAD: Upload file to user specified path without validation
|
||||
public void uploadFile() throws IOException {
|
||||
String savePath = getPara("dir");
|
||||
File file = getFile("fileParam").getFile();
|
||||
String finalFilePath = BASE_PATH + savePath;
|
||||
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
FileOutputStream fos = new FileOutputStream(finalFilePath);
|
||||
int i = 0;
|
||||
|
||||
do {
|
||||
byte[] buf = new byte[1024];
|
||||
i = fis.read(buf);
|
||||
fos.write(buf);
|
||||
} while (i != -1);
|
||||
|
||||
fis.close();
|
||||
fos.close();
|
||||
}
|
||||
|
||||
// GOOD: Upload file to user specified path with path normalization and validation
|
||||
public void uploadFile2() throws IOException {
|
||||
String savePath = getPara("dir");
|
||||
File file = getFile("fileParam").getFile();
|
||||
String finalFilePath = BASE_PATH + savePath;
|
||||
Path path = Paths.get(finalFilePath).normalize();
|
||||
|
||||
if (path.startsWith(BASE_PATH)) {
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
FileOutputStream fos = new FileOutputStream(path.toFile());
|
||||
int i = 0;
|
||||
|
||||
do {
|
||||
byte[] buf = new byte[1024];
|
||||
i = fis.read(buf);
|
||||
fos.write(buf);
|
||||
} while (i != -1);
|
||||
|
||||
fis.close();
|
||||
fos.close();
|
||||
}
|
||||
}
|
||||
|
||||
// BAD: Upload file to user specified path without validation through session attribute
|
||||
public void uploadFile3() throws IOException {
|
||||
String savePath = getPara("dir");
|
||||
setSessionAttr("uploadDir", savePath);
|
||||
String sessionUploadDir = getSessionAttr("uploadDir");
|
||||
|
||||
File file = getFile("fileParam").getFile();
|
||||
String finalFilePath = BASE_PATH + sessionUploadDir;
|
||||
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
FileOutputStream fos = new FileOutputStream(finalFilePath);
|
||||
int i = 0;
|
||||
|
||||
do {
|
||||
byte[] buf = new byte[1024];
|
||||
i = fis.read(buf);
|
||||
fos.write(buf);
|
||||
} while (i != -1);
|
||||
|
||||
fis.close();
|
||||
fos.close();
|
||||
}
|
||||
|
||||
// BAD: Upload file to user specified path without validation through request attribute
|
||||
public void uploadFile4() throws IOException {
|
||||
String savePath = getPara("dir");
|
||||
setAttr("uploadDir2", savePath);
|
||||
String requestUploadDir = getAttr("uploadDir2");
|
||||
|
||||
File file = getFile("fileParam").getFile();
|
||||
String finalFilePath = BASE_PATH + requestUploadDir;
|
||||
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
FileOutputStream fos = new FileOutputStream(finalFilePath);
|
||||
int i = 0;
|
||||
|
||||
do {
|
||||
byte[] buf = new byte[1024];
|
||||
i = fis.read(buf);
|
||||
fos.write(buf);
|
||||
} while (i != -1);
|
||||
|
||||
fis.close();
|
||||
fos.close();
|
||||
}
|
||||
|
||||
// BAD: Upload file to user specified path without validation through session object (not detected)
|
||||
public void uploadFile5() throws IOException {
|
||||
String savePath = getPara("dir");
|
||||
getSession().setAttribute("uploadDir3", savePath);
|
||||
String sessionUploadDir = getSessionAttr("uploadDir3");
|
||||
|
||||
File file = getFile("fileParam").getFile();
|
||||
String finalFilePath = BASE_PATH + sessionUploadDir;
|
||||
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
FileOutputStream fos = new FileOutputStream(finalFilePath);
|
||||
int i = 0;
|
||||
|
||||
do {
|
||||
byte[] buf = new byte[1024];
|
||||
i = fis.read(buf);
|
||||
fos.write(buf);
|
||||
} while (i != -1);
|
||||
|
||||
fis.close();
|
||||
fos.close();
|
||||
}
|
||||
|
||||
// GOOD: Upload file to a system path from a request object
|
||||
public void uploadFile6() throws IOException {
|
||||
setAttr("uploadDir4", "/data/upload_dir/");
|
||||
String requestUploadDir = getAttr("uploadDir4");
|
||||
|
||||
File file = getFile("fileParam").getFile();
|
||||
String finalFilePath = BASE_PATH + requestUploadDir;
|
||||
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
FileOutputStream fos = new FileOutputStream(finalFilePath);
|
||||
int i = 0;
|
||||
|
||||
do {
|
||||
byte[] buf = new byte[1024];
|
||||
i = fis.read(buf);
|
||||
fos.write(buf);
|
||||
} while (i != -1);
|
||||
|
||||
fis.close();
|
||||
fos.close();
|
||||
}
|
||||
|
||||
// GOOD: Upload file to a system path from a request object
|
||||
public void uploadFile7() throws IOException {
|
||||
String savePath = getPara("dir");
|
||||
setAttr("uploadDir5", savePath);
|
||||
setAttr("realUploadDir", "/data/upload_dir/");
|
||||
String requestUploadDir = getAttr("realUploadDir5");
|
||||
|
||||
File file = getFile("fileParam").getFile();
|
||||
String finalFilePath = BASE_PATH + requestUploadDir;
|
||||
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
FileOutputStream fos = new FileOutputStream(finalFilePath);
|
||||
int i = 0;
|
||||
|
||||
do {
|
||||
byte[] buf = new byte[1024];
|
||||
i = fis.read(buf);
|
||||
fos.write(buf);
|
||||
} while (i != -1);
|
||||
|
||||
fis.close();
|
||||
fos.close();
|
||||
}
|
||||
|
||||
private void readFile(HttpServletResponse resp, File file) {
|
||||
OutputStream os = null;
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
os = resp.getOutputStream();
|
||||
fis = new FileInputStream(file);
|
||||
byte fileContent[] = new byte[(int) file.length()];
|
||||
fis.read(fileContent);
|
||||
os.write(fileContent);
|
||||
} catch (Exception e) {
|
||||
System.err.println("Invalid directory or file " + file.getName());
|
||||
} finally {
|
||||
try {
|
||||
if (os != null)
|
||||
os.close();
|
||||
} catch (Exception e2) {
|
||||
}
|
||||
try {
|
||||
if (fis != null)
|
||||
fis.close();
|
||||
} catch (Exception e2) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BAD: Download file to user specified path without validation
|
||||
public void downloadFile() throws FileNotFoundException, IOException {
|
||||
HttpServletRequest request = getRequest();
|
||||
String path = request.getParameter("path");
|
||||
String filePath = BASE_PATH + path;
|
||||
|
||||
HttpServletResponse resp = getResponse();
|
||||
File file = new File(filePath);
|
||||
if (path != null && file.exists()) {
|
||||
resp.setHeader("Content-type", "application/force-download");
|
||||
resp.setHeader("Content-Disposition", "inline;filename=\"" + filePath + "\"");
|
||||
resp.setHeader("Content-Transfer-Encoding", "Binary");
|
||||
resp.setHeader("Content-length", "" + file.length());
|
||||
resp.setHeader("Content-Type", "application/octet-stream");
|
||||
resp.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
|
||||
readFile(resp, file);
|
||||
} else {
|
||||
System.err.println("File does not exist " + path);
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: Download file with path validation
|
||||
public void downloadFile2() throws FileNotFoundException, IOException {
|
||||
HttpServletRequest request = getRequest();
|
||||
String path = request.getParameter("path");
|
||||
String filePath = BASE_PATH + path;
|
||||
|
||||
HttpServletResponse resp = getResponse();
|
||||
if (!filePath.contains("..") && filePath.startsWith(BASE_PATH)) {
|
||||
File file = new File(filePath);
|
||||
if (file.exists()) {
|
||||
resp.setHeader("Content-type", "application/force-download");
|
||||
resp.setHeader("Content-Disposition", "inline;filename=\"" + filePath + "\"");
|
||||
resp.setHeader("Content-Transfer-Encoding", "Binary");
|
||||
resp.setHeader("Content-length", "" + file.length());
|
||||
resp.setHeader("Content-Type", "application/octet-stream");
|
||||
resp.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
|
||||
readFile(resp, file);
|
||||
} else {
|
||||
System.err.println("File does not exist " + path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-073/FilePathInjection.ql
|
||||
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jfinal-4.9.15
|
||||
347
java/ql/test/stubs/jfinal-4.9.15/com/jfinal/core/Controller.java
generated
Normal file
347
java/ql/test/stubs/jfinal-4.9.15/com/jfinal/core/Controller.java
generated
Normal file
@@ -0,0 +1,347 @@
|
||||
package com.jfinal.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import com.jfinal.kit.Kv;
|
||||
import com.jfinal.upload.UploadFile;
|
||||
|
||||
public abstract class Controller {
|
||||
public String getPara(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPara(String name, String defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, String[]> getParaMap() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Enumeration<String> getParaNames() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String[] getParaValues(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer[] getParaValuesToInt(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long[] getParaValuesToLong(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Controller setAttr(String name, Object value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Controller setAttrs(Map<String, Object> attrMap) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Enumeration<String> getAttrNames() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T getAttr(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T getAttr(String name, T defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getAttrForStr(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getAttrForInt(String name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public String getHeader(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getParaToInt(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getParaToInt(String name, Integer defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long getParaToLong(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long getParaToLong(String name, Long defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Boolean getParaToBoolean(String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Boolean getParaToBoolean(String name, Boolean defaultValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Boolean getParaToBoolean() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Boolean getParaToBoolean(int index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Boolean getParaToBoolean(int index, Boolean defaultValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Date getParaToDate(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Date getParaToDate(String name, Date defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Date getParaToDate() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public HttpServletRequest getRequest() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public HttpServletResponse getResponse() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public HttpSession getSession() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public HttpSession getSession(boolean create) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T getSessionAttr(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T getSessionAttr(String key, T defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Controller setSessionAttr(String key, Object value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getCookie(String name, String defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getCookie(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getCookieToInt(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getCookieToInt(String name, Integer defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long getCookieToLong(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long getCookieToLong(String name, Long defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Cookie getCookieObject(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Cookie[] getCookieObjects() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPara() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPara(int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPara(int index, String defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getParaToInt(int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getParaToInt(int index, Integer defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long getParaToLong(int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long getParaToLong(int index, Long defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getParaToInt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long getParaToLong() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Kv getKv() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<UploadFile> getFiles(String uploadPath, Integer maxPostSize, String encoding) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public UploadFile getFile(String parameterName, String uploadPath, Integer maxPostSize, String encoding) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<UploadFile> getFiles(String uploadPath, int maxPostSize) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public UploadFile getFile(String parameterName, String uploadPath, int maxPostSize) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<UploadFile> getFiles(String uploadPath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public UploadFile getFile(String parameterName, String uploadPath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<UploadFile> getFiles() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public UploadFile getFile() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public UploadFile getFile(String parameterName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Controller set(String attributeName, Object attributeValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String get(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String get(String name, String defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getInt(String name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Integer getInt(String name, Integer defaultValue) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Long getLong(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long getLong(String name, Long defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String name, Boolean defaultValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Date getDate(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Date getDate(String name, Date defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String get(int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String get(int index, String defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getInt() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Integer getInt(int index) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Integer getInt(int index, Integer defaultValue) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Long getLong() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long getLong(int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long getLong(int index, Long defaultValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Boolean getBoolean() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Boolean getBoolean(int index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Boolean getBoolean(int index, Boolean defaultValue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
6
java/ql/test/stubs/jfinal-4.9.15/com/jfinal/kit/Kv.java
generated
Normal file
6
java/ql/test/stubs/jfinal-4.9.15/com/jfinal/kit/Kv.java
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.jfinal.kit;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Kv extends HashMap {
|
||||
}
|
||||
32
java/ql/test/stubs/jfinal-4.9.15/com/jfinal/upload/UploadFile.java
generated
Normal file
32
java/ql/test/stubs/jfinal-4.9.15/com/jfinal/upload/UploadFile.java
generated
Normal file
@@ -0,0 +1,32 @@
|
||||
package com.jfinal.upload;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class UploadFile {
|
||||
public UploadFile(String parameterName, String uploadPath, String filesystemName, String originalFileName, String contentType) {
|
||||
}
|
||||
|
||||
public String getParameterName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getOriginalFileName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getUploadPath() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user