ENT-6508 - Prevent directory traversal from zip file names (#7085)

This commit is contained in:
Conal Smith 2022-02-25 15:51:49 +00:00 committed by GitHub
parent 4b29ad337b
commit 5f1e86c17c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 0 deletions

View File

@ -88,6 +88,9 @@ class NodeAttachmentService @JvmOverloads constructor(
while (true) {
val cursor = jar.nextJarEntry ?: break
// Security check to stop directory traversal from filename entry
require(!(cursor.name.contains("../"))) { "Bad character in ${cursor.name}" }
require(!(cursor.name.contains("..\\"))) { "Bad character in ${cursor.name}" }
if (manifestHasEntries && !allManifestEntries!!.remove(cursor.name)) extraFilesNotFoundInEntries.add(cursor)
val entryPath = Paths.get(cursor.name)
// Security check to stop zips trying to escape their rightful place.

View File

@ -46,14 +46,19 @@ import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.net.URL
import java.nio.charset.StandardCharsets
import java.nio.file.FileAlreadyExistsException
import java.nio.file.FileSystem
import java.nio.file.Path
import java.util.*
import java.util.jar.JarEntry
import java.util.jar.JarInputStream
import java.util.jar.JarOutputStream
import java.util.jar.Manifest
import kotlin.streams.toList
import kotlin.test.*
@ -788,6 +793,32 @@ class NodeAttachmentServiceTest {
}
}
@Test(timeout=300_000)
fun `attachments containing jar entries whose names expose malicious directory traversal are prevented`() {
fun createJarWithJarEntryTraversalAttack(jarEntryName: String): InputStream {
val byteArrayOutputStream = ByteArrayOutputStream()
JarOutputStream(byteArrayOutputStream, Manifest()).apply {
putNextEntry(JarEntry(jarEntryName))
write("some-text".toByteArray())
closeEntry()
close()
}
return ByteArrayInputStream(byteArrayOutputStream.toByteArray())
}
val traversalAttackJarWin = createJarWithJarEntryTraversalAttack("..\\attack")
val traversalAttackJarUnix = createJarWithJarEntryTraversalAttack("../attack")
assertFailsWith(IllegalArgumentException::class) {
NodeAttachmentService.checkIsAValidJAR(traversalAttackJarWin)
}
assertFailsWith(IllegalArgumentException::class) {
NodeAttachmentService.checkIsAValidJAR(traversalAttackJarUnix)
}
}
@Test(timeout=300_000)
fun `attachments can be queried by providing a intersection of signers using an EQUAL statement - EQUAL containing a single public key`() {
SelfCleaningDir().use { file ->