Copying Windows file permissions in Lucee
There is a currently unresolved regression bug in Lucee affecting file uploads, which is worth being aware of.
When you upload a file using Lucee it isn't saved directly to the destination
path, but is first stored in the server's GetTempDirectory()
location before being moved to where you've specified it should be.
(Update 7 July 2021: Charlie Arehart has a useful explanation of the basic mechanics of file uploading in CFML.)
Having this intermediate step is good for security as it allows the OS to detect viruses before the file is placed anywhere it might do damage.
Inherited permissions
Prior to Lucee 5.3.4.4, an uploaded file would inherit the destination
directory's permissions, as you would expect. But thereafter that stopped happening and the file instead keeps the permissions of the GetTempDirectory()
path.
This means, for example, that if you upload an image to a directory with web server read permissions, the new file won't in fact be readable by the web server, unless the GetTempDirectory()
path also has that permission.
Security checks
Of course, using a web accessible upload destination isn't good security practice anyway. Alongside the anti-malware detection mentioned above, other safety checks such as IsImageFile()
and other MIME type checking should first be performed in code. Again this needs doing in an intermediate location not accessible to the web, after which the file can be moved to its public destination.
So the recommended workflow is:
- Upload the file using
FileUpload()
or equivalent, specifying an intermediate, protecteddestination
path. - Lucee will first save the file to the
GetTempDirectory()
path and then move it to yourdestination
. - Perform your MIME checks on the file while it's in the intermediate location.
- Finally,
FileMove()
the file to its final destination.
Setting the permissions
But how do you ensure the file has the right permissions for that final location?
I'm not a Linux user, but if you are on that platform Lucee has a built-in function FileSetAccessMode() which I assume will allow you to control file permissions.
Unfortunately there is no Windows equivalent, but if we drop down to java there are tools we can use to achieve what we want fairly easily.
The following UDF can be used with an uploaded file once it's been security checked and moved to its final location to ensure it has the permissions of its parent (containing) directory.
public void function copyParentDirectoryPermissions( required string filePath, required string parentDirectoryPath ){
//built-in Java classes with required static methods
var Paths = CreateObject( "java", "java.nio.file.Paths" );
var Files = CreateObject( "java", "java.nio.file.Files" );
var aclViewClass = CreateObject( "java", "java.nio.file.attribute.AclFileAttributeView" ).getClass();
//create "path" java objects to work with
var parentFolderPath = Paths.get( JavaCast( "string", arguments.parentDirectoryPath ), [] );
var filePath = Paths.get( JavaCast( "string", arguments.filePath ), [] );
//create "views" of the respective ACLs
var parentFolderAclView = Files.getFileAttributeView( parentFolderPath, aclViewClass, [] );
var fileAclView = Files.getFileAttributeView( filePath, aclViewClass, [] );
//copy the folder ACL to the file
fileAclView.setAcl( parentFolderAclView.getAcl() );
}
Comments