Improve attachment checks to ensure that a stream is actually a JAR/ZIP.

This commit is contained in:
Mike Hearn 2017-03-20 19:06:07 +01:00
parent 2cb02c75eb
commit 347224c900
2 changed files with 20 additions and 3 deletions

View File

@ -21,7 +21,9 @@ import net.corda.node.services.persistence.schemas.Models
import java.io.ByteArrayInputStream
import java.io.FilterInputStream
import java.io.InputStream
import java.nio.file.*
import java.nio.file.FileAlreadyExistsException
import java.nio.file.Path
import java.nio.file.Paths
import java.util.*
import java.util.jar.JarInputStream
import javax.annotation.concurrent.ThreadSafe
@ -159,14 +161,21 @@ class NodeAttachmentService(override var storePath: Path, dataSourceProperties:
private fun checkIsAValidJAR(stream: InputStream) {
// Just iterate over the entries with verification enabled: should be good enough to catch mistakes.
// Note that JarInputStream won't throw any kind of error at all if the file stream is in fact not
// a ZIP! It'll just pretend it's an empty archive, which is kind of stupid but that's how it works.
// So we have to check to ensure we found at least one item.
val jar = JarInputStream(stream)
var count = 0
while (true) {
val cursor = jar.nextJarEntry ?: break
val entryPath = Paths.get(cursor.name)
// Security check to stop zips trying to escape their rightful place.
if (entryPath.isAbsolute || entryPath.normalize() != entryPath || '\\' in cursor.name)
if (entryPath.isAbsolute || entryPath.normalize() != entryPath || '\\' in cursor.name || cursor.name == "." || cursor.name == "..")
throw IllegalArgumentException("Path is either absolute or non-normalised: $entryPath")
count++
}
if (count == 0)
throw IllegalArgumentException("Stream is either empty or not a JAR/ZIP")
}
// Implementations for AcceptsFileUpload

View File

@ -9,6 +9,7 @@ import net.corda.core.read
import net.corda.core.readAll
import net.corda.core.utilities.LogHelper
import net.corda.core.write
import net.corda.core.writeLines
import net.corda.node.services.database.RequeryConfiguration
import net.corda.node.services.persistence.NodeAttachmentService
import net.corda.node.services.persistence.schemas.AttachmentEntity
@ -86,7 +87,6 @@ class NodeAttachmentStorageTest {
@Test
fun `duplicates not allowed`() {
val testJar = makeTestJar()
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry())
testJar.read {
@ -126,6 +126,14 @@ class NodeAttachmentStorageTest {
}
}
@Test(expected = IllegalArgumentException::class)
fun `non jar rejected`() {
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry())
val path = fs.getPath("notajar")
path.writeLines(listOf("Hey", "there!"))
path.read { storage.importAttachment(it) }
}
private var counter = 0
private fun makeTestJar(): Path {
counter++