Skip to content
Permalink
Browse files Browse the repository at this point in the history
[DS-4132] JPSUI resumable upload dir validation
  • Loading branch information
kshepherd committed Jul 26, 2022
1 parent c89e493 commit d1dd7d2
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 8 deletions.
Expand Up @@ -217,7 +217,7 @@ else if (!StringUtils.isEmpty(resumableFilename)) // if resumable.js asks whethe
{
if (request.getMethod().equals("GET"))
{
DoGetResumable(request, response);
DoGetResumable(context, request, response);
}
}
else
Expand Down Expand Up @@ -1568,27 +1568,38 @@ public void uploadFiles(Context context, HttpServletRequest request)

// Resumable.js uses HTTP Get to recognize whether a specific part/chunk of
// a file was uploaded already. This method handles those requests.
protected void DoGetResumable(HttpServletRequest request, HttpServletResponse response)
protected void DoGetResumable(Context context, HttpServletRequest request, HttpServletResponse response)
throws IOException
{
String baseDir;

if (ConfigurationManager.getProperty("upload.temp.dir") != null)
{
tempDir = ConfigurationManager.getProperty("upload.temp.dir");
baseDir = ConfigurationManager.getProperty("upload.temp.dir");
}
else
{
tempDir = System.getProperty("java.io.tmpdir");
baseDir = System.getProperty("java.io.tmpdir");
}

String resumableIdentifier = request.getParameter("resumableIdentifier");
String resumableChunkNumber = request.getParameter("resumableChunkNumber");
long resumableCurrentChunkSize =
Long.valueOf(request.getParameter("resumableCurrentChunkSize"));

tempDir = tempDir + File.separator + resumableIdentifier;
tempDir = baseDir + File.separator + resumableIdentifier;

File fileDir = new File(tempDir);

// Test fileDir to see if canonical path is within the original baseDir
if(!fileDir.getCanonicalPath().startsWith(baseDir)) {
log.error("Error processing resumable upload chunk: temporary chunk file would be created outside " +
"permissible temp dir ("+ baseDir +") for submitter: " + context.getCurrentUser().getEmail());
throw new IOException("Error processing resumableIdentifier: " + resumableIdentifier +
" (submitter: " + context.getCurrentUser().getEmail() + ")" +
". Temporary upload directory would be created outside permissible base temp dir ("+ baseDir +")");
}

// create a new directory for each resumableIdentifier
if (!fileDir.exists()) {
fileDir.mkdir();
Expand All @@ -1597,6 +1608,16 @@ protected void DoGetResumable(HttpServletRequest request, HttpServletResponse re
String chunkPath = tempDir + File.separator + "part" + resumableChunkNumber;

File chunkFile = new File(chunkPath);

// Test chunkFile to see if canonical path is within the original baseDir
if(!chunkFile.getCanonicalPath().startsWith(baseDir)) {
log.error("Error processing resumable upload chunk: temporary chunk file would be created outside " +
"permissible temp dir ("+ baseDir +") for submitter: " + context.getCurrentUser().getEmail());
throw new IOException("Error processing resumableIdentifier: " + resumableIdentifier +
" (submitter: " + context.getCurrentUser().getEmail() + ")" +
". Temporary upload directory would be created outside permissible base temp dir ("+ baseDir +")");
}

// if the chunk was uploaded already, we send a status code of 200
if (chunkFile.exists()) {
if (chunkFile.length() == resumableCurrentChunkSize) {
Expand Down
Expand Up @@ -21,6 +21,7 @@
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dspace.core.ConfigurationManager;

/**
Expand All @@ -44,6 +45,10 @@ public class FileUploadRequest extends HttpServletRequestWrapper

private String tempDir = null;

/** log4j logger */
private static Logger log = Logger
.getLogger(FileUploadRequest.class);

/** Original request */
private HttpServletRequest original = null;

Expand Down Expand Up @@ -102,8 +107,18 @@ public FileUploadRequest(HttpServletRequest req) throws IOException, FileSizeLim
{
String chunkDirPath = tempDir + File.separator + parameters.get("resumableIdentifier");
String chunkPath = chunkDirPath + File.separator + "part" + parameters.get("resumableChunkNumber");

File fileDir = new File(chunkDirPath);


// Test fileDir to see if canonical path is within the original tempDir
if(!fileDir.getCanonicalPath().startsWith(tempDir)) {
log.error("Error processing resumable upload chunk: temporary chunk file would be created outside " +
"permissible temp dir ("+ tempDir +") for file: " + filename);
throw new IOException("Error processing resumable chunk directory " + chunkDirPath +
" (filename: " + filename + ")" +
". Temporary upload directory would be created outside permissible base temp dir ("+ tempDir +")");
}

if(fileDir.exists())
{
item.write(new File(chunkPath));
Expand All @@ -119,8 +134,17 @@ public FileUploadRequest(HttpServletRequest req) throws IOException, FileSizeLim
String filename = getFilename(item.getName());
if (filename != null && !"".equals(filename))
{
item.write(new File(tempDir + File.separator
+ filename));
File fileDir = new File(tempDir + File.separator+ filename);
// Test fileDir to see if canonical path is within the original tempDir
if(!fileDir.getCanonicalPath().startsWith(tempDir)) {
log.error("Error processing resumable upload chunk: temporary chunk file would be created outside " +
"permissible temp dir ("+ tempDir +") for file: " + filename);
throw new IOException("Error processing resumable chunk directory " + fileDir +
" (filename: " + filename + ")" +
". Temporary upload directory would be created outside permissible base temp dir ("+ tempDir +")");
}

item.write(fileDir);
}
}
}
Expand Down

0 comments on commit d1dd7d2

Please sign in to comment.