mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-24 02:38:50 +02:00
Rename unsafe file extensions of attachments to prevent XSS and server side code injection.
This commit is contained in:
parent
5ffd44466e
commit
14bbe3d6d6
2 changed files with 47 additions and 1 deletions
|
@ -61,6 +61,10 @@ class AttachmentSubmitHandler
|
||||||
protected MimeTypesInterface $mimeTypes;
|
protected MimeTypesInterface $mimeTypes;
|
||||||
protected FileTypeFilterTools $filterTools;
|
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,
|
public function __construct(AttachmentPathResolver $pathResolver, bool $allow_attachments_downloads,
|
||||||
HttpClientInterface $httpClient, MimeTypesInterface $mimeTypes,
|
HttpClientInterface $httpClient, MimeTypesInterface $mimeTypes,
|
||||||
FileTypeFilterTools $filterTools)
|
FileTypeFilterTools $filterTools)
|
||||||
|
@ -190,6 +194,9 @@ class AttachmentSubmitHandler
|
||||||
//Move the attachment files to secure location (and back) if needed
|
//Move the attachment files to secure location (and back) if needed
|
||||||
$this->moveFile($attachment, $options['secure_attachment']);
|
$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
|
//Check if we should assign this attachment to master picture
|
||||||
//this is only possible if the attachment is new (not yet persisted to DB)
|
//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()) {
|
if ($options['become_preview_if_empty'] && null === $attachment->getID() && $attachment->isPicture()) {
|
||||||
|
@ -202,6 +209,44 @@ class AttachmentSubmitHandler
|
||||||
return $attachment;
|
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
|
protected function configureOptions(OptionsResolver $resolver): void
|
||||||
{
|
{
|
||||||
$resolver->setDefaults([
|
$resolver->setDefaults([
|
||||||
|
|
|
@ -144,6 +144,7 @@
|
||||||
<i class="fas fa-fw fa-shield-alt"></i> {% trans %}attachment.secure{% endtrans %}
|
<i class="fas fa-fw fa-shield-alt"></i> {% trans %}attachment.secure{% endtrans %}
|
||||||
</span>
|
</span>
|
||||||
</h6>
|
</h6>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if attach.secure and not is_granted('show_private', attach) %}
|
{% if attach.secure and not is_granted('show_private', attach) %}
|
||||||
{# Leave blank #}
|
{# Leave blank #}
|
||||||
|
@ -161,7 +162,7 @@
|
||||||
<i class="fas fa-exclamation-circle fa-fw"></i> {% trans %}attachment.file_not_found{% endtrans %}
|
<i class="fas fa-exclamation-circle fa-fw"></i> {% trans %}attachment.file_not_found{% endtrans %}
|
||||||
</span>
|
</span>
|
||||||
</h6>
|
</h6>
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue