diff --git a/src/Services/Attachments/AttachmentSubmitHandler.php b/src/Services/Attachments/AttachmentSubmitHandler.php index 56613a58..6bfa3286 100644 --- a/src/Services/Attachments/AttachmentSubmitHandler.php +++ b/src/Services/Attachments/AttachmentSubmitHandler.php @@ -61,6 +61,10 @@ class AttachmentSubmitHandler protected MimeTypesInterface $mimeTypes; protected FileTypeFilterTools $filterTools; + protected const BLACKLISTED_EXTENSIONS = ['php', 'phtml', 'php3', 'ph3', 'php4', 'ph4', 'php5', 'ph5', 'phtm', 'sh', + 'asp', 'cgi', 'py', 'pl', 'exe', 'aspx', 'js', 'mjs', 'jsp', 'css', 'jar', 'html', 'htm', 'shtm', 'shtml', 'htaccess', + 'htpasswd', '']; + public function __construct(AttachmentPathResolver $pathResolver, bool $allow_attachments_downloads, HttpClientInterface $httpClient, MimeTypesInterface $mimeTypes, FileTypeFilterTools $filterTools) @@ -190,6 +194,9 @@ class AttachmentSubmitHandler //Move the attachment files to secure location (and back) if needed $this->moveFile($attachment, $options['secure_attachment']); + //Rename blacklisted (unsecure) files to a better extension + $this->renameBlacklistedExtensions($attachment); + //Check if we should assign this attachment to master picture //this is only possible if the attachment is new (not yet persisted to DB) if ($options['become_preview_if_empty'] && null === $attachment->getID() && $attachment->isPicture()) { @@ -202,6 +209,44 @@ class AttachmentSubmitHandler return $attachment; } + /** + * Rename attachments with an unsafe extension (meaning files which would be runned by a to a safe one. + * @param Attachment $attachment + * @return void + */ + protected function renameBlacklistedExtensions(Attachment $attachment): Attachment + { + //We can not do anything on builtins or external ressources + if ($attachment->isBuiltIn() || $attachment->isExternal()) { + return $attachment; + } + + //Determine the old filepath + $old_path = $this->pathResolver->placeholderToRealPath($attachment->getPath()); + if (!file_exists($old_path)) { + return $attachment; + } + $filename = basename($old_path); + $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); + + + //Check if the extension is blacklisted and replace the file extension with txt if needed + if(in_array($ext, self::BLACKLISTED_EXTENSIONS)) { + $new_path = $this->generateAttachmentPath($attachment, $attachment->isSecure()) + .DIRECTORY_SEPARATOR.$this->generateAttachmentFilename($attachment, 'txt'); + + //Move file to new directory + $fs = new Filesystem(); + $fs->rename($old_path, $new_path); + + //Update the attachment + $attachment->setPath($this->pathResolver->realPathToPlaceholder($new_path)); + } + + + return $attachment; + } + protected function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ diff --git a/templates/Parts/edit/edit_form_styles.html.twig b/templates/Parts/edit/edit_form_styles.html.twig index b31132c6..c0e12ed1 100644 --- a/templates/Parts/edit/edit_form_styles.html.twig +++ b/templates/Parts/edit/edit_form_styles.html.twig @@ -144,6 +144,7 @@ {% trans %}attachment.secure{% endtrans %} + {% endif %} {% if attach.secure and not is_granted('show_private', attach) %} {# Leave blank #} @@ -161,7 +162,7 @@ {% trans %}attachment.file_not_found{% endtrans %} - {% endif %} + {% endif %} {% endif %}