Add file name validation

This commit is contained in:
Naoki Takezoe
2018-04-29 01:03:17 +09:00
parent c63c8d3cd2
commit eef01262bd
7 changed files with 57 additions and 27 deletions

View File

@@ -1,5 +1,7 @@
package gitbucket.core.controller
import java.io.File
import gitbucket.core.account.html
import gitbucket.core.helper
import gitbucket.core.model._
@@ -284,7 +286,9 @@ trait AccountControllerBase extends AccountManagementControllerBase {
response.setDateHeader("Last-Modified", account.updatedDate.getTime)
account.image
.map { image =>
Some(RawData(FileUtil.getMimeType(image), new java.io.File(getUserUploadDir(userName), image)))
Some(
RawData(FileUtil.getMimeType(image), new File(getUserUploadDir(userName), FileUtil.checkFilename(image)))
)
}
.getOrElse {
if (account.isGroupAccount) {

View File

@@ -1,6 +1,6 @@
package gitbucket.core.controller
import java.io.FileInputStream
import java.io.{File, FileInputStream}
import gitbucket.core.api.{ApiError, JsonFormat}
import gitbucket.core.model.Account
@@ -327,7 +327,7 @@ trait AccountManagementControllerBase extends ControllerBase {
protected def updateImage(userName: String, fileId: Option[String], clearImage: Boolean): Unit =
if (clearImage) {
getAccountByUserName(userName).flatMap(_.image).map { image =>
new java.io.File(getUserUploadDir(userName), image).delete()
new File(getUserUploadDir(userName), FileUtil.checkFilename(image)).delete()
updateAvatarImage(userName, None)
}
} else {
@@ -338,9 +338,9 @@ trait AccountManagementControllerBase extends ControllerBase {
uploadDir.mkdirs()
}
Thumbnails
.of(new java.io.File(getTemporaryDir(session.getId), fileId))
.of(new File(getTemporaryDir(session.getId), FileUtil.checkFilename(fileId)))
.size(324, 324)
.toFile(new java.io.File(uploadDir, filename))
.toFile(new File(uploadDir, FileUtil.checkFilename(filename)))
updateAvatarImage(userName, Some(filename))
}
}

View File

@@ -1,7 +1,9 @@
package gitbucket.core.controller
import java.io.File
import gitbucket.core.model.Account
import gitbucket.core.service.{AccountService, RepositoryService, ReleaseService}
import gitbucket.core.service.{AccountService, ReleaseService, RepositoryService}
import gitbucket.core.servlet.Database
import gitbucket.core.util._
import gitbucket.core.util.SyntaxSugars._
@@ -31,7 +33,8 @@ class FileUploadController
post("/image") {
execute(
{ (file, fileId) =>
FileUtils.writeByteArrayToFile(new java.io.File(getTemporaryDir(session.getId), fileId), file.get)
FileUtils
.writeByteArrayToFile(new File(getTemporaryDir(session.getId), FileUtil.checkFilename(fileId)), file.get)
session += Keys.Session.Upload(fileId) -> file.name
},
FileUtil.isImage
@@ -41,7 +44,8 @@ class FileUploadController
post("/tmp") {
execute(
{ (file, fileId) =>
FileUtils.writeByteArrayToFile(new java.io.File(getTemporaryDir(session.getId), fileId), file.get)
FileUtils
.writeByteArrayToFile(new File(getTemporaryDir(session.getId), FileUtil.checkFilename(fileId)), file.get)
session += Keys.Session.Upload(fileId) -> file.name
},
_ => true
@@ -52,9 +56,9 @@ class FileUploadController
execute(
{ (file, fileId) =>
FileUtils.writeByteArrayToFile(
new java.io.File(
new File(
getAttachedDir(params("owner"), params("repository")),
fileId + "." + FileUtil.getExtension(file.getName)
FileUtil.checkFilename(fileId + "." + FileUtil.getExtension(file.getName))
),
file.get
)
@@ -129,12 +133,15 @@ class FileUploadController
val owner = params("owner")
val repository = params("repository")
val tag = params("tag")
execute({ (file, fileId) =>
FileUtils.writeByteArrayToFile(
new java.io.File(getReleaseFilesDir(owner, repository), tag + "/" + fileId),
file.get
)
}, _ => true)
execute(
{ (file, fileId) =>
FileUtils.writeByteArrayToFile(
new File(getReleaseFilesDir(owner, repository), FileUtil.checkFilename(tag + "/" + fileId)),
file.get
)
},
_ => true
)
}
.getOrElse(BadRequest())
}

View File

@@ -80,7 +80,7 @@ trait ReleaseControllerBase extends ControllerBase {
response.setHeader("Content-Disposition", s"attachment; filename=${asset.label}")
RawData(
FileUtil.getMimeType(asset.label),
new File(getReleaseFilesDir(repository.owner, repository.name), tagName + "/" + fileId)
new File(getReleaseFilesDir(repository.owner, repository.name), FileUtil.checkFilename(tagName + "/" + fileId))
)
}).getOrElse(NotFound())
})
@@ -111,7 +111,10 @@ trait ReleaseControllerBase extends ControllerBase {
files.foreach {
case (fileId, fileName) =>
val size =
new java.io.File(getReleaseFilesDir(repository.owner, repository.name), tagName + "/" + fileId).length
new File(
getReleaseFilesDir(repository.owner, repository.name),
FileUtil.checkFilename(tagName + "/" + fileId)
).length
createReleaseAsset(repository.owner, repository.name, tagName, fileId, fileName, size, loginAccount)
}
@@ -153,15 +156,18 @@ trait ReleaseControllerBase extends ControllerBase {
files.foreach {
case (fileId, fileName) =>
val size =
new java.io.File(getReleaseFilesDir(repository.owner, repository.name), tagName + "/" + fileId).length
new File(
getReleaseFilesDir(repository.owner, repository.name),
FileUtil.checkFilename(tagName + "/" + fileId)
).length
createReleaseAsset(repository.owner, repository.name, tagName, fileId, fileName, size, loginAccount)
}
assets.foreach { asset =>
if (!files.exists { case (fileId, _) => fileId == asset.fileName }) {
val file = new java.io.File(
val file = new File(
getReleaseFilesDir(repository.owner, repository.name),
release.tag + "/" + asset.fileName
FileUtil.checkFilename(release.tag + "/" + asset.fileName)
)
FileUtils.forceDelete(file)
}
@@ -175,7 +181,9 @@ trait ReleaseControllerBase extends ControllerBase {
post("/:owner/:repository/releases/:tag/delete")(writableUsersOnly { repository =>
val tagName = params("tag")
getRelease(repository.owner, repository.name, tagName).foreach { release =>
FileUtils.deleteDirectory(new File(getReleaseFilesDir(repository.owner, repository.name), release.tag))
FileUtils.deleteDirectory(
new File(getReleaseFilesDir(repository.owner, repository.name), FileUtil.checkFilename(release.tag))
)
}
deleteRelease(repository.owner, repository.name, tagName)
redirect(s"/${repository.owner}/${repository.name}/releases")

View File

@@ -896,7 +896,8 @@ trait RepositoryViewerControllerBase extends ControllerBase {
}
newFiles.foreach { file =>
val bytes = FileUtils.readFileToByteArray(new File(getTemporaryDir(session.getId), file.id))
val bytes =
FileUtils.readFileToByteArray(new File(getTemporaryDir(session.getId), FileUtil.checkFilename(file.id)))
builder.add(
JGitUtil.createDirCacheEntry(file.name, FileMode.REGULAR_FILE, inserter.insert(Constants.OBJ_BLOB, bytes))
)

View File

@@ -7,7 +7,7 @@ import gitbucket.core.model.Profile._
import gitbucket.core.model.Profile.profile.blockingApi._
import gitbucket.core.model.Profile.dateColumnType
import gitbucket.core.util.Directory._
import gitbucket.core.util.StringUtil
import gitbucket.core.util.{FileUtil, StringUtil}
import org.apache.commons.io.FileUtils
trait CommitsService {
@@ -83,7 +83,7 @@ trait CommitsService {
newLine: Option[Int],
diffJson: String
): Unit = {
val dir = new java.io.File(getDiffDir(owner, repository), commitId)
val dir = new File(getDiffDir(owner, repository), FileUtil.checkFilename(commitId))
if (!dir.exists) {
dir.mkdirs()
}
@@ -99,7 +99,7 @@ trait CommitsService {
oldLine: Option[Int],
newLine: Option[Int]
): Option[String] = {
val dir = new java.io.File(getDiffDir(owner, repository), commitId)
val dir = new File(getDiffDir(owner, repository), FileUtil.checkFilename(commitId))
val file = diffFile(dir, fileName, oldLine, newLine)
if (file.exists) {
Option(FileUtils.readFileToString(file, "UTF-8"))

View File

@@ -52,7 +52,7 @@ object FileUtil {
}
def getLfsFilePath(owner: String, repository: String, oid: String): String =
Directory.getLfsDir(owner, repository) + "/" + oid
Directory.getLfsDir(owner, repository) + "/" + checkFilename(oid)
def readableSize(size: Long): String = FileUtils.byteCountToDisplaySize(size)
@@ -76,6 +76,16 @@ object FileUtil {
file
}
/**
* Create an instance of java.io.File safely.
*/
def checkFilename(name: String): String = {
if (name.contains("..")) {
throw new IllegalArgumentException(s"Invalid file name: ${name}")
}
name
}
lazy val MaxFileSize =
if (System.getProperty("gitbucket.maxFileSize") != null)
System.getProperty("gitbucket.maxFileSize").toLong